1

I am working on translating code from Python to Solidity and everything has worked up until this last loop. Cannot figure out where the difference is in the code (besides the bytes being in decimal and hex encodings). Follows is the code in both languages and the outputs.

Python

outmasks = bytes([12, 11, 12, 14, 23, 8, 9, 9, 7, 3, 6, 5, 19, 19, 6, 6, 4, 6, 6, 0, 9, 6, 13, 14, 19, 2, 7, 4, 0, 0, 0, 12, 23, 8, 8, 10, 6, 14, 14, 9, 4, 5, 6, 5, 20, 11, 12, 11])

for cnt in range(0x30):
    outs |= outmasks[cnt] << 5*cnt

print(hex(outs))

0x5b174298a44b9c6521176000021c53734c9018c431a73298674a5177316c

Solidity

function test() public returns (bytes30 outs) {

    bytes memory outmasks = hex"0c0b0c0e1708090907030605131306060406060009060d0e130207040000000c1708080a060e0e0904050605140b0c0b";


    for (uint8 cnt = 0; cnt<48; cnt++) {
        outs |= outmasks[cnt] << 5*cnt;
    }
}

0x6c0000000000000000000000000000000000000000000000000000000000

1 Answer 1

2

This is what I came up with:

 function test() public returns (bytes30 outs) {

     bytes memory outmasks = hex"0c0b0c0e1708090907030605131306060406060009060d0e130207040000000c1708080a060e0e0904050605140b0c0b";

     for (uint8 cnt = 0; cnt<47; cnt++) {
         outs |= bytes30(outmasks[cnt]) >> (232 - 5 *cnt);
     }
     outs |= bytes30(outmasks[47]) << 3;
 }

The question would be now: WHY?

Your solution takes a byte from the outmask array. What you get is a byte value! We have 2 cases now:

  • cnt < 2: You shift within the byte range
  • cnt >= 2: You shift your value out of the byte range. That results in outmasks[cnt] << 5*cnt = 0x00

That is the reason why you get 0x6c0000000000000000000000000000000000000000000000000000000000


Now here is something I find very odd and can't explain why Solidity is doing that.

If you cast byte to byte30 it sets the value as MSB. (for example: 0x30 -> 0x300000000000000000000000000000000000000000000000000000000000). That is the reason why I have the right shift, instead of the left shift.


I hope you are able to follow it. I made it in a rush. Sorry

3
  • It is how padding works in solidity, bytesXX will pad to the left, and uintXX will pad to the right, ie bytes2(bytes1(0xFF)) -> 0xFF00 and uint16(uint8(0xFF)) -> 0x00FF.
    – Ismael
    Commented Nov 28, 2018 at 19:57
  • So it is a Solidity think?
    – Donut
    Commented Nov 28, 2018 at 20:13
  • Yes, it is a convention of Solidity. All data at the EVM level are 32 bytes.
    – Ismael
    Commented Nov 28, 2018 at 20:59

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.