1

So as per the ABI encoding specifications mentioned in Solidity Docs, for a dynamic array, the data location (in bytes from start, for the data part) is specified at first, followed by the length of the array at the previously specified location, followed by the actual data values.

Example in docs:

Function to be called: function sam(bytes memory, bool, uint[] memory) public pure {}

Calldata bytes for sam("dave", true, [1, 2, 3]):

0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003

Here, the first set of bold bytes represents the location of the bytes value for "dave". The second set of bold values is the actual data (starting with the length of the data which is 4 here).

So, while interpreting the calldata, how does the EVM differ the location of the dynamic data from being just a normal variable value? i.e here, how is 0x00...60 is identified as a location value, instead of being maybe a static uint?

3
  • Location, Length, Data. Where is the problem? Why would it interpret the location value as anything other than location? Oct 21 '20 at 6:38
  • Here the set of bytes 0x00...60 represents the location, but a uint value of 96 would also resolve to 0x00...60, right? so here how would the EVM differentiate that it is a location value and not a uint with value 96? P.S: It might be that I am missing out on some facts here which led to this doubt, but I am kinda curious about this. Oct 21 '20 at 8:33
  • Because the location is defined to be the 1st uint, while the data is defined to start at the 3rd uint (after the location and the length). Oct 21 '20 at 8:38
0

Answering my own question.

So, I apparently missed the fact that the abi-encoding function follows the head-tail encoding mechanism. The abi-decoding function then keeps track of the parameter type- actually it checks if the data type has a predefined size, if not, then it treats the value in hand as a start position.

Here is a very clear pyethereum implementation of decode_abi.

This is the magical part of the function:

for i, typ in enumerate(types):
    if sizes[i] is None:
        start_positions[i] = big_endian_to_int(data[pos:pos + 32])
        j = i - 1
        while j >= 0 and start_positions[j] is None:
            start_positions[j] = start_positions[i]
            j -= 1
        pos += 32
    else:
        outs[i] = data[pos:pos + sizes[i]]
        pos += sizes[i]

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.