Лучшие практики по оптимизации Gas-расходов смарт-контрактов Ethereum
Газовые сборы в основной сети Ethereum всегда были проблемой, особенно это становится очевидным в условиях перегрузки сети. В часы пик пользователи вынуждены платить высокие транзакционные сборы. Поэтому оптимизация газовых расходов на этапе разработки смарт-контрактов имеет решающее значение. Оптимизация потребления газа не только эффективно снижает затраты на транзакции, но и повышает эффективность транзакций, предоставляя пользователям более экономичный и эффективный опыт работы с блокчейном.
В этой статье будет рассмотрена механика Gas-стоимости Эфирной виртуальной машины (EVM), основные концепции оптимизации Gas-стоимости, а также лучшие практики оптимизации Gas-стоимости при разработке смарт-контрактов. Надеемся, что эти материалы смогут вдохновить разработчиков и предоставить практическую помощь, а также помогут обычным пользователям лучше понять, как функционируют Gas-расходы EVM, чтобы вместе справляться с вызовами в экосистеме блокчейна.
Введение в механизм Gas-ставок EVM
В сетях, совместимых с EVM, "Gas" является единицей измерения вычислительной мощности, необходимой для выполнения определенных операций.
В структуре EVM расходы на газ делятся на три части: выполнение операций, вызовы внешних сообщений, а также чтение и запись в память и хранилище.
Поскольку выполнение каждой транзакции требует вычислительных ресурсов, за это взимается определенная плата, чтобы предотвратить бесконечные циклы и атаки отказа в обслуживании ( DoS ). Плата, необходимая для завершения транзакции, называется "Gas fee".
С момента вступления в силу хардфорка Лондон EIP-1559( ), комиссия за Gas рассчитывается по следующей формуле:
Газовая плата = единицы использованного газа * ( базовая плата + плата за приоритет )
Базовая плата будет уничтожена, а плата за приоритет будет использоваться в качестве стимула, чтобы побудить валидаторов добавлять транзакции в блокчейн. Установка более высокой платы за приоритет при отправке транзакции может повысить вероятность того, что транзакция будет включена в следующий блок. Это похоже на "чаевые", которые пользователи платят валидаторам.
1. Понимание оптимизации Gas в EVM
Когда вы компилируете смарт-контракты на языке Solidity, контракт преобразуется в серию "операционных кодов", то есть opcodes.
Любой код операции (, например, создание смарт-контракта, выполнение вызова сообщений, доступ к хранилищу аккаунта и выполнение операций на виртуальной машине ) имеет признанную стоимость потребления газа, эти расходы зафиксированы в желтой книге Ethereum.
После нескольких изменений EIP, стоимость газа для некоторых операций была скорректирована, что может отличаться от значений в желтой книге.
2.Основные концепции оптимизации газа
Основная идея оптимизации Gas заключается в том, чтобы в EVM-блокчейне приоритизировать операции с высокой стоимостью эффективности и избегать операций с дорогими затратами на Gas.
В EVM следующие операции имеют низкую стоимость:
Чтение и запись переменных в памяти
Чтение констант и неизменяемых переменных
Чтение и запись локальных переменных
Чтение переменной calldata, например, массива и структуры calldata
Вызов внутренних функций
Операции с высокой стоимостью включают:
Чтение и запись переменных состояния, хранящихся в смарт-контрактах
Вызов внешних функций
Циклические операции
Лучшие практики оптимизации затрат на газ EVM
Основываясь на вышеуказанных основных концепциях, мы подготовили для сообщества разработчиков список лучших практик по оптимизации Gas-расходов. Следуя этим практикам, разработчики могут снизить потребление Gas для смарт-контрактов, уменьшить затраты на транзакции и создать более эффективные и удобные для пользователей приложения.
1. Постарайтесь минимизировать использование хранилища
В Solidity хранилище( является ограниченным ресурсом, его потребление газа значительно выше, чем у памяти). Каждый раз, когда смарт-контракт читает или записывает данные в хранилище, возникают значительные затраты на газ.
Согласно определению из желтой книги Ethereum, стоимость операций хранения более чем в 100 раз выше, чем стоимость операций с памятью. Например, инструкции OPcodesmload и mstore потребляют всего 3 единицы газа, в то время как операции хранения, такие как sload и sstore, даже в самых идеальных условиях требуют как минимум 100 единиц.
Методы ограничения использования хранилища включают:
Храните непостоянные данные в памяти
Уменьшение количества изменений в хранилище: сохраняя промежуточные результаты в памяти и распределяя результаты переменным хранилища только после завершения всех вычислений.
( 2. Упаковка переменных
Количество хранилищ, использующихся в смарт-контрактах, таких как Storage slot), а также способ, которым разработчики представляют данные, будут сильно влиять на потребление Gas.
Компилятор Solidity упаковывает последовательные переменные хранения в процессе компиляции и использует 32-байтный слот хранения в качестве базовой единицы хранения переменной. Упаковка переменных означает разумное распределение переменных, позволяющее нескольким переменным помещаться в один слот хранения.
С помощью этой настройки разработчики могут сэкономить 20 000 единиц газа. Для хранения неиспользуемого слота памяти требуется 20 000 газа, но теперь нужно всего два слота памяти.
Поскольку каждый слот хранения потребляет Gas, упаковка переменных оптимизирует использование Gas, уменьшая необходимое количество слотов хранения.
![Оптимизация Gas в смарт-контрактах Ethereum: десять лучших практик]###https://img-cdn.gateio.im/webp-social/moments-995905cb414526d4d991899d0c2e6443.webp(
) 3. Оптимизация типов данных
Переменная может быть представлена несколькими типами данных, но стоимость операций зависит от различных типов данных. Выбор подходящего типа данных помогает оптимизировать использование газа.
Например, в Solidity целые числа могут быть разбиты на разные размеры: uint8, uint16, uint32 и т.д. Поскольку EVM выполняет операции с единицами по 256 бит, использование uint8 означает, что EVM сначала должен преобразовать его в uint256, и это преобразование дополнительно потребляет Gas.
С точки зрения отдельных переменных, использование uint256 здесь дешевле, чем uint8. Однако, если использовать оптимизацию упаковки переменных, которую мы ранее предлагали, ситуация меняется. Если разработчик сможет упаковать четыре переменные uint8 в один слот памяти, то общая стоимость их итерации будет ниже, чем у четырех переменных uint256. Таким образом, смарт-контракты смогут читать и записывать один слот памяти и поместить четыре переменные uint8 в память/хранилище за одну операцию.
( 4. Используйте переменные фиксированного размера вместо динамических переменных
Если данные можно ограничить 32 байтами, рекомендуется использовать тип данных bytes32 вместо bytes или strings. Как правило, фиксированные переменные расходуют меньше газа, чем переменные переменной длины. Если длина байтов может быть ограничена, старайтесь выбирать минимальную длину от bytes1 до bytes32.
![Оптимизация Gas для смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-5f3d7e103e47c886f50599cffe35c707.webp###
( 5. Отображения и массивы
Списки данных в Solidity могут быть представлены двумя типами данных: массивы ) Arrays ### и отображения ( Mappings ), но их синтаксис и структура совершенно различны.
В большинстве случаев отображение более эффективно и стоит дешевле, но массивы имеют итерабельность и поддерживают упаковку типов данных. Поэтому рекомендуется при управлении списком данных предпочитать отображение, если только не требуется итерация или можно оптимизировать потребление газа за счет упаковки типов данных.
![Газовые оптимизации смарт-контрактов Ethereum: 10 лучших практик]###https://img-cdn.gateio.im/webp-social/moments-9c566626ab499ef65d6f5089a2876ad3.webp(
) 6. Используйте calldata вместо memory
Переменные, объявленные в параметрах функции, могут храниться в calldata или memory. Основное различие между ними заключается в том, что memory может быть изменен функцией, тогда как calldata неизменяем.
Запомните этот принцип: если параметры функции являются только для чтения, следует предпочесть использование calldata вместо memory. Это поможет избежать ненужных операций копирования из calldata функции в memory.
( 7. Используйте ключевые слова Constant/Immutable, насколько это возможно.
Постоянные/Неизменяемые переменные не хранятся в хранилище контракта. Эти переменные вычисляются во время компиляции и хранятся в байт-коде контракта. Поэтому их стоимость доступа значительно ниже по сравнению с хранилищем, рекомендуется использовать ключевые слова Constant или Immutable, когда это возможно.
![Оптимизация Gas для смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-a823fb7761aafa6529a6c45304e0314b.webp###
( 8. Используйте Unchecked, чтобы гарантировать, что не произойдет переполнение/недополнение
Когда разработчики могут быть уверены, что арифметические операции не приведут к переполнению или недополнению, можно использовать ключевое слово unchecked, введенное в Solidity v0.8.0, чтобы избежать избыточной проверки на переполнение или недополнение, тем самым сэкономив затраты на Gas.
Кроме того, компиляторы версии 0.8.0 и выше больше не требуют использования библиотеки SafeMath, так как сам компилятор уже встроил функции защиты от переполнения и недостатка.
![Оптимизация Gas смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-839b91e2f02389949aa698d460a497d8.webp###
( 9. Оптимизация модификатора
Код модификатора встроен в изменённые функции, и каждый раз при использовании модификатора его код копируется. Это увеличивает размер байт-кода и повышает потребление газа.
Путем рефакторинга логики в внутреннюю функцию _checkOwner)###, разрешается повторное использование этой внутренней функции в модификаторе, что позволяет уменьшить размер байт-кода и снизить затраты на газ.
10. Оптимизация короткого замыкания
Для || и && операторов логические операции будут оцениваться с коротким замыканием, то есть если первое условие уже может определить результат логического выражения, то второе условие не будет оцениваться.
Чтобы оптимизировать потребление газа, следует размещать условия с низкой вычислительной стоимостью вначале, чтобы иметь возможность пропустить дорогостоящие вычисления.
Дополнительные общие рекомендации
( 1. Удалить ненужный код
Если в смарт-контракте есть неиспользуемые функции или переменные, рекомендуется их удалить. Это самый прямой способ снижения стоимости развертывания контракта и поддержания небольшого объема контракта.
Вот несколько практических советов:
Используйте самые эффективные алгоритмы для вычислений. Если в смарт-контракте напрямую используются результаты некоторых вычислений, то следует удалить эти избыточные вычислительные процессы. По сути, любые неиспользуемые вычисления должны быть удалены.
В Ethereum разработчики могут получать вознаграждение в виде газа, освобождая место для хранения. Если переменная больше не нужна, следует использовать ключевое слово delete для её удаления или установить её в значение по умолчанию.
Оптимизация циклов: избегайте операций в цикле с высокой стоимостью, по возможности объединяйте циклы и выносите повторные вычисления за пределы тела цикла.
![Ethereum смарт-контрактов Gas оптимизация десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-248337b15929868ed1250ffb9fcfa289.webp(
Предварительно скомпилированные контракты предлагают сложные библиотечные функции, такие как операции шифрования и хеширования. Поскольку код не выполняется в EVM, а работает локально на клиентском узле, требуется меньше газа. Использование предварительно скомпилированных контрактов может сэкономить газ, снижая вычислительные затраты на выполнение смарт-контрактов.
Примеры предкомпилированных смарт-контрактов включают алгоритм цифровой подписи на основе эллиптической кривой ###ECDSA### и хэш-алгоритм SHA2-256. Используя эти предкомпилированные контракты в смарт-контрактах, разработчики могут снизить затраты на газ и повысить эффективность работы приложений.
( 3. Использование встроенного ассемблера
Встраиваемая сборка ) in-line assembly ### позволяет разработчикам писать низкоуровневый, но эффективный код, который может выполняться непосредственно EVM, без необходимости использования дорогих операций Solidity. Встраиваемая сборка также позволяет более точно контролировать использование памяти и хранилища, что дополнительно снижает стоимость Gas. Кроме того, встраиваемая сборка может
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
16 Лайков
Награда
16
7
Поделиться
комментарий
0/400
AlgoAlchemist
· 4ч назад
Газ要搞死我了
Посмотреть ОригиналОтветить0
BearEatsAll
· 15ч назад
Высокие газовые сборы не являются ли мертвой дорогой для тех, кто хочет получить выгоду?
Посмотреть ОригиналОтветить0
MEVHunterWang
· 07-11 05:59
Газ опять вырос, смотреть больно.
Посмотреть ОригиналОтветить0
CoffeeNFTrader
· 07-11 05:55
Газ снова оптимизирован, но это всё равно ловушка. Лучше идти на layer2.
Посмотреть ОригиналОтветить0
StrawberryIce
· 07-11 05:54
Застрял на высоком Газ, давай-давай-давай!
Посмотреть ОригиналОтветить0
OffchainWinner
· 07-11 05:50
Я не хочу больше использовать L2...
Посмотреть ОригиналОтветить0
HalfBuddhaMoney
· 07-11 05:31
даже если газовые сборы высоки, все равно нужно пополнить, брат.
13 практик оптимизации Gas для смарт-контрактов Ethereum
Лучшие практики по оптимизации Gas-расходов смарт-контрактов Ethereum
Газовые сборы в основной сети Ethereum всегда были проблемой, особенно это становится очевидным в условиях перегрузки сети. В часы пик пользователи вынуждены платить высокие транзакционные сборы. Поэтому оптимизация газовых расходов на этапе разработки смарт-контрактов имеет решающее значение. Оптимизация потребления газа не только эффективно снижает затраты на транзакции, но и повышает эффективность транзакций, предоставляя пользователям более экономичный и эффективный опыт работы с блокчейном.
В этой статье будет рассмотрена механика Gas-стоимости Эфирной виртуальной машины (EVM), основные концепции оптимизации Gas-стоимости, а также лучшие практики оптимизации Gas-стоимости при разработке смарт-контрактов. Надеемся, что эти материалы смогут вдохновить разработчиков и предоставить практическую помощь, а также помогут обычным пользователям лучше понять, как функционируют Gas-расходы EVM, чтобы вместе справляться с вызовами в экосистеме блокчейна.
Введение в механизм Gas-ставок EVM
В сетях, совместимых с EVM, "Gas" является единицей измерения вычислительной мощности, необходимой для выполнения определенных операций.
В структуре EVM расходы на газ делятся на три части: выполнение операций, вызовы внешних сообщений, а также чтение и запись в память и хранилище.
Поскольку выполнение каждой транзакции требует вычислительных ресурсов, за это взимается определенная плата, чтобы предотвратить бесконечные циклы и атаки отказа в обслуживании ( DoS ). Плата, необходимая для завершения транзакции, называется "Gas fee".
С момента вступления в силу хардфорка Лондон EIP-1559( ), комиссия за Gas рассчитывается по следующей формуле:
Газовая плата = единицы использованного газа * ( базовая плата + плата за приоритет )
Базовая плата будет уничтожена, а плата за приоритет будет использоваться в качестве стимула, чтобы побудить валидаторов добавлять транзакции в блокчейн. Установка более высокой платы за приоритет при отправке транзакции может повысить вероятность того, что транзакция будет включена в следующий блок. Это похоже на "чаевые", которые пользователи платят валидаторам.
1. Понимание оптимизации Gas в EVM
Когда вы компилируете смарт-контракты на языке Solidity, контракт преобразуется в серию "операционных кодов", то есть opcodes.
Любой код операции (, например, создание смарт-контракта, выполнение вызова сообщений, доступ к хранилищу аккаунта и выполнение операций на виртуальной машине ) имеет признанную стоимость потребления газа, эти расходы зафиксированы в желтой книге Ethereum.
После нескольких изменений EIP, стоимость газа для некоторых операций была скорректирована, что может отличаться от значений в желтой книге.
2.Основные концепции оптимизации газа
Основная идея оптимизации Gas заключается в том, чтобы в EVM-блокчейне приоритизировать операции с высокой стоимостью эффективности и избегать операций с дорогими затратами на Gas.
В EVM следующие операции имеют низкую стоимость:
Операции с высокой стоимостью включают:
Лучшие практики оптимизации затрат на газ EVM
Основываясь на вышеуказанных основных концепциях, мы подготовили для сообщества разработчиков список лучших практик по оптимизации Gas-расходов. Следуя этим практикам, разработчики могут снизить потребление Gas для смарт-контрактов, уменьшить затраты на транзакции и создать более эффективные и удобные для пользователей приложения.
1. Постарайтесь минимизировать использование хранилища
В Solidity хранилище( является ограниченным ресурсом, его потребление газа значительно выше, чем у памяти). Каждый раз, когда смарт-контракт читает или записывает данные в хранилище, возникают значительные затраты на газ.
Согласно определению из желтой книги Ethereum, стоимость операций хранения более чем в 100 раз выше, чем стоимость операций с памятью. Например, инструкции OPcodesmload и mstore потребляют всего 3 единицы газа, в то время как операции хранения, такие как sload и sstore, даже в самых идеальных условиях требуют как минимум 100 единиц.
Методы ограничения использования хранилища включают:
( 2. Упаковка переменных
Количество хранилищ, использующихся в смарт-контрактах, таких как Storage slot), а также способ, которым разработчики представляют данные, будут сильно влиять на потребление Gas.
Компилятор Solidity упаковывает последовательные переменные хранения в процессе компиляции и использует 32-байтный слот хранения в качестве базовой единицы хранения переменной. Упаковка переменных означает разумное распределение переменных, позволяющее нескольким переменным помещаться в один слот хранения.
С помощью этой настройки разработчики могут сэкономить 20 000 единиц газа. Для хранения неиспользуемого слота памяти требуется 20 000 газа, но теперь нужно всего два слота памяти.
Поскольку каждый слот хранения потребляет Gas, упаковка переменных оптимизирует использование Gas, уменьшая необходимое количество слотов хранения.
![Оптимизация Gas в смарт-контрактах Ethereum: десять лучших практик]###https://img-cdn.gateio.im/webp-social/moments-995905cb414526d4d991899d0c2e6443.webp(
) 3. Оптимизация типов данных
Переменная может быть представлена несколькими типами данных, но стоимость операций зависит от различных типов данных. Выбор подходящего типа данных помогает оптимизировать использование газа.
Например, в Solidity целые числа могут быть разбиты на разные размеры: uint8, uint16, uint32 и т.д. Поскольку EVM выполняет операции с единицами по 256 бит, использование uint8 означает, что EVM сначала должен преобразовать его в uint256, и это преобразование дополнительно потребляет Gas.
С точки зрения отдельных переменных, использование uint256 здесь дешевле, чем uint8. Однако, если использовать оптимизацию упаковки переменных, которую мы ранее предлагали, ситуация меняется. Если разработчик сможет упаковать четыре переменные uint8 в один слот памяти, то общая стоимость их итерации будет ниже, чем у четырех переменных uint256. Таким образом, смарт-контракты смогут читать и записывать один слот памяти и поместить четыре переменные uint8 в память/хранилище за одну операцию.
( 4. Используйте переменные фиксированного размера вместо динамических переменных
Если данные можно ограничить 32 байтами, рекомендуется использовать тип данных bytes32 вместо bytes или strings. Как правило, фиксированные переменные расходуют меньше газа, чем переменные переменной длины. Если длина байтов может быть ограничена, старайтесь выбирать минимальную длину от bytes1 до bytes32.
![Оптимизация Gas для смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-5f3d7e103e47c886f50599cffe35c707.webp###
( 5. Отображения и массивы
Списки данных в Solidity могут быть представлены двумя типами данных: массивы ) Arrays ### и отображения ( Mappings ), но их синтаксис и структура совершенно различны.
В большинстве случаев отображение более эффективно и стоит дешевле, но массивы имеют итерабельность и поддерживают упаковку типов данных. Поэтому рекомендуется при управлении списком данных предпочитать отображение, если только не требуется итерация или можно оптимизировать потребление газа за счет упаковки типов данных.
![Газовые оптимизации смарт-контрактов Ethereum: 10 лучших практик]###https://img-cdn.gateio.im/webp-social/moments-9c566626ab499ef65d6f5089a2876ad3.webp(
) 6. Используйте calldata вместо memory
Переменные, объявленные в параметрах функции, могут храниться в calldata или memory. Основное различие между ними заключается в том, что memory может быть изменен функцией, тогда как calldata неизменяем.
Запомните этот принцип: если параметры функции являются только для чтения, следует предпочесть использование calldata вместо memory. Это поможет избежать ненужных операций копирования из calldata функции в memory.
( 7. Используйте ключевые слова Constant/Immutable, насколько это возможно.
Постоянные/Неизменяемые переменные не хранятся в хранилище контракта. Эти переменные вычисляются во время компиляции и хранятся в байт-коде контракта. Поэтому их стоимость доступа значительно ниже по сравнению с хранилищем, рекомендуется использовать ключевые слова Constant или Immutable, когда это возможно.
![Оптимизация Gas для смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-a823fb7761aafa6529a6c45304e0314b.webp###
( 8. Используйте Unchecked, чтобы гарантировать, что не произойдет переполнение/недополнение
Когда разработчики могут быть уверены, что арифметические операции не приведут к переполнению или недополнению, можно использовать ключевое слово unchecked, введенное в Solidity v0.8.0, чтобы избежать избыточной проверки на переполнение или недополнение, тем самым сэкономив затраты на Gas.
Кроме того, компиляторы версии 0.8.0 и выше больше не требуют использования библиотеки SafeMath, так как сам компилятор уже встроил функции защиты от переполнения и недостатка.
![Оптимизация Gas смарт-контрактов Ethereum: десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-839b91e2f02389949aa698d460a497d8.webp###
( 9. Оптимизация модификатора
Код модификатора встроен в изменённые функции, и каждый раз при использовании модификатора его код копируется. Это увеличивает размер байт-кода и повышает потребление газа.
Путем рефакторинга логики в внутреннюю функцию _checkOwner)###, разрешается повторное использование этой внутренней функции в модификаторе, что позволяет уменьшить размер байт-кода и снизить затраты на газ.
10. Оптимизация короткого замыкания
Для || и && операторов логические операции будут оцениваться с коротким замыканием, то есть если первое условие уже может определить результат логического выражения, то второе условие не будет оцениваться.
Чтобы оптимизировать потребление газа, следует размещать условия с низкой вычислительной стоимостью вначале, чтобы иметь возможность пропустить дорогостоящие вычисления.
Дополнительные общие рекомендации
( 1. Удалить ненужный код
Если в смарт-контракте есть неиспользуемые функции или переменные, рекомендуется их удалить. Это самый прямой способ снижения стоимости развертывания контракта и поддержания небольшого объема контракта.
Вот несколько практических советов:
Используйте самые эффективные алгоритмы для вычислений. Если в смарт-контракте напрямую используются результаты некоторых вычислений, то следует удалить эти избыточные вычислительные процессы. По сути, любые неиспользуемые вычисления должны быть удалены.
В Ethereum разработчики могут получать вознаграждение в виде газа, освобождая место для хранения. Если переменная больше не нужна, следует использовать ключевое слово delete для её удаления или установить её в значение по умолчанию.
Оптимизация циклов: избегайте операций в цикле с высокой стоимостью, по возможности объединяйте циклы и выносите повторные вычисления за пределы тела цикла.
![Ethereum смарт-контрактов Gas оптимизация десять лучших практик])https://img-cdn.gateio.im/webp-social/moments-248337b15929868ed1250ffb9fcfa289.webp(
) 2. Используйте предкомпилированные смарт-контракты
Предварительно скомпилированные контракты предлагают сложные библиотечные функции, такие как операции шифрования и хеширования. Поскольку код не выполняется в EVM, а работает локально на клиентском узле, требуется меньше газа. Использование предварительно скомпилированных контрактов может сэкономить газ, снижая вычислительные затраты на выполнение смарт-контрактов.
Примеры предкомпилированных смарт-контрактов включают алгоритм цифровой подписи на основе эллиптической кривой ###ECDSA### и хэш-алгоритм SHA2-256. Используя эти предкомпилированные контракты в смарт-контрактах, разработчики могут снизить затраты на газ и повысить эффективность работы приложений.
( 3. Использование встроенного ассемблера
Встраиваемая сборка ) in-line assembly ### позволяет разработчикам писать низкоуровневый, но эффективный код, который может выполняться непосредственно EVM, без необходимости использования дорогих операций Solidity. Встраиваемая сборка также позволяет более точно контролировать использование памяти и хранилища, что дополнительно снижает стоимость Gas. Кроме того, встраиваемая сборка может