Можливо, ви натрапляли на кілька порад Solidity, щоб покращити свої навички кодування, щоб заощадити газ, але сьогодні я хочу більше зосередитися на тому, як розуміння віртуальної машини Ethereum може ефективно заощадити витрати на газ у ваших смарт-контрактах.

Оскільки ми збираємося зануритися в Ethereum, я залишу тут фрагмент його жовтого паперу, де вказується вартість газу для кодів операції, і під час статті ми будемо посилатися на них.



Порада №1: Холодний доступ ПРОТИ теплого доступу

Gхолодне навантаження: 2100 газ

Gwarmaccess: 100 газ

У нас є наші перші OPCODES, перший визначає, скільки коштує отримати доступ до змінної вперше (або холодний доступ), а другий визначає, скільки коштує отримати доступ до змінної вдруге і далі (теплий доступ). ). Як ви бачите, різниця в ціні досить велика, тому розуміння цього може значно змінити вартість транзакцій вашого смарт-контракту. Давайте подивимося на приклад.





Кешування даних усередині функції в Solidity може призвести до меншого використання газу, навіть якщо для цього потрібно більше рядків коду. У цьому випадку це відбувається шляхом перемикання розташування масиву та замість використання його зі сховища і, отже, холодного доступу до нього кожного разу в циклі, він зберігає масив у пам’яті, де доступ до нього дешевший.

Порада №2: нульові чи ненульові значення та відшкодування газу

Gsset = 20 000 газу

Rsclear = {знижка на ціну виконання}

Зміна значення з 0 на ненульове в блокчейні Ethereum дороге, як ми бачимо в ціні Gsset, але зміна значення з ненульового на 0 може дати вам відшкодування у вартості газу згідно з кодом операції Rsclear. Щоб не скористатися перевагою відшкодування, встановлено, що ви можете отримати відшкодування не більше ніж 20% від загальної вартості транзакції.

Ви можете знайти такий сценарій у дуже поширеному сценарії на блокчейні, який полягає в оновленні балансу адрес у смарт-контрактах. Давайте розглянемо приклад кожного:





  • У першому прикладі контракту ZeroToNonZero від нуля до ненуля (5000 газу*) + від нуля до ненуля (20 000 газу) = 25 000 газу

  • У другому прикладі контракту NonZeroToZero, від нуля до нуля (5000 газу*) + від нуля до ненуля (20 000 газу) — Повернення (4800 газу) = 21 200 газу

*2100 (Gcolssload) + 2900 (Gsreset) = 5000 газів

Порада №3: ​​Порядок змінних стану має значення

Сховище схоже на структуру даних «ключ-значення», яка зберігає значення змінних стану смарт-контракту Solidity.

Ви можете розглядати сховище як масив, який допоможе візуалізувати це. Кожен простір у цьому «масиві» сховища називається слотом і містить 32 байти (256 біт) даних, і кожна змінна стану, оголошена в смарт-контракті, займатиме слот залежно від її позиції в декларації та її типу.

Не всі типи даних займають усі 32 байти кожного слота, оскільки є деякі типи даних (bool, uint8, адреса…), які займають менше цього.

Хитрість тут полягає в тому, що якщо дві/три чи більше змінних разом мають 32 байти або менше, компілятор solidity спробує упакувати їх разом в один слот, але ці змінні мають бути визначені одна біля одної.





Тут ми використовуємо типи даних bool (1 байт), адреса (20 байт) і uint256 (32 байти). Отже, знаючи розмір цих змінних, ви можете легко зрозуміти, що в першому прикладі в контракті TwoSlots, оскільки ми маємо bool і адресу разом (1 + 20 = 21 байт, що менше 32 байтів), вони займатимуть один слот. У контракті ThreeSlots, оскільки bool і uint256 не можуть бути в одному слоті (1 + 32 = 33 байти, що перевищує ємність слота), загалом ми будемо використовувати три слоти.

Чому це так важливо?

Код операції SLOAD коштує 2100 газів і використовується для читання зі слотів зберігання, тому, якщо ви можете зберігати змінні в меншій кількості слотів, ви зрештою заощадите трохи газу.

Порада №4: uint256 дешевше, ніж uint8

У пораді №3 ми дізналися, що uint256 (256 біт = 32 байти) сам по собі займає слот, і ми також дізналися, що uint8 менше 32 байтів. Отже, незважаючи на те, що 8 біт є меншими за 256 біт, зрозуміло, чому uint256 дешевший?

Щоб зрозуміти, що важливо знати, що якщо змінна сама не заповнює весь слот і якщо цей слот не заповнюється жодною іншою змінною, EVM збирається заповнити решту решти бітів «0» щоб мати можливість ним маніпулювати.

Це додавання «0», виконане EVM, коштуватиме газу, а це означає, що для економії транзакційного газу краще використовувати uint256 замість uint8.

__________________

Сподіваємось, дізнавшись про ці поради щодо зменшення витрат на газ у ваших смарт-контрактах, ви також трохи дізналися про те, як працює EVM.

__________________

Twitter @TheBlockChainer, щоб знайти більше щоденних оновлень про смарт-контракти, безпеку Web3, Solidity, аудит смарт-контрактів тощо.

__________________