Skip to main content

Try it Live

Run ABI examples in the interactive playground
Conceptual guide - For encoding rules, see ABI Encoding.

Overview

Selectors identify functions, events, and errors in Ethereum. They are derived from canonical signatures using keccak256.

Quick Start

import { Abi } from '@tevm/voltaire/Abi';

const transfer = {
  type: 'function',
  name: 'transfer',
  inputs: [
    { type: 'address', name: 'to' },
    { type: 'uint256', name: 'amount' }
  ],
  outputs: [{ type: 'bool' }]
} as const;

const selector = Abi.Function.getSelector(transfer);
// 0xa9059cbb

Canonical Signatures

Signatures are generated from the canonical type list:
  • No whitespace
  • Use full size types (uint256, int256)
  • Tuples use parentheses: foo((uint256,address))
  • Arrays include brackets: foo(address[])
const sig = Abi.Function.getSignature(transfer);
// "transfer(address,uint256)"

Event Topic0 and Anonymous Events

Non-anonymous events include topic0 = keccak256(signature). Anonymous events omit topic0 entirely, so all topics are indexed parameters only.
const anonymous = {
  type: 'event',
  name: 'Log',
  anonymous: true,
  inputs: [{ type: 'uint256', name: 'id', indexed: true }]
} as const;

Selector Collisions

Function selectors are 4 bytes, so collisions are possible. You can scan an ABI for collisions:
import { Abi } from '@tevm/voltaire/Abi';

const hasCollisions = Abi.hasSelectorCollisions(erc20Abi);
const collisions = Abi.findSelectorCollisions(erc20Abi);
Event selectors are 32 bytes and effectively collision-free.

Common Selectors

ERC-20 functions:
  • 0xa9059cbb - transfer(address,uint256)
  • 0x23b872dd - transferFrom(address,address,uint256)
  • 0x095ea7b3 - approve(address,uint256)
  • 0x70a08231 - balanceOf(address)
ERC-20 events:
  • 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef - Transfer(address,address,uint256)
  • 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925 - Approval(address,address,uint256)

Custom Hash Functions

Use selector factories when you need a custom keccak256 implementation:
import { Function } from '@tevm/voltaire/Abi';

const getSelector = Function.GetSelector({
  keccak256String: (value) => myKeccak256(value)
});

const selector = getSelector(transfer);

See Also