Я как-то очень плотно сейчас погружаюсь в линейную алгебру (векторы, матрицы, спуски) и не сильно способен разбирать новые сложные темы в Solidity. Поэтому сейчас будут более простые темы, которые подойдет и для начинающих.
У нас ранее был цикл постов по материалам Chinmaya, где он делал список пунктов, на которые следует обратить внимание при разработке. Вот думаю продолжить некоторое время делать небольшие разборы.
Сегодня давайте посмотрим на пункт 44:
Library functions can only be called directly (i.e. without the use of DELEGATECALL ) if they do not modify the state (view or pure)
что в переводе:
Функции библиотек могут быть вызваны напрямую (без использования delegatecall), если они не изменяют состояние смарт контракта.
А теперь чуть подробнее.
В Solidity библиотеки (libraries, а не набор контрактов, типа Open Zeppelin) представляют собой наборы функций, которые можно повторно использовать в разных контрактах. Тут важно понимать, как именно вызываются их функции, особенно если они взаимодействуют с состоянием контракта.
Функции библиотек могут быть вызваны напрямую только в том случае, если они не модифицируют состояние блокчейна, то есть помечены как view или pure. Это связано с тем, что библиотеки по умолчанию не хранят собственное состояние и выполняются в контексте вызывающего контракта.
Когда функция библиотеки вызывается напрямую (например, MyLibrary.doSomething()), код выполняется в контексте вызывающего контракта, но без изменения его хранилища (storage). Если бы библиотека могла изменять состояние при таком вызове, это привело бы к неоднозначности: откуда брать storage для записи? Поэтому Solidity запрещает вызов не-view/не-pure функций библиотек без использования DELEGATECALL, который явно указывает, что изменения должны применяться к storage вызывающего контракта.
Если функция библиотеки должна изменять состояние, её вызов должен происходить через DELEGATECALL. На практике это означает, что библиотеку нужно внедрить в контракт с помощью using ... for, а затем вызывать её методы для конкретных переменных. Например:
library Math {
function increment(uint256 storage num) external {
num += 1;
}
}
contract MyContract {
using Math for uint256;
uint256 public counter;
function increase() public {
counter.increment(); // Вызов через DELEGATECALL
}
}Здесь increment изменяет storage контракта, поэтому вызывается через механизм DELEGATECALL.
Понимание этого механизма поможет избежать ошибок при разработке смарт-контрактов.
#libraries