В Solidity оптимизация использования газа очень важна, поскольку каждая транзакция потребляет газ. Вот несколько советов, которые помогут оптимизировать расход газа:
•Используйте меньшие типы данных:меньшеданные Тип потребляет меньшеgas。Например,использоватьuint8
заменятьuint256
может спастиgas。•использоватьcalldata
заменятьmemory
:существоватьSolidityсередина,calldata
является неизмененным、только чтениеданныехранилище Расположение,Используется для параметра Function. Доступно только во внешней функции.,То есть,Толькоexternal
изменено модификаторомфункцияталантиспользоватьcalldata
。иmemory
по сравнению с,calldata
дасуществоватьEVMсреда выполнениясередина,Не обязательно начинать схранилищеили Памятьсерединачитатьданные。•Избегайте дорогостоящих операций в циклах:существоватьциклсерединавыполнять дорогостоящие операции(Например, вызов внешних контрактов или запись переменных состояния.)будет потреблять многоgas。если возможно,Попробуйте выполнить эти операции вне цикла.
// Не рекомендуется
for (uint i = 0; i < array.length; i++) {
array[i] = someExternalContract.calculate(i);
}
// рекомендовать
uint[] memory results = someExternalContract.calculateAll(array.length);
for (uint i = 0; i < array.length; i++) {
array[i] = results[i];
}
•Используйте события вместо хранения данных:если тебе нужно толькосуществовать Доступ вне сетиданные,Тогда использование событий экономит газ больше, чем хранилищеданные. Стоимость газа на мероприятиях значительно ниже, чем на хранилищеданных.
// Не рекомендуется
uint public lastUpdated;
function update() public {
lastUpdated = now;
}
// рекомендовать
event Updated(uint timestamp);
function update() public {
emit Updated(now);
}
•Удалить ненужные данные:когда тебе что-то больше не нужноданныечас,использоватьdelete
Ключевые словаудалитьих можно вернутьgas。
mapping(address => uint) public balances;
function burn(address user, uint amount) public {
require(balances[user] >= amount, "Insufficient balance");
balances[user] -= amount;
if (balances[user] == 0) {
delete balances[user];
}
}
•Избегайте избыточного хранения данных:Если вам нужно прочитать одно и то же несколько разхранилищепеременная,Рассмотрите возможность помещения его в переменную памяти.
// Не рекомендуется
function calculate() public {
uint a = balances[msg.sender];
uint b = balances[msg.sender];
uint c = a + b;
}
// рекомендовать
function calculate() public {
uint balance = balances[msg.sender];
uint c = balance + balance;
}
•Используйте библиотечные функции:существоватьSolidityсередина,Функция библиотеки помогает нам повторно использовать код и оптимизировать потребление газа. Это связано с тем, что библиотечная функция рассматривается как встроенная функция на уровне EVM.,Таким образом, они обычно более экономичны, чем реализация той же логики непосредственно в контракте.
// определить библиотеку SafeMath
library SafeMath {
function mul(uint a, uint b) internal pure returns (uint) {
if (a == 0) {
return 0;
}
uint c = a * b;
require(c / a == b, "Multiplication overflow");
return c;
}
}
contract MyContract {
using SafeMath for uint;
uint public value;
function multiply(uint amount) public {
value = value.mul(amount); // мулфункция с использованием библиотеки SafeMath
}
}
•Используйте статические вызовы:Если вам нужно только прочитать другие контрактыданные,Такиспользоватьstaticcall
Сравниватьиспользоватьcall
Экономьте большеgas,потому чтоstaticcall
не изменит статус。•staticcall
Сравниватьcall
Экономьте большеgas,Есть две причины:•безопасность:потому чтоstaticcall
Невозможно изменить статус,Поэтому это не вызывает сложных изменений состояния.,Он не будет потреблять много газа. с другой стороны,call
Можно изменить статус,Поэтому это может вызвать сложные изменения состояния.,потреблять многоgas。•простота:staticcall
Просто нужно прочитатьданные,Следовательно, это менее трудоемко в вычислительном отношении.,Также он потребляет меньше газа. с другой стороны,call
может выполнить любую операцию,Включает в себя трудоемкие операции,поэтому это возможнобудет потреблять многоgas。•использоватьimmutable
иconstant
:если естьсуществовать Ценности, которые не изменятся в течение жизненного цикла контракта,Это нормальноиспользоватьimmutable
илиconstant
,Это экономит газ.
// Не рекомендуется
address public owner;
constructor() {
owner = msg.sender;
}
// рекомендовать
address public immutable owner;
constructor() {
owner = msg.sender;
}
•Оптимизировать массив:Если контрактсерединаиспользоватьмножество,Вы можете рассмотреть возможность использования сопоставления для выполнения операций «Оптимизировать массив».
// Не рекомендуется
uint[] public array;
function remove(uint index) public {
for (uint i = index; i<array.length-1; i++){
array[i] = array[i+1];
}
array.pop();
}
// рекомендовать
mapping(uint => uint) public map;
uint public size = 0;
function remove(uint index) public {
map[index] = map[size-1];
delete map[size-1];
size--;
}
•использоватьrequire
вместоassert
:require
иassert
можно использовать для проверки условий,ноrequire
существоватьнеудачачас Остаток будет возвращенgas,иassert
не будет。
// Не рекомендуется
function transfer(address to, uint amount) public {
assert(balances[msg.sender] >= amount);
balances[msg.sender] -= amount;
balances[to] += amount;
}
// рекомендовать
function transfer(address to, uint amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
}
Отказ от ответственности: эта работа распространяется под лицензией Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)[1]. Пожалуйста, укажите источник при ее использовании. Автор: мэнбин[2] блог: мэнбин[3] Гитхаб: mengbin92[4] cnblogs: Непреднамеренно полюбила воду[5] Сообщество разработчиков облачных технологий Tencent: Мюнстер[6]
[1]
С указанием авторства-Некоммерческая-ShareAlike 4.0 интернациональность (CC BY-NC-SA 4.0): https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh
[2]
mengbin: mengbin1992@outlook.com
[3]
mengbin: https://mengbin.top
[4]
mengbin92: https://mengbin92.github.io/
[5]
Влюбляюсь в воду нечаянно: https://www.cnblogs.com/lianshuiwuyi/
[6]
Мюнстер: https://cloud.tencent.com/developer/user/6649301