Лучшие практики оптимизации газа для смарт-контрактов Ethereum
Газовые сборы в главной сети Ethereum всегда были сложной проблемой, особенно это становится очевидным во время перегрузок сети. В пиковые часы пользователи часто вынуждены платить высокие комиссии за транзакции. Поэтому оптимизация газовых сборов на этапе разработки смарт-контрактов является ключевым моментом. Оптимизация потребления газа не только эффективно снижает затраты на транзакции, но и повышает эффективность сделок, предоставляя пользователям более экономичный и эффективный опыт использования блокчейна.
В данной статье будет рассмотрена механика Gas-费 Эфира (EVM), ключевые концепции оптимизации Gas-费, а также лучшие практики оптимизации Gas-费 при разработке смарт-контрактов. Надеемся, что эти материалы вдохновят разработчиков и окажут практическую помощь, а также помогут обычным пользователям лучше понять, как функционируют Gas-费 в EVM, чтобы совместно справляться с вызовами в экосистеме блокчейна.
Введение в механизм газовых сборов EVM
В совместимых с EVM сетях "Gas" обозначает единицу, используемую для измерения вычислительной мощности, необходимой для выполнения определенных операций.
В структуре EVM потребление газа делится на три части: выполнение операций, вызов внешних сообщений и чтение/запись в память и хранилище.
Поскольку выполнение каждой транзакции требует вычислительных ресурсов, взимается определенная плата, чтобы предотвратить бесконечные циклы и атаки отказа в обслуживании ( DoS ). Плата, необходимая для завершения транзакции, называется "Gas 费".
С момента вступления в силу EIP-1559, Gas-расходы рассчитываются по следующей формуле:
Газовая плата = количество использованного газа * (базовая плата + приоритетная плата)
Базовый сбор будет уничтожен, а сборы приоритетного характера будут использоваться в качестве стимула, чтобы побудить валидаторов добавлять транзакции в блокчейн. Установка более высокой приоритетной платы при отправке транзакции может увеличить вероятность того, что транзакция будет включена в следующий блок. Это похоже на "чаевые", которые пользователи платят валидаторам.
1. Понимание оптимизации газа в EVM
Когда вы компилируете смарт-контракт с помощью Solidity, контракт преобразуется в серию "операционных кодов", то есть opcodes.
Любая команда операции (, такая как создание смарт-контракта, вызов сообщений, доступ к хранилищу аккаунта и выполнение операций на виртуальной машине ), имеет признанную стоимость потребления газа, которая зафиксирована в желтой книге Ethereum.
После нескольких изменений EIP, некоторые коды операций были скорректированы, что может отличаться от желтой книги.
2.Основные концепции оптимизации газа
Основная идея оптимизации Gas заключается в том, чтобы в блокчейне EVM приоритетно выбирать операции с высокойCost-эффективностью и избегать операций с дорогими затратами Gas.
В EVM следующие операции имеют низкую стоимость:
Чтение и запись переменных памяти
Чтение констант и неизменяемых переменных
Чтение и запись локальных переменных
Чтение переменных calldata, таких как массивы и структуры calldata
Вызов внутренних функций
Операции с высокой стоимостью включают:
Чтение и запись состояния переменных, хранящихся в смарт-контрактах
Вызов внешних функций
Циклическая операция
Оптимизация Gas-расходов EVM: лучшие практики
Основываясь на вышеприведенных основных концепциях, мы составили список лучших практик оптимизации Gas для сообщества разработчиков. Следуя этим практикам, разработчики могут снизить потребление Gas смарт-контрактами, уменьшить транзакционные расходы и создать более эффективные и удобные для пользователей приложения.
1. Постарайтесь уменьшить использование хранилища
В Solidity хранилище ( хранение ) является ограниченным ресурсом, его потребление газа значительно выше, чем у памяти (. Каждый раз, когда смарт-контракт читает или записывает данные из хранилища, возникают высокие расходы на газ.
Согласно определению из «жёлтой книги» Ethereum, стоимость операций хранения более чем в 100 раз выше, чем стоимость операций с памятью. Например, команды OPcodesmload и mstore потребляют всего 3 единицы газа, в то время как операции хранения, такие как sload и sstore, даже в самых идеальных условиях, стоят как минимум 100 единиц.
Методы ограничения использования хранения включают:
Хранить непостоянные данные в памяти
Уменьшение количества изменений в хранении: сохраняйте промежуточные результаты в памяти и только после завершения всех вычислений распределяйте результаты переменным хранения.
![Ethereum смарт-контрактов Gas оптимизация десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-b237228ebe933741fb60f2e8bcb38405.webp(
) 2. Упаковка переменных
Количество хранилищ, используемых в смарт-контрактах, таких как Storage slot###, и способ, которым разработчик представляет данные, существенно влияют на потребление Gas.
Компилятор Solidity упаковывает последовательные переменные хранения в процессе компиляции и использует 32-байтный слот хранения в качестве базовой единицы хранения переменных. Упаковка переменных означает разумное размещение переменных, чтобы несколько переменных могли поместиться в одном слоте хранения.
С помощью этого изменения детали разработчики могут сэкономить 20 000 единиц газа. Хранение неиспользуемого слота памяти требует 20 000 газа, но теперь необходимо всего два слота памяти.
Поскольку каждый слот хранения потребляет Gas, упаковка переменных оптимизирует использование Gas за счет уменьшения количества необходимых слотов хранения.
( 3. Оптимизация типов данных
Переменная может представляться различными типами данных, но стоимость операций, соответствующих разным типам данных, также различна. Выбор подходящего типа данных помогает оптимизировать использование Gas.
Например, в Solidity целые числа могут быть разбиты на разные размеры: uint8, uint16, uint32 и т.д. Поскольку EVM выполняет операции с единицами в 256 бит, использование uint8 означает, что EVM сначала должна преобразовать его в uint256, и это преобразование потребует дополнительных затрат на Gas.
С точки зрения отдельных аспектов, здесь использование uint256 дешевле, чем uint8. Однако, если использовать предложенную ранее оптимизацию упаковки переменных, все будет иначе. Если разработчик сможет упаковать четыре переменные uint8 в один слот хранения, общая стоимость их итерации будет ниже, чем у четырех переменных uint256. Таким образом, смарт-контракт сможет считывать и записывать в один слот хранения и помещать четыре переменные uint8 в память/хранение за одну операцию.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-995905cb414526d4d991899d0c2e6443.webp(
) 4. Используйте переменные фиксированного размера вместо динамических переменных
Если данные могут быть ограничены 32 байтами, рекомендуется использовать тип данных bytes32 вместо bytes или strings. Как правило, переменные фиксированного размера потребляют меньше газа, чем переменные переменного размера. Если длину байтов можно ограничить, старайтесь выбирать минимальную длину от bytes1 до bytes32.
![Оптимизация Gas для смарт-контрактов Ethereum: 10 лучших практик]###https://img-cdn.gateio.im/webp-social/moments-55fcdb765912ef9cd238c46b1d248cff.webp(
) 5. Отображения и массивы
Списки данных Solidity могут быть представлены двумя типами данных: массивами ### Arrays ( и отображениями ) Mappings ###, но их синтаксис и структура совершенно разные.
В большинстве случаев отображения более эффективны и менее затратны, но массивы имеют итеративность и поддерживают упаковку типов данных. Поэтому рекомендуется при управлении списком данных отдавать предпочтение отображениям, если не требуется итерация или можно оптимизировать расход газа за счет упаковки типов данных.
( 6. Используйте calldata вместо memory
Переменные, объявленные в параметрах функции, могут храниться в calldata или memory. Основное отличие между ними заключается в том, что memory может быть изменен функцией, в то время как calldata неизменен.
Запомните этот принцип: если параметры функции только для чтения, следует предпочесть использование calldata, а не memory. Это позволяет избежать ненужных операций копирования из calldata функции в memory.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-9c566626ab499ef65d6f5089a2876ad3.webp(
) 7. Используйте ключевые слова Constant/Immutable по возможности
Постоянные/неизменяемые переменные не хранятся в хранилище контракта. Эти переменные вычисляются во время компиляции и хранятся в байт-коде контракта. Поэтому их стоимость доступа намного ниже по сравнению с хранилищем, и рекомендуется использовать ключевые слова Constant или Immutable по возможности.
![Ethereum смарт-контрактов Gas оптимизация десяти лучших практик]###https://img-cdn.gateio.im/webp-social/moments-c0701f9e09280a1667495d54e262dd2f.webp(
) 8. Используйте Unchecked, чтобы гарантировать, что не произойдет переполнение/недостаток.
Когда разработчики могут убедиться, что арифметические операции не приведут к переполнению или недостатку, они могут использовать ключевое слово unchecked, введенное в Solidity v0.8.0, чтобы избежать избыточных проверок на переполнение или недостаток, тем самым экономя Gas.
Кроме того, компиляторы версии 0.8.0 и выше больше не требуют использования библиотеки SafeMath, так как сам компилятор уже встроил функции защиты от переполнения и недостатка.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик]###https://img-cdn.gateio.im/webp-social/moments-a823fb7761aafa6529a6c45304e0314b.webp(
) 9. Оптимизация модификатора
Код модификатора встраивается в измененную функцию, и каждый раз при использовании модификатора его код копируется. Это увеличивает размер байт-кода и повышает потребление Gas.
Путем реорганизации логики в внутреннюю функцию _checkOwner###(, позволяя повторно использовать эту внутреннюю функцию в модификаторе, можно уменьшить размер байт-кода и снизить стоимость газа.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-839b91e2f02389949aa698d460a497d8.webp###
( 10. Оптимизация короткого замыкания
Для || и && операторов логические операции будут выполнять короткое замыкание, то есть если первое условие уже может определить результат логического выражения, второе условие не будет оцениваться.
Чтобы оптимизировать потребление газа, условия с низкой стоимостью вычислений следует ставить впереди, чтобы потенциально избежать дорогостоящих вычислений.
![Оптимизация газа смарт-контрактов Ethereum: 10 лучших практик])https://img-cdn.gateio.im/webp-social/moments-a141884dcdcdc56faff12eee2601b7b7.webp(
Дополнительные общие рекомендации
) 1. Удалить бесполезный код
Если в контракте есть неиспользуемые функции или переменные, рекомендуется их удалить. Это самый прямой способ снизить стоимость развертывания контракта и сохранить его небольшой объем.
Вот несколько полезных советов:
Используйте самые эффективные алгоритмы для вычислений. Если в смарт-контракте используются результаты некоторых вычислений напрямую, то следует удалить эти избыточные вычислительные процессы. По сути, любые неиспользуемые вычисления должны быть удалены.
В Ethereum разработчики могут получить вознаграждение за газ, освободив место для хранения. Если переменная больше не нужна, следует использовать ключевое слово delete для ее удаления или установить ее на значение по умолчанию.
Оптимизация циклов: избегайте затратных операций в циклах, по возможности объединяйте циклы и выносите повторные вычисления за пределы тела цикла.
2. Использование предопределенных смарт-контрактов
Предварительно скомпилированные контракты предоставляют сложные библиотечные функции, такие как операции шифрования и хеширования. Поскольку код выполняется не на EVM, а локально на клиентском узле, требуется меньше газа. Использование предварительно скомпилированных контрактов позволяет сэкономить газ, уменьшая объем вычислительных затрат, необходимых для выполнения смарт-контрактов.
Примеры предкомпилированных смарт-контрактов включают алгоритм цифровой подписи эллиптической кривой (ECDSA) и хэш-алгоритм SHA2-256. Используя эти предкомпилированные смарт-контракты в смарт-контрактах, разработчики могут снизить затраты на газ и повысить эффективность работы приложений.
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
19 Лайков
Награда
19
8
Репост
Поделиться
комментарий
0/400
SerumDegen
· 07-23 04:02
лmao газ высасывает мой кошелек до дна... реkt аф
Посмотреть ОригиналОтветить0
WalletDivorcer
· 07-21 18:08
С руками можно оптимизировать контракт.
Посмотреть ОригиналОтветить0
ProofOfNothing
· 07-20 15:12
Газ без денег о чем говорить
Посмотреть ОригиналОтветить0
AlphaBrain
· 07-20 04:31
Ладно, не хочу оптимизировать Газ, пойду на L2.
Посмотреть ОригиналОтветить0
ImpermanentLossEnjoyer
· 07-20 04:29
Кто еще помнит ужасный случай с транзакцией на 2000u?
Посмотреть ОригиналОтветить0
OvertimeSquid
· 07-20 04:19
Чтобы провести сделку, нужно погасить ипотеку, верно?
Гид по оптимизации Gas-стоимости смарт-контрактов Ethereum: десять лучших практик и советов
Лучшие практики оптимизации газа для смарт-контрактов Ethereum
Газовые сборы в главной сети Ethereum всегда были сложной проблемой, особенно это становится очевидным во время перегрузок сети. В пиковые часы пользователи часто вынуждены платить высокие комиссии за транзакции. Поэтому оптимизация газовых сборов на этапе разработки смарт-контрактов является ключевым моментом. Оптимизация потребления газа не только эффективно снижает затраты на транзакции, но и повышает эффективность сделок, предоставляя пользователям более экономичный и эффективный опыт использования блокчейна.
В данной статье будет рассмотрена механика Gas-费 Эфира (EVM), ключевые концепции оптимизации Gas-费, а также лучшие практики оптимизации Gas-费 при разработке смарт-контрактов. Надеемся, что эти материалы вдохновят разработчиков и окажут практическую помощь, а также помогут обычным пользователям лучше понять, как функционируют Gas-费 в EVM, чтобы совместно справляться с вызовами в экосистеме блокчейна.
Введение в механизм газовых сборов EVM
В совместимых с EVM сетях "Gas" обозначает единицу, используемую для измерения вычислительной мощности, необходимой для выполнения определенных операций.
В структуре EVM потребление газа делится на три части: выполнение операций, вызов внешних сообщений и чтение/запись в память и хранилище.
Поскольку выполнение каждой транзакции требует вычислительных ресурсов, взимается определенная плата, чтобы предотвратить бесконечные циклы и атаки отказа в обслуживании ( DoS ). Плата, необходимая для завершения транзакции, называется "Gas 费".
С момента вступления в силу EIP-1559, Gas-расходы рассчитываются по следующей формуле:
Газовая плата = количество использованного газа * (базовая плата + приоритетная плата)
Базовый сбор будет уничтожен, а сборы приоритетного характера будут использоваться в качестве стимула, чтобы побудить валидаторов добавлять транзакции в блокчейн. Установка более высокой приоритетной платы при отправке транзакции может увеличить вероятность того, что транзакция будет включена в следующий блок. Это похоже на "чаевые", которые пользователи платят валидаторам.
1. Понимание оптимизации газа в EVM
Когда вы компилируете смарт-контракт с помощью Solidity, контракт преобразуется в серию "операционных кодов", то есть opcodes.
Любая команда операции (, такая как создание смарт-контракта, вызов сообщений, доступ к хранилищу аккаунта и выполнение операций на виртуальной машине ), имеет признанную стоимость потребления газа, которая зафиксирована в желтой книге Ethereum.
После нескольких изменений EIP, некоторые коды операций были скорректированы, что может отличаться от желтой книги.
2.Основные концепции оптимизации газа
Основная идея оптимизации Gas заключается в том, чтобы в блокчейне EVM приоритетно выбирать операции с высокойCost-эффективностью и избегать операций с дорогими затратами Gas.
В EVM следующие операции имеют низкую стоимость:
Операции с высокой стоимостью включают:
Оптимизация Gas-расходов EVM: лучшие практики
Основываясь на вышеприведенных основных концепциях, мы составили список лучших практик оптимизации Gas для сообщества разработчиков. Следуя этим практикам, разработчики могут снизить потребление Gas смарт-контрактами, уменьшить транзакционные расходы и создать более эффективные и удобные для пользователей приложения.
1. Постарайтесь уменьшить использование хранилища
В Solidity хранилище ( хранение ) является ограниченным ресурсом, его потребление газа значительно выше, чем у памяти (. Каждый раз, когда смарт-контракт читает или записывает данные из хранилища, возникают высокие расходы на газ.
Согласно определению из «жёлтой книги» Ethereum, стоимость операций хранения более чем в 100 раз выше, чем стоимость операций с памятью. Например, команды OPcodesmload и mstore потребляют всего 3 единицы газа, в то время как операции хранения, такие как sload и sstore, даже в самых идеальных условиях, стоят как минимум 100 единиц.
Методы ограничения использования хранения включают:
![Ethereum смарт-контрактов Gas оптимизация десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-b237228ebe933741fb60f2e8bcb38405.webp(
) 2. Упаковка переменных
Количество хранилищ, используемых в смарт-контрактах, таких как Storage slot###, и способ, которым разработчик представляет данные, существенно влияют на потребление Gas.
Компилятор Solidity упаковывает последовательные переменные хранения в процессе компиляции и использует 32-байтный слот хранения в качестве базовой единицы хранения переменных. Упаковка переменных означает разумное размещение переменных, чтобы несколько переменных могли поместиться в одном слоте хранения.
С помощью этого изменения детали разработчики могут сэкономить 20 000 единиц газа. Хранение неиспользуемого слота памяти требует 20 000 газа, но теперь необходимо всего два слота памяти.
Поскольку каждый слот хранения потребляет Gas, упаковка переменных оптимизирует использование Gas за счет уменьшения количества необходимых слотов хранения.
( 3. Оптимизация типов данных
Переменная может представляться различными типами данных, но стоимость операций, соответствующих разным типам данных, также различна. Выбор подходящего типа данных помогает оптимизировать использование Gas.
Например, в Solidity целые числа могут быть разбиты на разные размеры: uint8, uint16, uint32 и т.д. Поскольку EVM выполняет операции с единицами в 256 бит, использование uint8 означает, что EVM сначала должна преобразовать его в uint256, и это преобразование потребует дополнительных затрат на Gas.
С точки зрения отдельных аспектов, здесь использование uint256 дешевле, чем uint8. Однако, если использовать предложенную ранее оптимизацию упаковки переменных, все будет иначе. Если разработчик сможет упаковать четыре переменные uint8 в один слот хранения, общая стоимость их итерации будет ниже, чем у четырех переменных uint256. Таким образом, смарт-контракт сможет считывать и записывать в один слот хранения и помещать четыре переменные uint8 в память/хранение за одну операцию.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-995905cb414526d4d991899d0c2e6443.webp(
) 4. Используйте переменные фиксированного размера вместо динамических переменных
Если данные могут быть ограничены 32 байтами, рекомендуется использовать тип данных bytes32 вместо bytes или strings. Как правило, переменные фиксированного размера потребляют меньше газа, чем переменные переменного размера. Если длину байтов можно ограничить, старайтесь выбирать минимальную длину от bytes1 до bytes32.
![Оптимизация Gas для смарт-контрактов Ethereum: 10 лучших практик]###https://img-cdn.gateio.im/webp-social/moments-55fcdb765912ef9cd238c46b1d248cff.webp(
) 5. Отображения и массивы
Списки данных Solidity могут быть представлены двумя типами данных: массивами ### Arrays ( и отображениями ) Mappings ###, но их синтаксис и структура совершенно разные.
В большинстве случаев отображения более эффективны и менее затратны, но массивы имеют итеративность и поддерживают упаковку типов данных. Поэтому рекомендуется при управлении списком данных отдавать предпочтение отображениям, если не требуется итерация или можно оптимизировать расход газа за счет упаковки типов данных.
( 6. Используйте calldata вместо memory
Переменные, объявленные в параметрах функции, могут храниться в calldata или memory. Основное отличие между ними заключается в том, что memory может быть изменен функцией, в то время как calldata неизменен.
Запомните этот принцип: если параметры функции только для чтения, следует предпочесть использование calldata, а не memory. Это позволяет избежать ненужных операций копирования из calldata функции в memory.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-9c566626ab499ef65d6f5089a2876ad3.webp(
) 7. Используйте ключевые слова Constant/Immutable по возможности
Постоянные/неизменяемые переменные не хранятся в хранилище контракта. Эти переменные вычисляются во время компиляции и хранятся в байт-коде контракта. Поэтому их стоимость доступа намного ниже по сравнению с хранилищем, и рекомендуется использовать ключевые слова Constant или Immutable по возможности.
![Ethereum смарт-контрактов Gas оптимизация десяти лучших практик]###https://img-cdn.gateio.im/webp-social/moments-c0701f9e09280a1667495d54e262dd2f.webp(
) 8. Используйте Unchecked, чтобы гарантировать, что не произойдет переполнение/недостаток.
Когда разработчики могут убедиться, что арифметические операции не приведут к переполнению или недостатку, они могут использовать ключевое слово unchecked, введенное в Solidity v0.8.0, чтобы избежать избыточных проверок на переполнение или недостаток, тем самым экономя Gas.
Кроме того, компиляторы версии 0.8.0 и выше больше не требуют использования библиотеки SafeMath, так как сам компилятор уже встроил функции защиты от переполнения и недостатка.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик]###https://img-cdn.gateio.im/webp-social/moments-a823fb7761aafa6529a6c45304e0314b.webp(
) 9. Оптимизация модификатора
Код модификатора встраивается в измененную функцию, и каждый раз при использовании модификатора его код копируется. Это увеличивает размер байт-кода и повышает потребление Gas.
Путем реорганизации логики в внутреннюю функцию _checkOwner###(, позволяя повторно использовать эту внутреннюю функцию в модификаторе, можно уменьшить размер байт-кода и снизить стоимость газа.
![Оптимизация газа смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-839b91e2f02389949aa698d460a497d8.webp###
( 10. Оптимизация короткого замыкания
Для || и && операторов логические операции будут выполнять короткое замыкание, то есть если первое условие уже может определить результат логического выражения, второе условие не будет оцениваться.
Чтобы оптимизировать потребление газа, условия с низкой стоимостью вычислений следует ставить впереди, чтобы потенциально избежать дорогостоящих вычислений.
![Оптимизация газа смарт-контрактов Ethereum: 10 лучших практик])https://img-cdn.gateio.im/webp-social/moments-a141884dcdcdc56faff12eee2601b7b7.webp(
Дополнительные общие рекомендации
) 1. Удалить бесполезный код
Если в контракте есть неиспользуемые функции или переменные, рекомендуется их удалить. Это самый прямой способ снизить стоимость развертывания контракта и сохранить его небольшой объем.
Вот несколько полезных советов:
Используйте самые эффективные алгоритмы для вычислений. Если в смарт-контракте используются результаты некоторых вычислений напрямую, то следует удалить эти избыточные вычислительные процессы. По сути, любые неиспользуемые вычисления должны быть удалены.
В Ethereum разработчики могут получить вознаграждение за газ, освободив место для хранения. Если переменная больше не нужна, следует использовать ключевое слово delete для ее удаления или установить ее на значение по умолчанию.
Оптимизация циклов: избегайте затратных операций в циклах, по возможности объединяйте циклы и выносите повторные вычисления за пределы тела цикла.
2. Использование предопределенных смарт-контрактов
Предварительно скомпилированные контракты предоставляют сложные библиотечные функции, такие как операции шифрования и хеширования. Поскольку код выполняется не на EVM, а локально на клиентском узле, требуется меньше газа. Использование предварительно скомпилированных контрактов позволяет сэкономить газ, уменьшая объем вычислительных затрат, необходимых для выполнения смарт-контрактов.
Примеры предкомпилированных смарт-контрактов включают алгоритм цифровой подписи эллиптической кривой (ECDSA) и хэш-алгоритм SHA2-256. Используя эти предкомпилированные смарт-контракты в смарт-контрактах, разработчики могут снизить затраты на газ и повысить эффективность работы приложений.