Высокий gas — одна из главных причин, почему пользователи уходят из dApp, а контракты становятся дороже в поддержке. Для разработчика оптимизация — не просто “косметика”, а способ снизить издержки, повысить UX и сделать протокол конкурентнее.
Что важно понимать: gas тратится на вычисления, запись в storage, чтение данных и вызовы функций. Самая дорогая операция — запись в storage, поэтому именно здесь чаще всего скрыт главный потенциал экономии.
-
Минимизируйте запись в storage
Если данные не нужно хранить постоянно, используйте `memory` или `calldata`. `calldata` особенно выгоден для внешних функций, потому что не копирует аргументы в память.
```solidity function setData(uint[] calldata values) external ``` -
Оптимизируйте типы данных, но с умом
Маленькие типы вроде `uint8` не всегда дешевле `uint256`. Экономия появляется, когда Solidity может упаковать несколько переменных в один слот storage.
```solidity struct User { uint128 balance; uint64 lastUpdate; uint64 level; } ```Если порядок выбран правильно, данные занимают меньше слотов — значит, меньше затрат на хранение.
-
Избегайте лишних циклов 🔁
Циклы с большим количеством итераций быстро делают транзакции дорогими, а иногда и невыполнимыми.
Лучше:
- разбивать операции на несколько транзакций
- использовать off-chain вычисления
- хранить уже подготовленные результаты
-
Кэшируйте storage-переменные в memory
Повторное чтение из storage дороже, чем работа с локальной переменной.
uint bal = balances[msg.sender];Если значение используется несколько раз — сначала сохраните его локально.
-
Используйте `unchecked` там, где безопасно ⚙️
В Solidity 0.8+ есть автоматическая проверка переполнения. Это повышает безопасность, но увеличивает gas. В некоторых местах, например в счетчиках цикла, можно использовать:
unchecked { ++i; }Но только если переполнение реально исключено логикой.
-
Снижайте количество external calls
Внешние вызовы стоят дороже и увеличивают риски. По возможности объединяйте действия в одну функцию или используйте батчинг.
-
Удаляйте ненужные данные 🧹
Если storage-переменная больше не нужна, её обнуление может частично вернуть gas через refund. После обновлений EVM возвраты стали меньше, но подход всё ещё полезен.
-
Пишите `custom errors` вместо длинных require-строк
Это дешевле, чем хранить и передавать длинный текст ошибки.
error NotAuthorized(); Вместо: require(msg.sender == owner, "You are not authorized"); -
Оптимизируйте события (events) 📉
Логи дешевле storage, но тоже стоят денег. Не индексируйте всё подряд: `indexed` полезен для поиска, но увеличивает стоимость.
Главный принцип gas-оптимизации: не жертвуйте безопасностью и читаемостью ради минимальной экономии. Лучший результат дают не “хаки”, а грамотная архитектура контракта, продуманная модель хранения данных и профилирование через инструменты вроде Hardhat Gas Reporter или Foundry.
Хороший смарт-контракт — это не только безопасный код, но и код, которым пользователи реально хотят пользоваться 🚀
Подборку каналов про криптовалюты — с аналитикой, новостями и практикой — стоит держать под рукой 👀