Solidity – How to Decode encodePacked Data

abibytessolidity

I have two addresses, _token1 and _token2. I would like to pack them into bytes data to pass it to a function.

bytes memory params = abi.encode(_token1, _token2);

The obtained params is the concatenation of zero-padded data.

This can be decoded in a different function like this:

(address token1, address token2) = abi.decode(params, (address, address));

Since one address is 20 bytes, which is smaller than 32 bytes, we can get a short bytes by abi.encodePacked(_token1, _token2). My question is how can I decode this encodePacked data?

Best Answer

You can do it only in assembly.

This is an example using two addresses. packed is formed by 32 bytes for length + 20 bytes for first address + 20 bytes for second address. By doing mload(add(packed, ADDRESS_LENGTH)) we end up reading 12+20 bytes, where the last 20 is the first address; since the variable x is of type address, the first 12 bytes are automatically dropped. Same reasoning for the second address.

    uint256 constant ADDRESS_LENGTH = 0x14;

    function testDecodePacked(address _x, address _y) external view returns(address, address) {
        bytes memory packed = abi.encodePacked(_x, _y);

        address x;
        address y;
        assembly {
            x := mload(add(packed, ADDRESS_LENGTH))
            y := mload(add(packed, mul(ADDRESS_LENGTH, 2)))
        }

        require((x == _x) && (y == _y));
        return (x, y);
    }