Contract ABI (Application Binary Interface)
A contract ABI defines how to encode function calls and decode return values when interacting with an Ethereum smart contract.
Key Takeaways
- A contract ABI is a JSON specification that describes a smart contract's external interface: its functions, events, errors, and their parameter types. Without it, applications cannot encode transactions or decode responses.
- ABI encoding converts human-readable function calls into raw calldata by combining a 4-byte function selector (derived from the keccak-256 hash of the function signature) with encoded arguments padded to 32-byte boundaries.
- Every wallet, dApp, and developer tool depends on the ABI to construct transactions, parse event logs, and interpret revert errors: sending a transaction with the wrong ABI leads to reverts, silent failures, or unintended state changes.
What Is a Contract ABI?
A contract ABI (Application Binary Interface) is the standard way to interact with smart contracts in the Ethereum ecosystem. It acts as a translation layer between human-readable function calls and the raw bytecode that the Ethereum Virtual Machine (EVM) executes. Think of it as an API specification for a smart contract: it tells external software exactly which functions exist, what parameters they accept, and what they return.
The ABI is generated automatically when Solidity source code is compiled. The compiler analyzes every public and external function, event, error, and the constructor, then outputs a JSON array describing each interface element. This JSON is what wallets, dApps, block explorers, and developer libraries use to interact with deployed contracts. The ABI captures only the external interface: it contains no implementation logic, storage layout, or private function details.
Without an ABI, interacting with a contract would require manually constructing raw hexadecimal calldata: computing function selectors, padding arguments to 32-byte boundaries, and decoding return values byte by byte. The ABI makes this process automatic and reliable.
How It Works
ABI encoding follows a precise specification maintained in the Solidity documentation. The process converts a function call into a byte sequence that the EVM can execute.
Function Selectors
Every function call begins with a 4-byte function selector. This selector is computed by taking the first 4 bytes of the keccak-256 hash of the function's canonical signature. The canonical signature uses the function name followed by parenthesized parameter types, separated by commas with no spaces:
// Canonical signature → keccak-256 hash → first 4 bytes
transfer(address,uint256) → 0xa9059cbb
balanceOf(address) → 0x70a08231
approve(address,uint256) → 0x095ea7b3When a transaction hits a contract, the EVM reads the first 4 bytes of calldata and compares them against a dispatch table compiled into the contract bytecode. If a match is found, execution jumps to that function's code. If no match is found, the contract's fallback function executes (or the transaction reverts if no fallback exists).
Parameter Encoding
After the 4-byte selector, function arguments are ABI-encoded as a tuple. Every value is padded to 32-byte (256-bit) word boundaries. The encoding distinguishes between static and dynamic types:
- Static types (uint256, address, bool, bytes32): encoded directly in place, left-padded with zeros to fill 32 bytes
- Dynamic types (string, bytes, dynamic arrays): encoded using a head/tail mechanism where the head contains a 32-byte offset pointer and the tail contains a length prefix followed by the actual data
For example, calling transfer(address,uint256) with a recipient address and an amount of 100 tokens produces calldata structured as:
0xa9059cbb // function selector (4 bytes)
0000000000000000000000005B38Da6a701c568545dCfcB03FcB875f56beddC4 // address, left-padded
0000000000000000000000000000000000000000000000000000000000000064 // uint256 value 100ABI Entry Types
The ABI JSON array contains different entry types, each describing a distinct part of the contract interface:
| Type | Purpose | Key Fields |
|---|---|---|
| function | Callable contract methods | name, inputs, outputs, stateMutability |
| event | Emitted log entries | name, inputs (with indexed flag), anonymous |
| error | Custom revert reasons (Solidity 0.8.4+) | name, inputs |
| constructor | Deployment parameters | inputs, stateMutability |
| fallback | Handles unmatched selectors | stateMutability |
| receive | Handles plain Ether transfers | stateMutability (always payable) |
Each function entry includes a stateMutability field indicating whether it reads state (view), modifies state (nonpayable), accepts Ether (payable), or does neither (pure). This tells wallets whether to send a transaction or make a free read-only call.
ABI JSON Example
A simple ERC-20 token's ABI includes entries like:
[
{
"type": "function",
"name": "transfer",
"inputs": [
{ "name": "to", "type": "address" },
{ "name": "amount", "type": "uint256" }
],
"outputs": [{ "name": "", "type": "bool" }],
"stateMutability": "nonpayable"
},
{
"type": "event",
"name": "Transfer",
"inputs": [
{ "name": "from", "type": "address", "indexed": true },
{ "name": "to", "type": "address", "indexed": true },
{ "name": "value", "type": "uint256", "indexed": false }
]
},
{
"type": "error",
"name": "InsufficientBalance",
"inputs": [
{ "name": "available", "type": "uint256" },
{ "name": "required", "type": "uint256" }
]
}
]Event Log Decoding
Events are a critical part of the ABI. When a contract emits an event, the EVM writes log entries with up to four "topics" and a data field. The first topic is the keccak-256 hash of the event signature ( unless the event is declared anonymous). Indexed parameters become additional topics, while non-indexed parameters are ABI-encoded together in the data field.
dApps use the ABI to decode these logs into structured data. For example, when monitoring ERC-20 transfers, an application matches the Transfer event signature hash against topics[0], extracts the sender and recipient from topics[1] and topics[2], and decodes the transfer amount from the data field.
From Source Code to ABI
The ABI is a byproduct of compiling Solidity (or Vyper) source code. The compiler extracts the external interface and outputs it as a JSON artifact alongside the contract bytecode. Common toolchains generate ABIs automatically:
- Solidity compiler:
solc --abi Contract.soloutputs the ABI JSON directly - Hardhat:
npx hardhat compileplaces ABIs inartifacts/ - Foundry:
forge buildproduces ABIs in theout/directory
Once a contract is deployed, its ABI can also be retrieved from block explorers (if the source code was verified) or reverse-engineered from the deployed bytecode by analyzing the function dispatch table. However, reverse-engineered ABIs lose parameter names since those are not stored on-chain.
How Wallets and dApps Use the ABI
Every interaction between a user and a smart contract flows through the ABI. Developer libraries like ethers.js and web3.js abstract this process into simple JavaScript calls:
// ethers.js uses the ABI to construct calldata automatically
const contract = new ethers.Contract(address, abi, signer);
await contract.transfer(recipientAddress, amount);
// Under the hood:
// 1. Looks up "transfer(address,uint256)" in the ABI
// 2. Computes selector: 0xa9059cbb
// 3. ABI-encodes [recipientAddress, amount]
// 4. Sets tx.data = selector + encodedParams
// 5. Sends via eth_sendTransactionThe ABI also enables wallets to show users meaningful information before they sign. Instead of displaying raw hexadecimal calldata, a wallet with the contract's ABI can decode the calldata and show: "Transfer 100 USDC to 0x5B38...". This is what makes transaction simulation possible: tools decode pending transactions using the ABI to predict their effects before execution.
Token approvals are another common ABI-driven interaction. When a user approves a DeFi protocol to spend their tokens, the wallet encodes an approve(address,uint256) call using the ERC-20 ABI. Without the correct ABI, the wallet cannot construct this call properly, and the user cannot interact with the protocol.
Use Cases
DeFi Protocol Integration
DeFi applications depend on ABIs to compose interactions across multiple contracts. A single swap on a decentralized exchange might require encoding calls to a router contract, a liquidity pool, and one or more token contracts. Each call uses the respective contract's ABI to construct the correct calldata. Protocol aggregators and DEX aggregators maintain ABI libraries for hundreds of contracts to route transactions optimally.
Block Explorer Verification
When developers verify their contract source code on block explorers like Etherscan, the explorer compiles the code and publishes the resulting ABI. This allows anyone to read the contract's functions, call view methods directly from the explorer, and decode historical transactions and event logs. Verified ABIs are a cornerstone of blockchain transparency.
Wallet Transaction Decoding
Modern wallets use ABIs to protect users from blind signing. By maintaining a registry of known contract ABIs, wallets can decode incoming transaction requests and display human-readable descriptions. EIP-7896 (proposed in 2025) aims to formalize this by letting dApps attach ABI JSON directly to transaction requests, enabling wallets to decode any transaction without needing a pre-existing ABI registry.
Cross-Chain Applications
The ABI specification originated on Ethereum but is used across all EVM-compatible chains. Applications interacting with smart contracts on networks like Solana (via Neon EVM) or rollups like Arbitrum and Optimism use the same ABI encoding standard. This makes cross-chain development more consistent for EVM-based ecosystems.
Risks and Considerations
ABI Mismatch and Stale ABIs
Using an incorrect or outdated ABI is one of the most common sources of failed transactions. If a contract has been upgraded behind a proxy but the dApp still uses the old implementation's ABI, function selectors may not match, parameters may be misaligned, or new functions may be invisible. The transaction either reverts or, worse, executes an unintended function whose selector happens to collide.
Selector Collisions
Because function selectors are only 4 bytes (roughly 4.3 billion possible values), different function signatures can produce the same selector. While the Solidity compiler prevents collisions within a single contract, malicious contracts can deliberately create functions with selectors that match common operations like transfer. This can be exploited in phishing attacks where a transaction appears to do one thing but actually executes a different function.
Blind Signing Without ABI
When a wallet lacks the ABI for a contract, it cannot decode the transaction calldata. Users see only raw hexadecimal data and must either trust the dApp or refuse to sign. This "blind signing" problem has enabled numerous phishing attacks where malicious dApps trick users into signing token approvals or other dangerous transactions disguised as benign operations.
ABI Does Not Guarantee Safety
The ABI describes what a contract's functions look like, not what they do. A function named claimRewards could internally drain the caller's tokens. The ABI provides transparency into the interface but not the implementation. Tools like transaction simulation and smart contract audits are needed to verify actual behavior. Understanding the ABI is a necessary first step, but wallet security requires multiple layers of defense.
Why It Matters
The contract ABI is foundational infrastructure for the entire EVM ecosystem. Every token transfer, swap, NFT mint, and governance vote flows through ABI encoding. As decentralized applications grow more complex and traditional finance converges with DeFi, the ABI remains the critical bridge between user intent and on-chain execution. For builders working across Bitcoin and Ethereum ecosystems, understanding how ABIs work is essential for designing interoperable payment flows and contract interactions.
This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.