В учебнике по токену Ethereum есть проверка на переполнение uint256.
function transfer(address _to, uint256 _value) {
/* Check if sender has balance and for overflows */
if (balanceOf[msg.sender] < _value || balanceOf[_to] + _value < balanceOf[_to])
throw;
/* Add and subtract new balances */
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
}
Я не нашел нигде упоминаний о защите от переполнения uint или недостатков безопасности в контрактах из-за них. Кажется, что оба были бы распространены, если бы это было проблемой.
Ага. Вот пример переполнения и потери значимости uint.
contract C {
// (2**256 - 1) + 1 = 0
function overflow() returns (uint256 _overflow) {
uint256 max = 2**256 - 1;
return max + 1;
}
// 0 - 1 = 2**256 - 1
function underflow() returns (uint256 _underflow) {
uint256 min = 0;
return min - 1;
}
}
Вы можете выполнить код здесь: https://remix.ethereum.org/#version=soljson-latest.js&gist=30378c5375f388a28572dd18d58f787f
Да, переполнение возможно, и будьте особенно осторожны при использовании, var
например:
В
for (var i = 0; i < arrayName.length; i++) { ... }
, тип i будет uint8, потому что это наименьший тип, который требуется для хранения значения 0. Если массив содержит более 255 элементов, цикл не завершится.
Использование uint i
(256 бит) позволяет избежать проблемы.
Примечание. EVM не допускает бесконечных вычислений, поэтому цикл будет потреблять весь газ, и транзакция будет завершена, а комиссионные по-прежнему будут выплачиваться майнеру.
Начиная с Solidity v0.8.0+ больше невозможно переполнить или опустить uint
s.
Если вы проверите ответ @Noah Thorp, вы увидите, что Solidity будет revert
и выдаст ошибку.
Прямо из документов :
Арифметические операции возвращаются при потере значимости и переполнении. Вы можете использовать unchecked { ... }, чтобы использовать предыдущее поведение переноса.
Теперь это делается автоматически!
Дракон пятого измерения