15

Hey is there a way to convert bytes to uint in Solidity?

arete
  • 599
  • 1
  • 5
  • 15
  • Could you explain what conversion you would like? Best if you can give an example of a bytes value and the corresponding uint value you would like to see. – user19510 Jun 14 '18 at 14:52

5 Answers5

11

You can use this function to convert bytes to uint:

pragma solidity ^0.4.23;

contract mycontract {

function bytesToUint(bytes b) public returns (uint256){
    uint256 number;
    for(uint i=0;i<b.length;i++){
        number = number + uint(b[i])*(2**(8*(b.length-(i+1))));
    }
    return number;
}

}

Updated function for solidity ^0.8.11

function bytesToUint(bytes memory b) internal pure returns (uint256){
        uint256 number;
        for(uint i=0;i<b.length;i++){
            number = number + uint(uint8(b[i]))*(2**(8*(b.length-(i+1))));
        }
    return number;
}

The amount of gas used depends on the length of your bytes variable, but this is cheap. Converting a bytes variable of length 20 uses about 420 gas.

Hope this helps

Jaime
  • 8,340
  • 1
  • 12
  • 20
  • Getting an error in Remix: TypeError: Return argument type bytes memory is not implicitly convertible to expected type uint256 – arete Jun 14 '18 at 15:02
  • Can you show me your code?, this works for me well in remix, I put the whole code so you can just copy and paste it. Let me know – Jaime Jun 14 '18 at 15:13
  • Oh there you go. I think your first post had the return value as "b". This works. Thanks! – arete Jun 14 '18 at 15:25
10

Slicing an uint out of bytes using inline assembly

function sliceUint(bytes bs, uint start)
    internal pure
    returns (uint)
{
    require(bs.length >= start + 32, "slicing out of range");
    uint x;
    assembly {
        x := mload(add(bs, add(0x20, start)))
    }
    return x;
}
libertylocked
  • 1,368
  • 8
  • 16
6

A fully working modern solution can be found in this repository, authored by ConsenSys:

function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
    require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
    uint256 tempUint;
assembly {
    tempUint := mload(add(add(_bytes, 0x20), _start))
}

return tempUint;

}

The accepted answer is not working in Solidity ^0.5 anymore; it produces a type conversion error.

Paul Razvan Berg
  • 17,902
  • 6
  • 73
  • 143
Evgeniy
  • 161
  • 1
  • 3
1

If you know the bytes length(for instance address has 20 bytes), you can convert by casting

uint256 time = uint160(bytes20(0x2E4e72EDC83053F8ADE4a525191Ba7aBA086c067));

tonisives
  • 111
  • 2
1

Don't use byte-wise computation! it's very inefficient! The latest solidity allow you to do this:

To convert a general byte memory to uint:

function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
    require(b.length <= 32, "Bytes length exceeds 32.");
    return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
}

If you're unpacking a big bytes calldata (you know exactly how many bytes each slice has), you can also just cast it through bytesX as follow:

function decodeCompressedCalldata(bytes calldata compressed) internal {
    // convert to uint
    uint64 expiry = uint64(bytes8(compressed[0:8]));
// convert to uint -&gt; int
int a = int80(uint80(bytes10(compressed[8:18])));

}

Anton Cheng
  • 623
  • 6
  • 9