Как использовать функцию BytesToUint в Solidity (ту, что со сборкой)? - PullRequest
0 голосов
/ 04 августа 2020

Я использовал следующую функцию для преобразования байтов в uint:

function bytesToUint(bytes b) public pure returns (uint){
    uint number;

    for(uint i=0;i<b.length;i++){
        number = number + uint(b[b.length-1-i])*(10**i);
    }

    return number;
}

Поскольку явное преобразование byte1 в uint больше не поддерживается, я нашел следующую альтернативу:

function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
    require(_bytes.length >= (_start + 32), "Read out of bounds");
    uint256 tempUint;

    assembly {
        tempUint := mload(add(add(_bytes, 0x20), _start))
    }

    return tempUint;
}

The bytes - это входные данные в функции ApproveAndCall токена ERC20

function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
    allowed[msg.sender][spender] = tokens;
    emit Approval(msg.sender, spender, tokens);
    ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
    return true;
}

, который отправляется на получение одобрения моего смарт-контракта.

function receiveApproval(address _from, uint _token, address _tokenContract, bytes memory _data) public {
    
    if(!ERC20Interface(_tokenContract).transferFrom(_from, address(this), _token)) {
        revert();
    }
    
    _0xChangeLib.place_sell_order(exchange, _from, _tokenContract, _token, _0xChangeLib.toUint256(_data, 0));

}

Может ли кто-нибудь объяснить, как работает этот новый BytesToUint256 ? Я не могу разобраться в коде сборки и в том, как использовать эту функцию. Я не понимаю аргумент uint256 _start. Я также не уверен, смогу ли я использовать тот же формат для ввода, что и использовал. В качестве аргумента я преобразовывал количество wei в байты, например 100 wei = 0x100, с простой функцией в javascript и отправлял его на адрес токена с помощью Web3. js.

Я бы хотел в пределах Функция ReceiveApproval смарт-контракта для вызова функции BytesToUint для дальнейшей обработки данных.

Заранее большое спасибо за вашу помощь!

1 Ответ

1 голос
/ 05 августа 2020

_start в основном указывает на индекс байта в массиве bytes, где начинается целочисленное значение. Первые 32 (или 0x20 в шестнадцатеричном формате) байта содержат длину массива bytes, а затем начинают целочисленное значение, которое сохраняется в следующих 32 байтах. Значение _start равно нулю, потому что второй набор из 32 байтов содержит нужное вам целочисленное значение. Вы можете по существу преобразовать эту функцию в это.

function toUint256(bytes memory _bytes)   
  internal
  pure
  returns (uint256 value) {

    assembly {
      value := mload(add(_bytes, 0x20))
    }
}

Что касается вашего комментария, то 0x0 будет означать, что массив байтов имеет длину 1, т.е. второй ноль, а оператор require ожидает длину не менее 32 .

...