Можливо, ви натрапляли на кілька порад 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, аудит смарт-контрактів тощо.
__________________