what is an ABI?
an ABI — application binary interface — is the description of a smart contract's functions, events, and errors that lets off-chain code encode calls to it and decode what comes back. it is the contract between your application and the contract's on-chain bytecode.
why a contract needs an ABI
on-chain, a contract is just EVM bytecode, and a call to it is just a blob of bytes. the chain has no notion of function names or argument types — those exist only at the source level. to call balanceOf(0x…), a client has to know two things: the 4-byte function selector that identifies the function, and how to encode the address argument into bytes. the ABI supplies exactly that information, so libraries can turn a readable call into calldata and turn the returned bytes back into typed values.
what an ABI looks like
an ABI is a JSON array of fragments. each fragment has a type — function, event, error, constructor, fallback, or receive. a function fragment lists its name, its inputs and outputs (each a name and a type), and its stateMutability — view or pure for reads, nonpayable or payable for writes. a minimal ERC-20 balance lookup is one fragment:
{
"type": "function",
"name": "balanceOf",
"stateMutability": "view",
"inputs": [{ "name": "account", "type": "address" }],
"outputs": [{ "name": "", "type": "uint256" }]
}where ABIs come from
the solidity (or vyper) compiler emits the full ABI as part of its output, alongside the bytecode — that's the JSON you'll find in a build artifact's abifield or on a verified contract's explorer page. you don't need the whole thing to interact, though: a hand-written ABI containing only the functions you care about works fine. some tools also accept a human-readable ABI — an array of signature strings like function balanceOf(address) view returns (uint256) — which is equivalent to the JSON form.
try it
paste any contract's ABI into the read · write workbench to call its functions and send transactions, or use the calldata decoder to decode a transaction against it.