8

when I am using below function to convert bytes memory to address, this is working fine.

Suppose input to the function is 0X0000000000000000000000004af3246b4fff356261136f113411cb187134D675

I am getting the output 0x4af3246b4fff356261136f113411cb187134D675

    function bytesToAddress(bytes memory bys) public pure returns (address addr) {

        assembly {
             addr := mload(add(add(bys, 32), 0))
       }
    }

Can, anyone explain me, what actually happening ?

2 Answers 2

9

The expression add(bys, 32):

Returns a pointer to the actual data, which starts after the first 32 bytes in the bys array (those first 32 bytes contain the length of the bys array).


The expression mload(x):

Loads the data pointed to by x, so you can just as well use mload(add(bys, 32)), because there is no added value in doing x + 0.


The expression addr := y:

Stores the value of y into the variable addr (in your case, since the value of y is 32-byte long and the type of addr is 20-byte long, only the 20 least significant bytes are stored).

4
  • Okay ,but when I am giving 32 bytes (64 characters) input to the function having first 24 characters zeros ,, how I am getting 20 bytes (40 characters) as output. Commented May 4, 2020 at 13:07
  • 1
    @PardeepThakur: Just as you would whenever you assign a larger-type variable into a smaller-type variable, for example, uint16 x = 0x1234; and then uint8 y = x;. The value of y would be the value of the 8 lower bits of x, i.e., 0x34. The only thing is, that in pure Solidity, the compiler would ask you to explicitly cast x to the type of y, i.e., uint8 y = uint8(x);. And in assembly, the compiler performs the down-cast implicitly. Commented May 4, 2020 at 13:19
  • @goodvibration forgive me for this noob question, but what does bys refer to exactly in add(bys, 32)? You can't really add a bytes array type to the number 32 right.
    – Pottedtree
    Commented Jun 22, 2021 at 13:44
  • 1
    @rlyx31 You're adding 32bytes to bys which is a pointer to the byte array (basically saying "take the address of my byte array, then add 32 to this address and get what there") Commented Nov 19, 2021 at 12:47
3

You may meet the following code in many projects:

contract A {

    event Log(address addr);

    function() external {
        emit Log(bytesToAddress(msg.data));
    }

    function bytesToAddress(bytes memory source) public pure returns(address addr) {
        assembly {
            addr := mload(add(source, 0x14))
        }
    }
}

Actually source when meet in assembly refers to 52 bytes:

0000000000000000000000000000000000000000000000000000000000000020
4af3246b4fff356261136f113411cb187134D675

So shifting 0x14 bytes (20 bytes) means capturing this value:

                                        V
0000000000000000000000000000000000000000000000000000000000000020
4af3246b4fff356261136f113411cb187134D675
                                       ^

This:

0000000000000000000000204af3246b4fff356261136f113411cb187134D675

But since return type is address Solidity compiler inserts code to erase top-12 bytes of address:

addr = addr & ((1 << 160) - 1)

Which leads to:

0000000000000000000000204af3246b4fff356261136f113411cb187134D675
&
000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
=
0000000000000000000000004af3246b4fff356261136f113411cb187134D675
                      ^
3
  • Shouldn't the bytes type (in this case source) have a size that's a multiple of 32 bytes? Instead of the 52 bytes, source should be 64 bytes, with 0s appended at the end of the address?
    – Pottedtree
    Commented Jun 22, 2021 at 13:55
  • @rlyx31 for sure, the is padding to 64 with zeroes. But these bytes remain untouched in the proposed schema.
    – k06a
    Commented Jun 27, 2021 at 19:22
  • 1
    bytes should be right-padded in calldata, not left-padded Commented Aug 31, 2021 at 21:29

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.