В этой статье вы найдете несколько советов по сокращению потребления газа в ваших смарт-контрактах.

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

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

Совет №1. Упакуйте свои переменные

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

Пример:

Компилятор Solidity может помещать 2 uint128 в одни и те же 256-битные слоты памяти, только если они объявлены рядом друг с другом. В противном случае каждая uint128 переменная занимает отдельный uint256 только для себя, тратя 128 бит на каждый слот (как и в первом контракте):

Совет № 2: Включите оптимизатор твердости

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

Вы можете включить оптимизацию с помощью этого параметра в вашем truffle-config.js файле:

Совет № 3. Удалите ненужные переменные

В Ethereum вы получаете возмещение за газ за освобождение места для хранения.
Удаление переменного возмещения 15 000 за газ, но не более половины стоимости транзакции за газ. Удаление с помощью ключевого слова delete эквивалентно присвоению начального значения для типа данных, например 0 для целых чисел.

Совет №4: вычисляйте известную ценность вне сети

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

Совет № 5: не сжимайте переменные

Это означает, что если вы используете uint8, EVM должен сначала преобразовать его в uint256, чтобы работать с ним, и преобразование требует дополнительных затрат! Вы можете задаться вопросом, о чем думали разработчики? Почему тогда они создали переменные меньшего размера? Ответ кроется в упаковке. В принципе, вы можете упаковать несколько небольших переменных в один слот, но если вы определяете единственную переменную и не можете ее упаковать, оптимально использовать uint256, а не uint8.

Совет № 6: используйте события

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

Совет № 7: используйте сборку

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

Совет № 8: используйте библиотеки

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

Совет № 9: минимизируйте данные в цепочке

Чем меньше вы вставляете в цепочку, тем меньше затраты на газ.
Когда вы разрабатываете Dapp, вам не нужно помещать 100% ваших данных в блокчейн, обычно у вас есть часть системы (ненужные данные (метаданные и т. д.)) на централизованном сервере.

Совет № 10: избегайте манипулирования данными хранилища

Выполнение операций с памятью или вызовом данных, аналогичных памяти, всегда дешевле хранения.

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

Во втором контракте перед запуском цикла for мы присваиваем значение данных хранилища d переменной _d, чтобы избежать доступа к хранилищу при каждой итерации.

Совет № 11: используйте eth-gas-reporter

Этот репортер отображает изменения потребления газа для каждой функции в вашем смарт-контракте.

Совет № 12: используйте правила короткого замыкания в своих интересах

При использовании логической дизъюнкции (||), логической конъюнкции (&&) убедитесь, что ваши функции упорядочены правильно для оптимального использования газа. В логическом дизъюнкции (ИЛИ), если первая функция принимает значение «истина», вторая не будет выполняться и, следовательно, сэкономит вам газ. В логической дизъюнкции (И), если первая функция оценивается как ложь, следующая функция не оценивается. Следовательно, вы должны соответствующим образом упорядочить свои функции в своем твердотельном коде, чтобы уменьшить вероятность необходимости оценивать вторую функцию.

Совет № 13: используйте ERC1167 для многократного развертывания одного и того же контракта

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

Совет №14: избегайте присвоения значений, которые вы никогда не будете использовать

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

uint256 value; дешевле uint256 value = 0;.

Совет № 15: используйте сопоставления вместо массивов

Solidity - это первый язык, в котором сопоставления обходятся дешевле, чем массивы.
В большинстве случаев будет лучше использовать mapping вместо массива из-за более дешевых операций.

Совет №16: ограничьте длину строки в требованиях

Если мы добавляем строки сообщений к операторам require, мы можем удешевить их, ограничив длину строки 32 байтами.

Совет № 17: массивы фиксированного размера дешевле динамических

Если мы знаем, какой длины должен быть массив, мы указываем фиксированный размер:

uint256[12] monthlyTransfers;

Это же правило применяется к строкам. Переменная string или bytes имеет динамический размер; мы должны использовать byte32, если наша строка достаточно короткая, чтобы уместиться.

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

Свяжитесь со мной в LinkedIn, Github, и Twitter.

Конец статьи

Использованная литература :