Given the following function:
function getArrayItems(bytes calldata) external returns (
bytes4 _signature,
bytes32 _wutIsThis,
bytes32 _length,
bytes32 _firstItem
) {
assembly {
_signature := calldataload(0x00) // trim the first 4 bytes
_wutIsThis := calldataload(0x04)
_length := calldataload(0x24)
_firstItem := calldataload(0x44)
}
}
I get the following output when I run the code in remix with the input 0xcafe
:
{
"0": "bytes4: _signature 0x38626302",
"1": "bytes32: _wutIsThis 0x0000000000000000000000000000000000000000000000000000000000000020",
"2": "bytes32: _length 0x0000000000000000000000000000000000000000000000000000000000000002",
"3": "bytes32: _firstItem 0xcafe000000000000000000000000000000000000000000000000000000000000"
}
I fully understand the 1st, 3rd and 4th items. _length
was tricky, but according to the docs:
The length of a dynamic array is stored at the first slot of the array and followed by the array elements.
It's the 2nd item, _wutIsThis
, that is causing me trouble. My hunch is that it's about the data location of the array. That is, data is offset by 0x0000000000000000000000000000000000000000000000000000000000000020
, which means that the first item of the array is located 32 bytes after the said location's position in calldata (I know, this is so meta).
Is that correct? If yes, why do we do this and where can I find some further documentation? The solidity docs on type data location are a bit vague and only explain that reference types must specify a keyword (memory
, storage
or keyword
).