5

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?

3 Answers 3

4
function func(bytes calldata data) external {
    bytes4 selector = bytes4(data[:4]);
}

Also works for calldata, if you don't feel like using Yul

1
  • 1
    Thanks Ryan for your answer. I will mark this as the accepted answer because this is a more secure way of accessing the first 4 bytes (see this GitHub issue). Commented Jan 18, 2023 at 9:37
7

Jan 2023

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.

Oct 2021

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.

2

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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.