0

I have the following code:

function getBytes5() public returns (bytes5) {
    uint256 x = now;        
    bytes memory inBytes = new bytes(32);
    bytes5 outBytes5;
    assembly {
         mstore(add(inBytes, 32), x)
         outBytes5 := mload(add(add(inBytes, 27), 5))
    }
    return outBytes5;
}

Which firstly stores the blockchain timestamp now in the inBytes variable and then tries to convert it from bytes32 to bytes5. However, the result I get is:

{
    "0": "bytes5": 0x0000000000
}

My understanding is that mload loads the values at the given addresses and add(add(inBytes, 27), 5) will return the last 5 bytes of the inBytes variable. But maybe there's a flaw somewhere in there?

2

Your issue is with the location you're passing to mload. The memory addressing of inBytes is 32 bytes for the length, then the rest is the data. Since you're storing a uint256 at the 32 bytes after the length, the memory map is going to look something like this:

0x00 00 00 00 00 00 00 00 
0x00 00 00 00 00 00 00 20
0x00 00 00 00 00 00 00 00
0x00 00 00 00 5C 6E 24 39

When you call mload, you pass in add(add(inBytes, 27), 5), which is just inBytes+32, which loads the entire last 2 lines of the above hex. However, the way casting works, it takes the most significant bytes. Which is why outBytes5 ends up all 0's. It's loading this portion to the variable:

0x00 00 00 00 00 00 00 00

0x00 00 00 00 00 00 00 20

0x00 00 00 00 00 00 00 00

0x00 00 00 00 5C 6E 24 39

To fix this, just change the mload location so the 5 bytes are the most significant bytes. This should work:

outBytes5 := mload(add(add(inBytes, 32), 27))

That should load 0x005C6E2439 to outBytes5 in the above example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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