1

I want to convert uint type data to bytes type in solidity. I've found a answer about this which is like below.

function toBytes(uint256 x) public pure returns (bytes memory b) {
    b = new bytes(32);
    assembly { mstore(add(b, 32), x) }
}

But this doesn't work like what I thought. For example, if I put 0x0000000000000000000000000000000000000000000000000000000000000abc to the input value, I expected to have a return value which looks like this 0xabc0000000000000000000000000000000000000000000000000000000000000. But this function returns same as input value which is 0x0000000000000000000000000000000000000000000000000000000000000abc. How could I convert 0x0000000000000000000000000000000000000000000000000000000000000abc this to 0xabc0000000000000000000000000000000000000000000000000000000000000 this in solidity?

6
  • Could you elaborate a bit more on what exactly you are trying to achieve? In your example byte boundaries are not preserved. Original uint has bytes 0a and bc, while resulting bytes has ab and c0. Commented Dec 24, 2019 at 6:39
  • @MikhailVladimirov I meant if I put the uint256 input value 0x0000000000000000000000000000000000000000000000000000000000000abc to a function, I want to receive 0xabc.
    – Jung Chun
    Commented Dec 24, 2019 at 6:50
  • 0xabc is not a valid bytes value, as it is 12 bit long, while each byte is 8 bits. So it is fractional number of bytes. Commented Dec 24, 2019 at 7:09
  • @MikhailVladimirov Oh OK, then I'll change my example to 0x000000000000000000000000000000000000000000000000000000000000abcd. I want to receive 0xabcd when I give an input value 0x000000000000000000000000000000000000000000000000000000000000abcd. But that function returns same as input value.
    – Jung Chun
    Commented Dec 24, 2019 at 7:38
  • 1
    But what would be correct output for the original example? I need this to understand the general rule. Commented Dec 24, 2019 at 9:00

2 Answers 2

0

What you are looking to do is called bit shifting. Solidity allows bit shifting using the << and >> operators.

For your example, the non-zero portion of 0x000000000000000000000000000000000000000000000000000000000000abcd is abcd which occupies 16 bits. Because a bytes32 is 256 bits long, you must shift 240 bits to return the desired value:

function toBytes(uint256 x) public pure returns (bytes32) {
    return bytes32(a) << 240;
}

Note that the above example only works when the initial value is 2 bytes long. If you are not certain of the length of your initial value, you can determine it using a for loop and some division:

function toBytes(uint256 a) public pure returns (bytes32) {
    uint i;
    for (i = 0; i < 33; i++) {
        if (a / 256**i == 0) break;
    }
    return bytes32(a) << (32-i)*8;
}

Further reading:

1
  • OP wants to convert to bytes not to bytes32. Commented Dec 24, 2019 at 14:58
0

What about this?

function toBytes(uint256 x) public pure returns (bytes memory b) {
  uint l = 32;

  if (x < 0x100000000000000000000000000000000) { x <<= 128; l -= 16; }
  if (x < 0x1000000000000000000000000000000000000000000000000) { x <<= 64; l -= 8; }
  if (x < 0x100000000000000000000000000000000000000000000000000000000) { x <<= 32; l -= 4; }
  if (x < 0x1000000000000000000000000000000000000000000000000000000000000) { x <<= 16; l -= 2; }
  if (x < 0x100000000000000000000000000000000000000000000000000000000000000) { x <<= 8; l -= 1; }
  if (x < 0x100000000000000000000000000000000000000000000000000000000000000) { x <<= 8; l -= 1; }

  b = new bytes (l);

  assembly { mstore(add(b, 32), x) }
}

For me it does:

0x0 -> 0x        (zero bytes)
0x1 -> 0x01      (1 byte)
0xFF -> 0xFF     (1 byte)
0x100 -> 0x0100  (2 bytes)
0xFFFF -> 0xFFFF (2 bytes)
etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.