Можно ли переполнить uints?

В учебнике по токену 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 или недостатков безопасности в контрактах из-за них. Кажется, что оба были бы распространены, если бы это было проблемой.

Ответы (3)

Ага. Вот пример переполнения и потери значимости 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

Нарушая изменения в Solidity v0.8.0+, они возвращают переполнения со стандартной панической ошибкой, прямо из документации... «Неудачные утверждения и другие внутренние проверки, такие как деление на ноль или арифметическое переполнение, не используют недопустимый код операции, а вместо этого используют код операции возврата. . В частности, они будут использовать данные об ошибках, эквивалентные вызову функции Panic(uint256) с кодом ошибки, характерным для конкретных обстоятельств».

Да, переполнение возможно, и будьте особенно осторожны при использовании, var например:

В for (var i = 0; i < arrayName.length; i++) { ... }, тип i будет uint8, потому что это наименьший тип, который требуется для хранения значения 0. Если массив содержит более 255 элементов, цикл не завершится.

Использование uint i(256 бит) позволяет избежать проблемы.

Примечание. EVM не допускает бесконечных вычислений, поэтому цикл будет потреблять весь газ, и транзакция будет завершена, а комиссионные по-прежнему будут выплачиваться майнеру.

Начиная с Solidity v0.8.0+ больше невозможно переполнить или опустить uints.

Если вы проверите ответ @Noah Thorp, вы увидите, что Solidity будет revertи выдаст ошибку.

Прямо из документов :

Арифметические операции возвращаются при потере значимости и переполнении. Вы можете использовать unchecked { ... }, чтобы использовать предыдущее поведение переноса.

Теперь это делается автоматически!