Большая часть газовых расходов Ethereum сосредоточена вокруг хранения. Каждая операция, изменяющая состояние (хранилище) сети Ethereum, как правило, требует больших затрат. В результате, концентрация внимания на том, как хранятся и доступны данные, может привести к значительному снижению затрат. В этой сессии мы рассмотрим несколько способов оптимизации хранения данных с помощью Remix.
Блокчейн Ethereum обеспечивает постоянное хранение данных. Все, что сохраняется в блокчейне, будет доступно до тех пор, пока существует блокчейн, но за это постоянство приходится платить. Оптимизация хранения не только снижает затраты, но и обеспечивает эффективное использование глобального состояния Ethereum.
Solidity хранит переменные в слотах. Каждый слот имеет размер 32 байта. Если переменные умещаются в одном слоте, их можно прочитать или обновить с помощью одной операции SLOAD или SSTORE, соответственно.
Рассмотрим два контракта:
Solidity
// Без оптимизации
pragma solidity ^0.8.9;
contract UnoptimizedStorage {
uint256 public value1;
uint256 public value2;
}
Solidity
// С оптимизацией
pragma solidity ^0.8.9;
contract OptimizedStorage {
uint128 public value1;
uint128 public value2;
}
Разверните оба контракта в Remix и обратите внимание на газовые различия при взаимодействии с их переменными.
В оптимизированном варианте и value1
, и value2
делят один 32-байтовый слот.
Когда Вы закончили использовать слот для хранения данных, особенно временного хранения, Вы можете удалить или обнулить слот, чтобы получить возврат газа.
Solidity
pragma solidity ^0.8.9;
contract RefundExample {
uint256 public temporaryData;
function storeTemporaryData(uint256 data) public {
temporaryData = data;
}
function clearTemporaryData() public {
delete temporaryData;
}
}
Разверните этот контракт в Remix.
Сохраните некоторые временные данные, а затем очистите их.
Проверьте стоимость газа. Обратите внимание на возврат газа, который Вы получаете за операцию удаления
.
Если к данным не нужно обращаться на цепи, подумайте о том, чтобы не хранить их, а регистрировать как событие. События гораздо дешевле, чем операции хранения.
Solidity
pragma solidity ^0.8.9;
contract EventExample {
event DataStored(uint256 data);
function storeData(uint256 data) public {
emit DataStored(data);
}
}.
Разверните контракт и взаимодействуйте с ним в Remix.
Обратите внимание на более низкую стоимость газа по сравнению с хранением.
Теперь, когда Вы освоили некоторые фундаментальные подходы к оптимизации хранения, очень важно практиковаться. Ознакомьтесь с предложенными примерами и поэкспериментируйте с созданием своих собственных. В следующей сессии мы более подробно рассмотрим оптимизацию видимости функций и повторное использование кода с помощью библиотек. Имейте в виду, что оптимизация - это и искусство, и наука. Продолжайте экспериментировать!
Большая часть газовых расходов Ethereum сосредоточена вокруг хранения. Каждая операция, изменяющая состояние (хранилище) сети Ethereum, как правило, требует больших затрат. В результате, концентрация внимания на том, как хранятся и доступны данные, может привести к значительному снижению затрат. В этой сессии мы рассмотрим несколько способов оптимизации хранения данных с помощью Remix.
Блокчейн Ethereum обеспечивает постоянное хранение данных. Все, что сохраняется в блокчейне, будет доступно до тех пор, пока существует блокчейн, но за это постоянство приходится платить. Оптимизация хранения не только снижает затраты, но и обеспечивает эффективное использование глобального состояния Ethereum.
Solidity хранит переменные в слотах. Каждый слот имеет размер 32 байта. Если переменные умещаются в одном слоте, их можно прочитать или обновить с помощью одной операции SLOAD или SSTORE, соответственно.
Рассмотрим два контракта:
Solidity
// Без оптимизации
pragma solidity ^0.8.9;
contract UnoptimizedStorage {
uint256 public value1;
uint256 public value2;
}
Solidity
// С оптимизацией
pragma solidity ^0.8.9;
contract OptimizedStorage {
uint128 public value1;
uint128 public value2;
}
Разверните оба контракта в Remix и обратите внимание на газовые различия при взаимодействии с их переменными.
В оптимизированном варианте и value1
, и value2
делят один 32-байтовый слот.
Когда Вы закончили использовать слот для хранения данных, особенно временного хранения, Вы можете удалить или обнулить слот, чтобы получить возврат газа.
Solidity
pragma solidity ^0.8.9;
contract RefundExample {
uint256 public temporaryData;
function storeTemporaryData(uint256 data) public {
temporaryData = data;
}
function clearTemporaryData() public {
delete temporaryData;
}
}
Разверните этот контракт в Remix.
Сохраните некоторые временные данные, а затем очистите их.
Проверьте стоимость газа. Обратите внимание на возврат газа, который Вы получаете за операцию удаления
.
Если к данным не нужно обращаться на цепи, подумайте о том, чтобы не хранить их, а регистрировать как событие. События гораздо дешевле, чем операции хранения.
Solidity
pragma solidity ^0.8.9;
contract EventExample {
event DataStored(uint256 data);
function storeData(uint256 data) public {
emit DataStored(data);
}
}.
Разверните контракт и взаимодействуйте с ним в Remix.
Обратите внимание на более низкую стоимость газа по сравнению с хранением.
Теперь, когда Вы освоили некоторые фундаментальные подходы к оптимизации хранения, очень важно практиковаться. Ознакомьтесь с предложенными примерами и поэкспериментируйте с созданием своих собственных. В следующей сессии мы более подробно рассмотрим оптимизацию видимости функций и повторное использование кода с помощью библиотек. Имейте в виду, что оптимизация - это и искусство, и наука. Продолжайте экспериментировать!