An ERC-20 token is a fungible digital asset issued on Ethereum that follows a shared interface defined by the ERC-20 standard. Every ERC-20 token behaves identically from the perspective of wallets and smart contracts: one unit is interchangeable with any other unit of the same token, and any application that understands the standard can interact with any compliant token without custom integration. USDC, USDT, and DAI are all ERC-20 tokens, and their combined circulating supply exceeds $271B as of Q1 2026 (DeFiLlama, April 2026).
The standard was proposed by Fabian Vogelsteller in November 2015 as Ethereum Improvement Proposal 20 and formalized with Vitalik Buterin. Before ERC-20 existed, every token issuer invented its own interface. Wallets had to ship custom code for each one, and decentralized exchanges couldn't trade tokens they hadn't explicitly integrated. ERC-20 solved that by specifying six required functions and two required events that every compliant contract must expose. The result is a shared vocabulary that allows a single DEX smart contract, a single wallet codebase, or a single cross-chain bridge to work with any ERC-20 token automatically.
What Is an ERC-20 Token?
An ERC-20 token is a fungible Ethereum asset whose smart contract implements six required functions and two standard events. Fungible means each unit is identical and interchangeable: 1 USDC equals every other 1 USDC. This stands in contrast to non-fungible tokens (NFTs), where each token has a unique identity and cannot be exchanged one-for-one.
The standard lives at EIP-20 on eips.ethereum.org, maintained by the Ethereum community. It does not require any central issuer registry. Any developer can deploy a contract that satisfies the six-function interface and immediately achieve compatibility with every ERC-20-aware application on Ethereum. As of Q1 2026, Ethereum hosts more than 500,000 ERC-20 token contracts (Etherscan, April 2026), ranging from billion-dollar stablecoins to project governance tokens with minimal circulating supply.
Fungibility is what makes ERC-20 tokens suited for payments, lending collateral, liquidity pool reserves, and stablecoin issuance. A DEX needs to know how to move tokens between accounts and check balances; ERC-20 provides exactly those operations in a consistent form. The ERC process itself is a broader framework for proposing changes to Ethereum's application layer, and ERC-20 is among the most widely adopted outputs of that process.
What Functions Does an ERC-20 Token Require?
ERC-20 defines six mandatory functions that every compliant contract must implement. Together they cover four operations: supply inspection (totalSupply), balance inspection (balanceOf), direct transfer (transfer), and delegated transfer via the approve-then-transferFrom pattern (approve, transferFrom, allowance). No other functions are required by the standard itself, though most deployments add optional metadata.
The six required functions break down as follows:
totalSupply() returns the total number of tokens in existence. Some contracts have a fixed supply (1 billion USDC at issuance); others mint and burn dynamically so totalSupply changes over time.
balanceOf(address account) returns the token balance held by a specific address. Wallets call this to display balances without knowing anything else about the contract.
transfer(address to, uint256 amount) moves tokens from the caller's account to the specified recipient. Emits a Transfer event. Returns a boolean indicating success. This is the primary path for direct peer-to-peer token transfers.
approve(address spender, uint256 amount) grants a third-party address (the spender) permission to move up to the specified amount from the caller's balance. This is the first half of the delegated-transfer pattern and is required before any DeFi protocol can pull tokens from your wallet.
transferFrom(address from, address to, uint256 amount) is called by the approved spender to execute the actual transfer. A Uniswap pool calls transferFrom when you swap; an Aave contract calls transferFrom when you deposit collateral.
allowance(address owner, address spender) returns the remaining approved amount that a spender can still pull from an owner. Protocols check this before attempting transferFrom to avoid reverts.
Beyond the six required functions, the standard also defines two required events: Transfer(address indexed from, address indexed to, uint256 value) and Approval(address indexed owner, address indexed spender, uint256 value). These events are emitted onchain so that indexers, wallets, and explorers can track token movements without reading full contract state on every block. The full function signatures and event definitions are in EIP-20.
The Three Optional Metadata Functions
ERC-20 defines three optional metadata functions that most deployed tokens include even though the standard doesn't require them. The name function returns a human-readable label ("USD Coin"), symbol returns the ticker ("USDC"), and decimals specifies the number of decimal places in the token's smallest unit. Most tokens use 18 decimals, mirroring Ethereum's ether precision, though USDC and USDT use 6.
The decimals function is particularly important in practice. ERC-20 token balances are stored as unsigned integers. The "6 USDC" you see in your wallet is stored as the integer 6,000,000 in the contract. Applications divide the integer balance by 10^decimals to display a human-readable figure. Misunderstanding this has caused serious integration bugs: a contract built assuming 18 decimals that receives a 6-decimal token like USDT can misquote prices by a factor of 10^12.
OpenZeppelin's ERC-20 implementation, the most widely used reference contract, sets decimals to 18 by default and allows subclasses to override it. The majority of high-value tokens inherit from OpenZeppelin's base or replicate its patterns.
How Does the ERC-20 Approval Model Work?
The ERC-20 approval model is a two-step pattern: a token holder calls approve to grant a contract permission to spend up to a set amount, then the contract calls transferFrom to pull tokens. This allows trustless DeFi protocols to move user funds without holding private keys. The allowance persists until revoked or consumed.
Here is the typical flow for a DeFi deposit. A user wants to supply 1,000 USDC to Aave. Before Aave can pull the tokens, the user calls USDC.approve(AavePoolAddress, 1000000000) (using 6-decimal units). This records an allowance in the USDC contract. The user then calls Aave's supply function. Aave's contract calls USDC.transferFrom(UserAddress, AavePool, 1000000000). The USDC contract checks the recorded allowance, confirms it's large enough, reduces it by the transferred amount, moves the tokens, and emits a Transfer event.
This two-step model has known limitations. The most significant is the approve front-running vulnerability: if a user reduces an existing allowance from 1,000 to 500, a watching spender can front-run the change by calling transferFrom for 1,000 before the approve executes, then calling transferFrom for 500 after. The EIP-20 specification acknowledges this in its security notes. The common mitigation is to first reduce the allowance to 0, confirm the transaction, then set the new value. An alternative is the EIP-2612 permit function (added to USDC v2.2 and DAI), which uses an off-chain signature instead of an onchain approve, eliminating the race condition entirely.
A second limitation is the lack of a receive hook. When a wallet sends ETH to a contract, that contract's receive() function fires. ERC-20's transfer() has no equivalent notification mechanism. The receiving contract has no way to know it received tokens unless it was explicitly called. This means tokens can be accidentally sent to contracts that have no logic to recover them, and building reactive on-receipt behavior requires workarounds. ERC-777 (a later standard) added receive hooks, but adoption remains limited due to reentrancy risks its hooks introduced.
Major ERC-20 Tokens and Their Scale
ERC-20 is the deployment format for the largest stablecoins by circulating supply, the most widely used DeFi governance tokens, and key oracle network tokens. The tokens listed below represent the categories most relevant to payments, DeFi, and enterprise use, not an exhaustive ranking by market cap.
The stablecoin segment is the highest-volume category of ERC-20 tokens. Per live data from DeFiLlama as of April 2026, USDT carries a $189.5B total circulating supply across all chains, with a significant portion deployed as ERC-20 on Ethereum. USDC has a $77.3B total supply. DAI, issued by MakerDAO's protocol, has a $4.6B supply. These three tokens alone process hundreds of billions of dollars in settlement volume monthly across Ethereum mainnet and L2s.
Beyond stablecoins, two governance tokens illustrate ERC-20's reach in DeFi infrastructure. LINK, Chainlink's oracle network token, is an ERC-20 used to pay node operators for delivering real-world data to smart contracts; its circulating supply mechanism and economic design are documented in Chainlink's whitepaper. UNI, Uniswap's governance token, is an ERC-20 used to vote on protocol upgrades; Uniswap has processed over $2T in cumulative volume (Uniswap Labs, 2025), with UNI serving as the governance layer over that liquidity.
The enterprise payments case for USD-backed stablecoins is closely tied to ERC-20: corporate treasury teams and payment providers building on Ethereum receive the ERC-20 interface as a default, which means any USDC or USDT integration works uniformly across the Ethereum ecosystem without per-token customization. For DAI specifically, the governance and risk mechanics behind MakerDAO's system are detailed in the MakerDAO and DAI deep-dive for treasury teams.
ERC-20 Limitations: Missing Return Values, Reentrancy, and Front-Running
ERC-20 has three documented limitations that every smart contract developer must account for: the missing return value bug found in some early deployments, the approve front-running vulnerability described above, and the absence of receive hooks. These aren't theoretical. Each has caused exploits, integration failures, or fund losses in production contracts.
The missing return value bug is specific to certain tokens, most notably the original USDT (Tether) contract. The ERC-20 specification says transfer() and transferFrom() must return a boolean. USDT's original Ethereum deployment omitted the return value from its transfer function, meaning a strict call expecting a bool return would revert. This non-compliance required a special handling pattern called SafeERC20, an OpenZeppelin utility wrapper that uses low-level calls to handle non-compliant tokens gracefully. Any protocol that interacts with arbitrary ERC-20 tokens should use SafeERC20 rather than calling transfer() directly.
The approve front-running risk was described in the approval model section. The practical mitigation used in production is the permit pattern (EIP-2612) for tokens that support it, or approve-to-zero-then-approve for tokens that don't. Neither workaround is required by the base standard, which is why contracts need to enforce the pattern themselves.
The no receive hook limitation means that ERC-20 tokens sent to a contract address that doesn't explicitly handle them can be permanently locked. Unlike Ether (which has a fallback function), ERC-20 tokens transferred via transfer() do not trigger any code in the recipient contract. Protocols that need to act on incoming tokens must build the token receipt into their own entry-point functions, which means accidental direct transfers to DeFi contract addresses outside the intended flow are typically unrecoverable.
ERC-20 vs ERC-721 vs ERC-1155 vs ERC-777: Comparison
ERC-20 is one of four widely used Ethereum token standards. The table below summarizes the core differences across fungibility, batch support, approval model, and primary use case. Understanding this matrix helps developers select the right standard before deployment, and helps analysts interpret what a given token can and cannot do.
Standard | Fungibility | Batch Transfer Support | Approval Model | Primary Use Case |
ERC-20 | Fully fungible (each unit identical) | No (one transfer per tx) | approve + transferFrom; EIP-2612 permit as optional extension | Stablecoins, governance tokens, utility tokens, DeFi collateral |
ERC-721 | Non-fungible (each token unique by ID) | No (one token per transfer call) | approve (single token) or setApprovalForAll (operator for all tokens in contract) | NFTs, digital art, collectibles, onchain credentials |
ERC-1155 | Both fungible and non-fungible in a single contract | Yes; safeBatchTransferFrom sends multiple token IDs in one transaction | setApprovalForAll only (no per-token or per-amount approval) | Gaming items, multi-asset contracts, NFT + fungible combinations |
ERC-777 | Fully fungible | No | Operators (a persistent spender role); backwards-compatible with ERC-20 allowances | Token receive hooks, richer DeFi integrations. Largely superseded due to reentrancy risks. |
The comparison above maps to several practical choice points. If every unit of the asset is interchangeable and the application is payments or DeFi, ERC-20 is the default. If each token needs a unique identity (a real estate title, a membership credential, a digital artwork), ERC-721 is the correct choice. If a single contract needs to issue both fungible currencies and unique items (as a blockchain game might), ERC-1155 is purpose-built for that, with the gas efficiency of batch transfers as a bonus. The full ERC-1155 specification and its batch mechanics are covered in the ERC-1155 explainer.
ERC-777 was designed to fix ERC-20's hook problem by adding tokensReceived callbacks for receiving contracts. In practice, those hooks created reentrancy attack surfaces: the Uniswap v1 reentrancy issue involving ERC-777 tokens is a documented example. As a result, major DeFi protocols either exclude ERC-777 tokens from whitelists or apply additional reentrancy guards, which limits its adoption relative to ERC-20 and ERC-1155.
ERC-20 Tokens in Cross-Chain Stablecoin Transfers
ERC-20 tokens originated on Ethereum mainnet, but cross-chain bridges and canonical programs have spread them across dozens of chains. USDC exists under two distinct models: native USDC, issued directly by Circle on each chain, and bridged USDC.e, a wrapped derivative. Only native USDC is redeemable directly by Circle; bridged versions depend on the bridge's liquidity and security model.
Circle's Cross-Chain Transfer Protocol (CCTP) is the canonical mechanism for moving native USDC between chains without bridges. CCTP burns native USDC on the source chain and mints an equal amount on the destination chain, with Circle's attestation service providing the mint authorization. This preserves the ERC-20 interface on both ends: the token on the destination chain is a first-class native USDC contract, not a wrapped derivative. Eco's stablecoin execution network uses CCTP as an internal transport mechanism for USDC transfers between supported chains, enabling atomic cross-chain settlement that clears through the same canonical token contract on each side.
For teams building cross-chain stablecoin automation (including treasury sweeps, payroll distributions, and protocol fee collection across L2s), understanding whether a given USDC deployment is native or bridged is a prerequisite to safe operations. The stablecoin automation platforms comparison covers which platforms handle native vs bridged token flows, and the cross-chain intent protocols overview explains how intent-based systems route around bridge fragmentation. For a broader view of how ERC-7715 permissions interact with token approvals in agentic payment flows, see the ERC-7715 explainer.
FAQ
What is the difference between ERC-20 and ERC-721?
ERC-20 tokens are fungible: every unit is identical and interchangeable, like stablecoin dollars. ERC-721 tokens are non-fungible: each token has a unique ID and represents a distinct asset, like an NFT artwork or a digital deed. A single ERC-20 contract issues identical units; a single ERC-721 contract issues uniquely identified items.
Why do so many DeFi protocols require token approval before deposits?
ERC-20's security model does not allow contracts to pull tokens from a wallet without prior authorization. The approve function records an allowance in the token contract, granting the protocol permission to call transferFrom up to the approved amount. This approval step is a one-time setup per token-protocol pair; without it, the deposit call would revert.
What does the decimals function in an ERC-20 token do?
The decimals function tells applications how to display the token's balance. ERC-20 balances are stored as integers; decimals specifies the number of places to shift the decimal point. USDC uses 6 decimals, so a balance of 1,000,000 displays as 1.00 USDC. Mismatched decimals assumptions are a common source of integration bugs in DeFi contracts.
Is USDC on Base the same as USDC on Ethereum?
Native USDC on Base is issued directly by Circle and is redeemable 1:1 via CCTP, the same as Ethereum-native USDC. Bridged USDC.e is a wrapped version created by locking Ethereum USDC in a bridge. They share the same ERC-20 interface but differ in redemption mechanics: native USDC goes through Circle; bridged USDC.e depends on the bridge's liquidity and security model.
Can ERC-20 tokens be sent to any Ethereum address?
Yes, the transfer function accepts any valid Ethereum address, including contract addresses that have no logic to handle incoming tokens. Tokens sent directly to contracts that don't implement a recovery path are typically locked permanently. Best practice is to send only to externally owned accounts or contracts explicitly designed to receive the specific token.
Related reading
Sources and methodology. Stablecoin circulating supplies from DeFiLlama stablecoins dashboard, April 29, 2026. Ethereum contract counts from Etherscan, April 2026. Token prices and market caps from CoinGecko, April 2026. ERC-20 function definitions from EIP-20 (Ethereum Foundation). Figures refresh quarterly.
