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?
location
is defined to be the 1st uint, while thedata
is defined to start at the 3rd uint (after thelocation
and thelength
).