Руководство по оптимизации Gas-расходов для EVM смарт-контрактов - 13 практических советов

Оптимизация Gas-расходов EVM - Руководство по разработке смарт-контрактов Ethereum

Плата за газ в основной сети Ethereum всегда была предметом повышенного внимания, особенно в периоды загруженности сети. В часы пик пользователи часто вынуждены платить высокие комиссии за транзакции. Поэтому оптимизация затрат на газ на этапе разработки смарт-контрактов имеет решающее значение. Оптимизация потребления газа не только эффективно снижает транзакционные издержки, но и повышает эффективность транзакций, обеспечивая пользователям более экономичный и эффективный опыт использования блокчейна.

В данной статье будет рассмотрена механика Gas-расходов Эфирной виртуальной машины (EVM), ключевые концепции оптимизации Gas-расходов, а также лучшие практики оптимизации Gas-расходов при разработке смарт-контрактов. Надеемся, что эти материалы вдохновят разработчиков и окажут практическую помощь, а также помогут обычным пользователям лучше понять, как работают Gas-расходы в EVM, чтобы вместе справляться с вызовами экосистемы блокчейна.

Оптимизация Gas для смарт-контрактов Ethereum: десять лучших практик

Введение в механизм Gas-ставок EVM

В совместимых с EVM сетях, "Gas" является единицей измерения вычислительной мощности, необходимой для выполнения определенных операций.

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

Поскольку выполнение каждой транзакции требует вычислительных ресурсов, взимается определенная плата, чтобы предотвратить бесконечные циклы и атаки отказа в обслуживании ( DoS ). Плата, необходимая для завершения транзакции, называется "Gas-стоимость".

С момента вступления в силу EIP-1559, газовые сборы рассчитываются по следующей формуле:

Газовый сбор = количество использованных единиц газа * (базовая ставка + приоритетный сбор)

Базовый сбор будет уничтожен, а приоритетный сбор будет использован в качестве стимула, чтобы побудить валидаторов добавлять транзакции в блокчейн. Установка более высокого приоритетного сбора при отправке транзакции может повысить вероятность того, что транзакция будет включена в следующий блок. Это похоже на "чаевые", которые пользователь платит валидатору.

! 10 лучших практик оптимизации газа для смарт-контрактов Ethereum

Понимание оптимизации Gas в EVM

Когда смарт-контракты компилируются с помощью Solidity, контракт преобразуется в серию "операционных кодов", то есть opcodes.

Любая операция с кодом (, например создание смарт-контракта, выполнение вызова сообщений, доступ к хранилищу аккаунтов и выполнение операций на виртуальной машине ) имеет признанную стоимость потребления газа, которая зафиксирована в желтой книге Ethereum.

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

Основные концепции оптимизации газа

Основная идея оптимизации газа заключается в приоритизации операций с высокой стоимостью эффективности на блокчейне EVM и избегании операций с дорогими затратами на газ.

В EVM следующие операции имеют низкую стоимость:

  • Чтение и запись переменных памяти
  • Чтение констант и неизменяемых переменных
  • Чтение и запись локальных переменных
  • Чтение переменной calldata, например массива calldata и структур
  • Вызов внутренних функций

Дорогие операции включают:

  • Чтение и запись состояния переменных, хранящихся в смарт-контрактах
  • Внешний вызов функции
  • Циклическая операция

Гас-оптимизация смарт-контрактов Ethereum: десять лучших практик

Лучшие практики оптимизации Gas-расходов EVM

1. Старайтесь минимизировать использование хранилища

В Solidity, Storage( хранение) является ограниченным ресурсом, его потребление газа значительно выше, чем у Memory( памяти). Каждый раз, когда смарт-контракт читает или записывает данные из хранилища, возникают высокие затраты на газ.

Согласно определению из жёлтой книги Ethereum, стоимость операций хранения более чем в 100 раз выше, чем стоимость операций с памятью. Например, инструкции OPcodesmload и mstore потребляют всего 3 единицы газа, в то время как операции хранения, такие как sload и sstore, даже в самых идеальных условиях, стоят как минимум 100 единиц.

Методы ограничения использования хранилища включают:

  • Храните непостоянные данные в памяти
  • Уменьшение количества изменений в хранилище: сохраняйте промежуточные результаты в памяти, а затем, после завершения всех вычислений, присваивайте результаты переменным хранения.

Оптимизация газа для смарт-контрактов Ethereum: десять лучших практик

2. Упаковка переменных

Количество слотов хранения, используемых в смарт-контрактах, и способ, которым разработчики представляют данные, будут значительно влиять на потребление газа.

Компилятор Solidity упаковывает последовательные переменные хранения в процессе компиляции и использует 32-байтовый слот хранения в качестве базовой единицы хранения переменных. Упаковка переменных означает разумное размещение переменных, позволяющее нескольким переменным помещаться в один слот хранения.

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

Оптимизация Gas для смарт-контрактов Ethereum: 10 лучших практик

