uint vs uint256 -> Маленькая деталь Solidity, которая может привести к большому хейзенбагу

Если мы используем вызов делегата в Solidity, есть одна маленькая деталь, которая может привести к очень трудно обнаруживаемой ошибке.

В обычной ситуации, когда мы объявляем переменную как uint256, мы обычно пишем просто синтаксис uint public number;. И это будет восприниматься как псевдоним для uint256 public number;. Эффективнее писать просто uint и это наиболее используемый тип числа. И с этой точки зрения производительности абсолютно логично использовать неопределенное uint вместо uint256. Но если мы хотим сделать delegatcall и указываем только uint, то мы вызываем маленький, совершенно прозрачный и трудноуловимый хайзенбаг.

Вот пример:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
contract TestTemplate {

    uint public amount;
    address public sender;

    function writeTo (uint _amount) public {
        amount = _amount;
        sender = msg.sender;
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

А теперь контракт, из которого мы делаем этот delegatecall:

contract TestTwo {

    uint public amount;
    address public sender;


    function writeTo(address _to, uint _amount) public  { 
        (bool success, bytes memory data) = _to.delegatecall(abi.encodeWithSignature("writeTo(uint)", _amount));        
    }
}
Enter fullscreen mode Выйти из полноэкранного режима

Этот _to.delegatecall(abi.encodeWithSignature("writeTo(uint)", _amount)); имеет решающее значение для генерации такого типа ошибок. Потому что если мы используем просто uint, что является широко распространенной практикой использования аллисов вместо настоящего uint256, то у нас будут проблемы.

Но вместо этого, если мы используем: _to.delegatecall(abi.encodeWithSignature("writeTo(uint256)", _amount));
после этого мы будем жить долго и счастливо.

Теперь со стороны это выглядит как произвольное решение, что на уровне языка мы можем использовать один способ объявления переменной в одном случае и второй, более строгий, в другом. Скорее всего, есть какие-то более глубокие причины, связанные с дизайном языка, почему так происходит. Но с практической точки зрения это может быть немного сложно. Поэтому для последовательности я начинаю использовать только uint256 по всему борду, полностью избегая такого рода проблем.

Оцените статью
devanswers.ru
Добавить комментарий