It is common for calldata to be encoded as bytes calldata
when developing contracts in Solidity.
I need to extract the function selector from such a bytes var. What's the best way to load the first 4 bytes?
function func(bytes calldata data) external {
bytes4 selector = bytes4(data[:4]);
}
Also works for calldata, if you don't feel like using Yul
As per the bug report in this GitHub issue, it is more secure to use Ryan Sea's answer, which uses high-level Solidity to access the first 4 bytes in the data
bytes array.
Most gas-efficient way is to use inline assembly:
function foo(bytes calldata data) external payable {
bytes4 selector;
assembly {
selector := calldataload(data.offset)
}
// ...
}
The offset suffix is a special property that we need to use in inline assembly to be able to read high-level storage variables.
There's an even faster way to get the first 4 bytes of calldata: accessing the global variable msg.sig will return the first 4 bytes of calldata and give you access to the function selector.
This is the safest, easiest, and cleanest way to retrieve function selectors in solidity.
Have fun coding!