( 3. Оптимизация типов данных

Выбор подходящего типа данных помогает оптимизировать использование газа. Например, в Solidity целые числа можно разбить на разные размеры: uint8, uint16, uint32 и т.д. Поскольку EVM выполняет операции с единицами по 256 бит, использование uint8 означает, что EVM сначала должен преобразовать его в uint256, и это преобразование будет дополнительно потреблять газ.

Однако, если использовать упаковку переменных для оптимизации, упаковав четыре переменные типа uint8 в один слот памяти, то общая стоимость их итерации будет ниже, чем у четырех переменных типа uint256. Таким образом, смарт-контракт сможет читать и записывать один слот памяти и помещать четыре переменные типа uint8 в память/хранилище за одну операцию.

![Газовые оптимизации смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-55fcdb765912ef9cd238c46b1d248cff.webp###

( 4. Используйте переменные фиксированного размера вместо динамических переменных

Если данные могут быть ограничены 32 байтами, рекомендуется использовать тип данных bytes32 вместо bytes или strings. Как правило, переменные фиксированного размера потребляют меньше газа, чем переменные переменного размера. Если длину байтов можно ограничить, старайтесь выбирать минимальную длину от bytes1 до bytes32.

) 5. Отображения и массивы

Списки данных Solidity можно представлять двумя типами данных: массивами ###Arrays ### и отображениями (Mappings ), но их синтаксис и структура совершенно различны.

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

Оптимизация газа смарт-контрактов Ethereum: десять лучших практик

( 6. Использование calldata вместо памяти

Переменные, объявленные в параметрах функции, могут храниться в calldata или memory. Основное различие между ними заключается в том, что memory может быть изменен функцией, тогда как calldata является неизменяемым.

Запомните этот принцип: если параметры функции являются только для чтения, следует предпочитать использование calldata вместо memory. Это поможет избежать ненужных операций копирования из calldata функции в memory.

![Оптимизация Gas для смарт-контрактов 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, чтобы избежать избыточной проверки на переполнение или недостаток, тем самым сэкономив стоимость газа.

Кроме того, компиляторы версии 0.8.0 и выше больше не требуют использования библиотеки SafeMath, так как сам компилятор уже встроил функции защиты от переполнения и недополнения.

![Оптимизация Gas для смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-a823fb7761aafa6529a6c45304e0314b.webp###

( 9. Оптимизация модификатора

Код модификатора встроен в измененные функции, и каждый раз при использовании модификатора его код копируется. Это увеличивает размер байт-кода и увеличивает потребление газа. Размер байт-кода можно уменьшить и снизить затраты на газ, реорганизовав логику в внутренние функции и повторно используя эту внутреннюю функцию в модификаторе.

![Оптимизация Gas смарт-контрактов Ethereum: 10 лучших практик])https://img-cdn.gateio.im/webp-social/moments-839b91e2f02389949aa698d460a497d8.webp###

( 10. Оптимизация короткого замыкания

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

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

![Оптимизация Gas для смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-a141884dcdcdc56faff12eee2601b7b7.webp###

Дополнительные общие рекомендации

( 1. Удалить ненужный код

Если в смарт-контракте есть неиспользуемые функции или переменные, рекомендуется удалить их. Это самый прямой способ снизить стоимость развертывания контракта и сохранить его небольшой объем.

Вот некоторые полезные советы:

  • Используйте наиболее эффективные алгоритмы для вычислений. Если в смарт-контрактах напрямую используются результаты некоторых вычислений, то следует избавиться от этих избыточных вычислительных процессов. По сути, любые неиспользуемые вычисления должны быть удалены.

  • В Ethereum разработчики могут получить вознаграждение в виде газа, освобождая место для хранения. Если переменная больше не нужна, следует использовать ключевое слово delete для ее удаления или установить ее в значение по умолчанию.

  • Оптимизация циклов: избегайте дорогостоящих операций с циклами, по возможности объединяйте циклы и выносите повторяющиеся вычисления за пределы тела цикла.

) 2. Использование предкомпилированных смарт-контрактов

Предварительно скомпилированные контракты предлагают сложные библиотечные функции, такие как операции шифрования и хеширования. Поскольку код выполняется не на EVM, а локально на клиентском узле, требуется меньше газа. Использование предварительно скомпилированных контрактов может сэкономить газ, уменьшая вычислительную нагрузку, необходимую для выполнения смарт-контрактов.

Примеры предкомпилированных смарт-контрактов включают в себя алгоритм цифровой подписи на основе эллиптической кривой ###ECDSA### и алгоритм хэширования SHA2-256. Используя эти предкомпилированные смарт-контракты в смарт-контрактах, разработчики могут снизить стоимость газа и повысить эффективность работы приложений.

( 3. Использование встроенного ассемблера

Встроенный ассемблер ) in-line assembly ### позволяет разработчикам писать низкоуровневый, но эффективный код, который может выполняться непосредственно EVM, без необходимости использования дорогих операций Solidity. Встроенный ассемблер также позволяет более точно контролировать использование памяти и хранилища, что дополнительно снижает стоимость Gas. Кроме того, встроенный ассемблер может выполнять некоторые сложные операции, которые трудно реализовать только с помощью Solidity, предоставляя больше гибкости для оптимизации потребления Gas.

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

( 4. Использование решений Layer 2

Использование решений Layer 2 может сократить объем данных, которые необходимо хранить и обрабатывать в Эфире.

Решения второго уровня, такие как роллапсы, сайдчейны и каналы состояния, могут разгрузить обработку транзакций с основной цепочки Ethereum, что позволяет осуществлять более быстрые и дешевые транзакции.

С помощью объединения большого количества транзакций эти решения уменьшают количество транзакций в цепочке, что снижает Gas-расходы. Использование решений второго уровня также может повысить масштабируемость Ethereum, позволяя большему числу пользователей и приложений участвовать в сети, не приводя к

ETH-2.2%
Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
  • Награда
  • 4
  • Поделиться
комментарий
0/400
GateUser-beba108dvip
· 08-04 12:07
Газ费 давит на меня, да?
Посмотреть ОригиналОтветить0
BTCBeliefStationvip
· 08-04 11:51
Газ тоже должен внутренне конкурировать, да? Падение тоже допустимо.
Посмотреть ОригиналОтветить0
ParanoiaKingvip
· 08-04 11:47
Эти газовые сборы просто ужасны.
Посмотреть ОригиналОтветить0
DegenGamblervip
· 08-04 11:45
Газ сошел с ума, не заканчивается?
Посмотреть ОригиналОтветить0
  • Закрепить