Увеличивает ли наличие отдельного договора на хранение стоимость газа при совершении сделки?

Я много читал об обновлении смарт-контрактов, и кажется, что основная преобладающая практика заключается в том, что, как правило, хорошей идеей является отделение логики контракта от хранилища контрактов, поэтому можно обновить один и не нужно менять другой.

Мой вопрос заключается в следующем: увеличивает ли тот факт, что один контракт должен вызывать другой контракт, количество газа, которое тратится по этой логике. Например, предположим, что у меня есть контракт, который ищет число X, а затем добавляет его к числу 5.

В одном случае контракт хранится в самом X, поэтому он может напрямую искать его. В другом случае отдельный контракт отвечает за хранение X, в результате чего один контракт выполняет вызов функции для получения X. Стоит ли один больше газа? Если да, то можно ли сказать, сколько еще?

Спасибо!

Ответы (2)

Да, но рекомендуется учитывать компромиссы, связанные с увеличением стоимости газа, с возможностью модернизации, которую он обеспечивает для вашего приложения.

Большинство обновляемых контрактов будут включать библиотеки и код операции DELEGATECALL, а некоторые затраты описаны в части документации Solidity по библиотекам :

Библиотеки можно рассматривать как неявные базовые контракты контрактов, которые их используют. Они не будут явно видны в иерархии наследования, но вызовы библиотечных функций выглядят так же, как вызовы функций явных базовых контрактов (Lf(), если L — имя библиотеки). Кроме того, внутренние функции библиотек видны во всех контрактах, как если бы библиотека была базовым контрактом. Конечно, вызовы внутренних функций используют внутреннее соглашение о вызовах, что означает, что все внутренние типы могут передаваться, а типы памяти будут передаваться по ссылке, а не копироваться. Чтобы реализовать это в EVM, код внутренних библиотечных функций (и всех вызываемых из них функций) будет подтянут в вызывающий контракт, а вместо DELEGATECALL будет использоваться обычный вызов JUMP.

По сути, когда все находится в контракте, он может использовать ссылки, избегать копий и использовать код операции JUMP.

Когда задействованы внешние контракты, DELEGATECALL намного дороже, чем JUMP (в настоящее время 700 газа против 10 газа), и есть другие затраты, такие как копирование данных.

Но важно также профилировать конкретный вариант использования и сравнивать. Для простого примера, приведенного выше, стоимость CALL/DELEGATECALL была бы огромной. Но в других случаях эти дополнительные затраты на газ могут иметь гораздо меньшее влияние в целом.

Вы заставили меня уклониться от ответа «Нет» ... Я думаю, что да, затраты на вычисления выше, но, поскольку мы говорим о хранилище, стоимость вычислений в большинстве случаев затмевается стоимостью изменения состояния. В случае чтения местные звонки не требуют расходов на газ.
@RobHitchens Я думаю, что ваш ответ хорош, и я бы проголосовал за него: мы представляем разные соображения и точки зрения, и я не вижу большого несоответствия. (Я согласен, что ранние ответы могут повлиять на дополнительные: не знаю, как его уменьшить; извините, что это заставило уклониться, особенно такой хорошо написанный ответ, как ваш.)

Я бы сказал да, немного, но в большинстве случаев это не так уж важно. Помимо единовременных затрат на развертывание, для каждой транзакции будет выполняться дополнительный код. Это не бесплатно, но в большинстве случаев дополнительный код не будет особенно дорогим в эксплуатации.

Посмотрите стоимость газа за операцию (без гарантии): https://docs.google.com/spreadsheets/d/15wghZr-Z6sRSMdmRmhls9dVXTOpxKy8Y64oy9MvDZEQ/edit#gid=0 .

Базовая эвристика заключается в том, что коды операций изменения состояния (например, SSTORE) довольно высоки по сравнению с кодами операций вычисления, которые не изменяют блокчейн. Как правило, можно добавить дополнительные недорогие служебные шаги (например, поиск адреса контракта и формирование сообщения) без значительного увеличения общей стоимости изменения состояния. Смена состояния в любом случае обойдется дорого.

Операции чтения часто обрабатываются постоянными функциями или локальными вызовами, которые вообще не используют газ . Таким образом, проблемы транзакционных издержек обычно ограничиваются транзакциями, которые приведут к изменению состояния. Таким образом, создание/вставка, обновление и удаление имеют свою стоимость (львиная доля таких операций, как SSTORE). Чтения обычно бесплатны независимо от сложности. Также учтите, что многие системы используют офчейн-хранилище, питаемое генераторами событий, которые сохраняют копию «официальных» фактов из соображений производительности. Еще один пример ситуации, в которой вообще имеет значение только стоимость обновлений.

Чтобы поэкспериментировать с конкретным примером и сравнить затраты, вы можете закодировать репрезентативные функции в обоих направлениях и сравнить фактическое потребление газа. Компилятор Solidity Realtime покажет байт-код после компиляции. Вы можете пройтись по исходному коду, чтобы увидеть, какие фактические шаги являются «дорогостоящими», и соответствующим образом оптимизировать.

В качестве примечания: остерегайтесь скрытых затрат на дополнительную сложность. Хотя обновляемые контракты выгодны во многих отношениях, существует ряд компромиссов, подобных инь-ян, которые необходимо учитывать для каждого варианта использования. Например, возможность обновления в некоторых случаях может снизить надежность и потенциально может стать новым источником ошибок.

Надеюсь, это полезно.

Как отмечено в ответе ниже, стоимость газа составляет 700 за вызов библиотеки по сравнению с 10 для операции JUMP.