Function Selectors in Solidity – What They Are and Their Importance

abicalldatafunction-selector

I am reading an article, it says:

To enable deployment on the Ethereum platform, the contract functions
are compiled into EVM bytecode and a piece of code called function
selector is added, which serves as an entry point into the contract
code.

Can some body please tell me what is a function selector?

I tried google and found:

The first four bytes of the call data for a function call specifies
the function to be called. It is the first (left, high-order in
big-endian) four bytes of the Keccak-256 (SHA-3) hash of the signature
of the function. The signature is defined as the canonical expression
of the basic prototype without data location specifier, i.e. the
function name with the parenthesised list of parameter types.
Parameter types are split by a single comma – no spaces are used.

I can't understand what is call data?

Some body please guide me.

Zulfi.

Best Answer

A function selector allows you to perform dynamic invocation of a function, based on the name of the function and the type of each one of the input arguments.

For example, suppose you have:

contract Contract1 {
    function func(uint256 x, uint8 y) public returns (uint32, uint32) {...}
}

contract Contract2 {
    Contract1 public contract1 = new Contract1();
    function func() public returns (uint32, uint32) {...}
}

Then you can call Contract1.func from Contract2.func as follows:

function func() public returns (uint32, uint32) {
    uint32[2] memory ret;

    address dest = address(contract1);

    bytes4 selector = contract1.func.selector;
    // Or bytes4 selector = bytes4(uint256(keccak256("func(uint256,uint8)") >> 224));

    bytes memory data = abi.encodeWithSelector(selector, uint256(789), uint8(123));

    assembly {
        let success := call(
            gas,           // pass the remaining gas to the function
            dest,          // the address of the contract1 instance
            0,             // pass 0 wei to the function
            add(data, 32), // the actual data starts after the length of 'data'
            mload(data),   // the length of 'data' appears at the first 32 bytes
            ret,           // the address of the output
            8              // the size of the output
        )
        if iszero(success) {
            revert(0, 0)
        }
    }

    return (ret[0], ret[1]);
}

If the invoked function is constant (either pure or view), then you can also use staticcall.

The example above is in assembly, but you can also use call directly in solidity.

I think that staticcall should be available starting from solidity v0.5.0.

Related Topic