4-byte function identifiers
Ethereum function selectors
In a standard ABI-encoded function call, the first four bytes are the function selector. Compiler-generated dispatch code uses it to choose a function and decode its arguments, but Ethereum itself does not enforce this convention and the selector is not globally unique.
From signature to selector
Take the Keccak-256 hash of the UTF-8 canonical signature, then keep its first four bytes. Ethereum uses Keccak-256 here—not the standardized SHA3-256 variant.
- 1Write the canonical signature
transfer(address,uint256) - 2Hash that exact text with Keccak-256
0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b - 3Keep the first four bytes
0xa9059cbb
The selector is placed before the encoded arguments. This example encodes 10¹⁸ base units for transfer(address,uint256). A token UI would display that as one token only if the target token uses 18 decimals; neither the target nor its decimals are contained in these bytes. Line breaks only show the three parts.
a9059cbb selector
0000000000000000000000002222222222222222222222222222222222222222 to
0000000000000000000000000000000000000000000000000de0b6b3a7640000 amountWhat belongs in the canonical signature?
Include the function name and the canonical input types, in order, with no spaces. Leave out the function keyword, parameter names, data-location specifiers such as memory, calldata, or storage, return types, visibility, and state mutability. Changing an input type or its position changes the selector.
Expand Solidity type aliases before hashing manually: uint becomes uint256, int becomes int256, and address payable becomes address. A tuple is written using its component types, such as (address,uint256)[], rather than the word tuple[].
| Canonical signature | Selector | What changed |
|---|---|---|
| transfer(address,uint256) | 0xa9059cbb | ERC-20 transfer |
| approve(address,uint256) | 0x095ea7b3 | Different name |
| safeTransferFrom(address,address,uint256) | 0x42842e0e | Three inputs |
| safeTransferFrom(address,address,uint256,bytes) | 0xb88d4fde | Overload adds bytes |
The address supplies the context
Every contract that implements transfer(address,uint256) uses the same 0xa9059cbb selector. The destination address determines which contract receives the call; that contract’s deployed code determines whether the selector is implemented and what the function actually does.
This is why a transaction’s input data can suggest a function without identifying a token, protocol, or even the intended semantics. Those facts come from the target address, verified source code, and ABI—not from the four bytes alone.
Different signatures can collide
Four bytes allow only 2³² possible selectors. Keccak-256 still produces a 32-byte hash, but truncating it means unrelated signatures can share the same prefix. A known example is:
burn(uint256) → 0x42966c68
collate_propagate_storage(bytes16) → 0x42966c68A contract normally knows which schema applies because its dispatcher was compiled for the functions it implements. A general-purpose decoder does not have that context. It should therefore treat selector-database results as candidates, try the argument layouts, and preserve multiple valid interpretations instead of declaring the first text match authoritative.
Common selector questions
Do overloaded functions have different selectors?
Yes. Overloads share a name but have different input-type lists, so their canonical signatures—and therefore their selectors—are different.
Does every calldata payload start with a selector?
No. Standard ABI-encoded function calls do. Constructor arguments, plain ETH receive calls, and arbitrary fallback payloads do not have to follow this structure. Return data and event data use different conventions too.
Are event topics also function selectors?
No. A non-anonymous event normally places the full 32-byte Keccak-256 hash of its canonical event signature in topic zero. Custom errors do use a 4-byte selector, but it appears in revert data rather than call dispatch.
Can I trust a selector lookup result?
Treat it as a lead. Public databases map selectors to submitted signature text, and collisions are possible. A verified ABI for the target contract is stronger evidence; decoding and re-encoding the arguments can eliminate candidates that do not fit the bytes.
Continue learning
How Ethereum calldata works
Build real calls and see how selectors, 32-byte words, offsets, arrays, tuples, and nested calldata fit together.
Read guide →Practical decodingDecode calldata without an ABI
See what can be recovered from raw transaction input, how signature lookup works, and where a contract-specific ABI is still required.
Read guide →