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 ?


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).

  • 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. – Pardeep Thakur May 4 '20 at 13:07
  • @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. – goodvibration May 4 '20 at 13:19
  • Thank you, I got it – Pardeep Thakur May 4 '20 at 14:59
  • @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. – rlyx31 yesterday

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:


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




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:

  • 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? – rlyx31 yesterday

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.