New to blockchain software development? Read my beginners guide here

How Solidity function selectors work

Created on September 2022 • Tags: solidityethereum

A technical guide about how function selectors work in Solidity


Table of Contents for How Solidity function selectors work


How selectors work

When you write Solidity code, you will write contracts with functions

contract Example {
function funcA() public {
}
function funcB(uint256 someNum) public {
}
}

When this gets compiled, the original names (funcA, funcB in the above example) do not get stored.

Instead each function is changed to a selector. Instead the first four bytes of a hash of the function (and arguments) are stored, and these are used when the functions are called.

In psuedocode, it looks like this:

var $funcANameAndArgs = 'funcA()';
var $funcBNameAndArgs = 'funcB(uint256)';

var $funcAHash = keccack256(funcANameAndArgs);
var $funcBHash = keccack256(funcBNameAndArgs);

var $selectorFuncA = firstFourBytes($funcAHash);
var $selectorFuncB = firstFourBytes($funcBHash);

It hashes the function name, and the types of any arguements (but not the names), and takes the first 4 bytes (8 characters in hex).

Note: If you define a function as function something(uint aNumber), then you have to hash something(uint256) (note the full uint256 is used, not just uint).

How to call another contract’s function, using a selector

You can use abi.encodeWithSignature

addr.call(abi.encodeWithSignature("transfer(address,uint256)", yourAddressVariable, yourAmountVariable))

Selectors for library functions

If you have a library, with a function that has a struct then the selector is generated in a different way.

Normally if you have a function that has a param that is a struct, the selector will be the first 4 bytes of the keccak256 hash of each variable type within a struct.

e.g.

struct CoolStruct {
uint256 coolValue;
uint256 otherCoolValue;
}

function getHash(CoolStruct memory self) public pure returns (bytes32 hash) {
hash = keccak256(abi.encodePacked(
self.coolValue
));
}

You’d expect the selector to be keccak256("getHash((uint256,uint256))"), which is 0x31183ed7

but in a library it is the first four bytes of keccak256("getHash(LibStructTest.CoolStruct)") (0x54d08d7a)

For more info about this (and also the source that I found / copied examples from) is https://github.com/ethereum/solidity/issues/6420

Spotted a typo or have a suggestion to make this crypto dev article better? Please let me know!

See all posts (70+ more)

See all posts (70+ more)

Was this post helpful? 📧

If you liked this content and want to receive emails about future posts like this, enter your email. I'll never spam you.

Or follow me on @CryptoGuide_Dev on twitter

By using this site, you agree that you have read and understand its Privacy Policy and Terms of Use.
Use any information on this site at your own risk, I take no responsibility for the accuracy of safety of the information on this site.