Cube

What Is ERC-20? The Fungible Token Standard Explained

Learn what ERC-20 is, how the Ethereum fungible token standard works, why approvals exist, and where ERC-20’s design tradeoffs matter.

What Is ERC-20? The Fungible Token Standard Explained hero image

Introduction

ERC-20 is the standard interface for fungible tokens on Ethereum and Ethereum-compatible chains. Its importance is easy to underestimate because the standard itself is small: just a handful of functions and events. But that small interface solved a large coordination problem. Before a standard, every token contract could expose its own custom API, which meant every wallet, exchange, and application had to integrate each token separately. ERC-20 made tokens legible to the rest of the ecosystem.

That is the central idea to keep in mind: **ERC-20 does not define what a token “means.” It defines how software can talk to a token contract in a predictable way. ** A token may represent a stablecoin, governance weight, exchange credit, a wrapped asset, or something purely internal to an application. ERC-20 does not care. What it cares about is that balances can be queried, transfers can be requested, and delegated spending can be expressed through a common interface.

This is why ERC-20 became foundational. If a wallet knows how to call balanceOf, transfer, and the other standard methods, it can support many tokens without bespoke code for each one. If an exchange knows the same interface, it can list new tokens much faster. The standard is less about inventing fungible tokens than about creating interoperability.

Why ERC-20 was needed: how it made tokens interoperable

A fungible token is a token where each unit is interchangeable with every other unit of the same token. One USDC is meant to be the same as any other USDC. That sounds simple, but on a smart-contract platform, someone still has to decide how balances are stored, how transfers update those balances, how supply is tracked, and how outside programs inspect the state.

Without a common standard, each token contract could choose different function names, different argument orders, different failure behavior, and different bookkeeping conventions. A wallet might know how to display one token but not another. A decentralized exchange might know how to move one token but not a competing token. The network would have tokens, but not really a token ecosystem.

ERC-20 solves this by standardizing the minimum common surface. It says, in effect: if your contract implements these functions and emits these events with these meanings, other software can treat your contract as a fungible token. That is enough to unlock a large amount of composability. A lending protocol can hold ERC-20 collateral. An automated market maker can swap ERC-20 assets. A wallet can display balances for many ERC-20s. None of them need to know the token’s deeper business logic as long as the interface behaves as expected.

The standard therefore creates an invariant at the ecosystem level: **different tokens can be different in purpose, issuance, or governance, but they become interoperable at the interface layer. ** That is the real achievement.

Is ERC-20 a token or just a contract interface?

A common misunderstanding is to think ERC-20 is itself a token or a blockchain asset. It is neither. It is a specification for smart contracts. The contract keeps track of balances and permissions, and other contracts or user wallets interact with it through the standard methods.

This distinction matters because the token does not live as a native object in Ethereum’s base ledger in the way ETH does. ETH is understood directly by the protocol. ERC-20 balances are contract state. Sending ETH uses protocol rules. Sending an ERC-20 token means calling token contract code that updates an internal balance mapping.

That difference has consequences. It is why ERC-20 tokens can implement custom issuance rules, blacklists, fees, rebasing behavior, or pause mechanisms. It is also why bugs or quirks in token contracts matter: the safety of an ERC-20 depends not only on Ethereum, but also on the specific token implementation.

You can see the contrast more clearly by looking beyond Ethereum. On Cardano, native tokens are tracked directly by the ledger rather than by a separate token contract for each asset. On CosmWasm-based chains, the CW20 standard plays a role similar to ERC-20 but changes the interaction model in important ways, including safer contract-oriented send flows. On Solana, fungible tokens live under a token program and token-account model rather than each token being its own standalone contract. ERC-20’s shape is therefore not the only possible way to standardize tokens; it is the Ethereum account-model answer to the problem.

How ERC-20 tracks totalSupply, balances, and allowances

At the heart of a typical ERC-20 implementation are three pieces of state.

The first is total supply, exposed through totalSupply(). This is the number of token units currently in existence according to the contract.

The second is the balance mapping, queried through balanceOf(owner). This tells you how many units a given address controls.

The third is the allowance mapping, queried through allowance(owner, spender). This is where ERC-20 becomes more than a basic balance table. It lets one address authorize another address to spend up to some amount on its behalf.

If you stripped away the syntax, the model is straightforward. The contract maintains a ledger of who owns how many units. Transfers subtract from one balance and add to another. Minting increases supply and credits a balance. Burning decreases supply and debits a balance. Allowances add a second layer of permissions so that a third party (often another contract) can move tokens for you within a preset limit.

That delegated-spending feature is the part that made ERC-20 deeply useful for decentralized applications. A DEX cannot ask your wallet to sign each internal movement in the middle of a trade path. A lending protocol cannot work if it has no standard way to pull tokens that you have agreed to deposit. The allowance mechanism is the bridge between “I own tokens” and “an application can use them under rules I set.”

What are the six ERC-20 methods and what do they do?

FunctionPurposeCallerEffectTypical use
totalSupply()Total token unitsanyone (view)reads aggregate supplyexplorers and analytics
balanceOf(owner)Account balanceanyone (view)reads owner balancewallet display
transfer(to,value)Direct transfertoken holderdebits sender, credits recipientuser-to-user send
approve(spender,value)Set allowancetoken holderoverwrites spender allowanceauthorize contracts
allowance(owner,spender)Read allowanceanyone (view)shows remaining approvalDEX/pre-checks
transferFrom(from,to,value)Delegated transferapproved spendermoves tokens using allowancecontracts pulling tokens
Figure 108.1: ERC-20 core methods at a glance

The ERC-20 specification defines a small required interface. The exact function signatures matter for compatibility, but the important part is what each function does mechanically.

totalSupply() returns the total number of token units tracked by the contract. Wallets, explorers, and applications use it to understand the token’s aggregate quantity, though by itself it says nothing about distribution or economics.

balanceOf(owner) returns the token balance for a given address. This is how wallets show holdings and how other contracts verify whether an account has enough tokens for a proposed action.

transfer(to, value) moves value tokens from the caller’s account to to. In the ordinary user-to-user case, this is the direct way to send tokens.

approve(spender, value) sets the caller’s allowance for spender to value. The key word is sets. It does not add to the existing allowance; calling it again overwrites the current amount.

allowance(owner, spender) reports how much spender is still permitted to withdraw from owner.

transferFrom(from, to, value) moves value tokens from from to to, using the caller’s allowance granted by from. This is how a contract spends tokens on a user’s behalf after being approved.

The structure here is elegant. There is one path for direct ownership transfer, transfer, and one path for delegated transfer, approve plus transferFrom. That separation is what made ERC-20 simple enough to standardize and flexible enough for applications.

Why ERC-20 uses approve + transferFrom (worked example)

Imagine Alice wants to deposit 100 tokens into a decentralized exchange contract so it can trade for her. If ERC-20 only had transfer, there would be a problem. Alice could send tokens to the contract address, but the exchange would have no standard, trusted way to distinguish an intentional deposit from an accidental transfer, nor any standard way to link that transfer to a particular trading action.

The allowance workflow solves this by making the contract pull tokens rather than having the user push them blindly. Alice first calls approve(exchange, 100). This records in the token contract that the exchange is allowed to spend up to 100 of Alice’s tokens. Nothing has moved yet; only permission has changed.

Then Alice calls the exchange contract’s deposit or trade function. Inside that function, the exchange calls transferFrom(Alice, exchange, 100) on the token contract. The token contract checks two things: that Alice’s balance is large enough and that the exchange’s allowance is at least 100. If both conditions hold, the token contract debits Alice, credits the exchange, and reduces the remaining allowance accordingly.

This pull-based design is why approvals are so common in DeFi. It gives the application a standard way to take tokens exactly when its own internal logic is ready. It also avoids the ambiguity of users simply transferring tokens to contracts that may not know what to do with them.

The analogy is a limited-use payment authorization. You do not hand over the cash immediately; you give a merchant permission to charge up to a ceiling. What the analogy explains is the separation between ownership and delegated spending. Where it fails is that ERC-20 approvals are on-chain state with transaction-ordering quirks, not a bank’s tightly controlled payment rail.

How Transfer and Approval events let wallets and indexers track ERC-20 activity

ERC-20 also standardizes two events: Transfer and Approval. These are not just conveniences. They are how wallets, block explorers, analytics systems, and indexers learn that token state has changed without re-executing every possible contract path by hand.

When tokens move, the contract must emit Transfer(from, to, value), including zero-value transfers. The specification also says token creation should emit a Transfer event with from set to the zero address 0x0. That convention lets off-chain software recognize minting as a special case of value entering circulation.

When an allowance is set, the contract emits Approval(owner, spender, value). This helps external systems track delegated spending permissions. Some widely used implementations also emit Approval during transferFrom allowance consumption so applications can reconstruct allowance changes from events more easily, but that is an implementation choice rather than the bare minimum defined by the standard.

This event layer is easy to overlook because it does not change balances by itself. But in practice it is a large part of ERC-20’s success. A standard without standard observability would be much less useful.

Are name, symbol, and decimals guaranteed for ERC-20 tokens?

Many users think every ERC-20 token naturally has a name, symbol, and decimal precision. In practice, these are common but not guaranteed. The specification treats metadata methods like name, symbol, and decimals as optional, and other interfaces must not assume they exist.

That matters because applications often behave as if metadata were part of the core guarantee. Most modern tokens do expose it, and many libraries build around that expectation. But at the standard level, ERC-20’s core promise is about balance and transfer behavior, not presentation.

decimals is especially easy to misunderstand. It does not create fractional tokens in the mathematical sense. The contract still tracks integers. decimals only tells interfaces how to display those integer units to humans. If a token uses 18 decimals, a wallet may display 1.5 tokens for an underlying integer amount of 1500000000000000000. The accounting remains integer-based.

What is the ERC-20 approval race condition and how do you mitigate it?

MitigationLocationBenefitTrade-offWhen to use
UI zero-then-setClient / walletblocks N+M raceextra txs and gaslegacy tokens
increase/decreaseAllowanceToken libraryatomic relative updatesnot in original specmodern implementations
require-zero-or-newToken contractprevents race on-chainbreaks backward compatibilitynew token deployments
approve with expected valueToken contractreverts on mismatchnon‑standard ERC-20high-security cases
Figure 108.2: Fixes for the ERC-20 approval race

ERC-20’s allowance mechanism is useful, but it has a well-known weakness. The problem appears when an owner changes an existing nonzero allowance to a different nonzero allowance using approve.

Suppose Alice has already approved Bob to spend N tokens. She now wants Bob’s new limit to be M. Because approve overwrites the old value, Alice might submit a transaction setting Bob’s allowance from N to M. But Bob can see pending transactions and, if he is malicious or simply automated, he may race to spend the old allowance before Alice’s update is mined. If Bob’s transferFrom uses up N first and Alice’s update to M lands afterward, Bob may effectively gain access to N + M over the two transactions.

This is not a bug in one token contract; it is a consequence of the standard overwrite pattern combined with transaction ordering. The ERC-20 specification itself warns about this and recommends a client-side mitigation: when changing an allowance, interfaces should first set it to 0 and only then set the new value. Importantly, the spec also says contracts should not enforce that reset requirement, largely for backward compatibility.

That last detail reveals the tradeoff. A safer contract-side rule could reduce the race, but stricter semantics might break existing integrations that expect ordinary approve behavior. So the standard left the burden mostly on wallets, UIs, and integrators.

OpenZeppelin and other libraries later added increaseAllowance and decreaseAllowance helper patterns in implementations to update allowances relative to the current value, which reduces the overwrite problem. But those functions are not part of the original ERC-20 core interface. This is one reason token approvals remain a separate topic of practical security, not just a footnote in the standard.

Why ERC-20 calls sometimes revert or return false; integration pitfalls

BehaviorCall returnsIntegrator actionTooling
Revert on failurerevert / exceptioncatch or let revert bubbleSafeERC20 wrappers
Return falseboolean false valuecheck return explicitlySafeERC20 helpers
No return valueno data returnedassume success if no revertlow-level wrappers
Unexpected ABIwrong/extra typesuse adapter or compatibility layercustom adapters
Figure 108.3: ERC-20 failure modes and integration guidance

On paper, ERC-20 methods like transfer, transferFrom, and approve return a boolean success value. The specification explicitly says callers must handle false and must not assume failure never occurs.

In practice, implementation behavior has varied. Some tokens return false on failure. Many modern implementations revert instead. Some older or nonstandard tokens have omitted expected return values entirely. This means that writing software that interacts safely with many ERC-20 tokens is trickier than simply following the idealized interface.

That is why utility libraries such as OpenZeppelin’s SafeERC20 exist. They wrap token calls so contracts can handle several real-world behaviors more safely: tokens that revert, tokens that return false, and tokens that return no value but succeed if they do not revert. This is not a criticism of the standard so much as a reminder that a standard interface does not guarantee perfect standard behavior in the wild.

The same pattern shows up with approvals. Some tokens require the allowance to be set to zero before being changed to a new nonzero value. Others do not. Libraries now include helpers such as forceful zero-then-set approval flows to accommodate awkward but widely used tokens. The ecosystem has had to become robust not only to the spec, but also to the history of partial compliance.

Can ERC-20 tokens get stuck when sent to smart contracts, and how do protocols avoid that?

ERC-20 has no built-in way for a receiving contract to acknowledge that it knows how to handle incoming tokens. A plain transfer just updates balances in the token contract. If the recipient is a contract that does not expect those tokens and exposes no recovery path, the tokens can become stuck.

This is a consequence of ERC-20’s minimalism. The standard knows how to move balances, but it does not define a receiver hook. For ordinary wallet addresses this is fine. For contracts, it can be dangerous.

That is why many protocol deposits rely on the approve plus transferFrom pattern instead of asking users to send tokens directly. In that pattern, the receiving contract participates actively in the flow, which means it can update its own internal accounting when it pulls tokens in. Some developers also add safeguards, like rejecting transfers to the token contract itself or providing admin or user recovery mechanisms for accidentally sent tokens. But those are local design choices, not guarantees of ERC-20.

Other token standards were partly motivated by this gap. CW20, for example, separates simple transfers from contract-oriented Send behavior that explicitly invokes receiver logic. ERC-777 pursued richer hook-based semantics on Ethereum. Each design makes a different tradeoff between minimal compatibility and safer or more expressive contract interaction.

Why ERC-20 became common across EVM chains (and how other chains differ)

ERC-20 is Ethereum-specific in origin, but the idea travels well because many chains reuse the Ethereum Virtual Machine or closely mimic its programming model. On those chains, an ERC-20 token contract often works almost the same way as it does on Ethereum mainnet. That portability helped make ERC-20 not just a local convention but a broader standard for EVM ecosystems.

Still, the concept should not be confused with fungible tokens in general. Other ecosystems solved the same problem differently. Solana’s token model centers on a shared token program and per-holder token accounts. Cardano uses ledger-native multi-asset support. CosmWasm’s CW20 resembles ERC-20 in spirit but adapts the mechanics to a different contract environment and explicitly addresses some ERC-20 friction points. These comparisons matter because they show which parts of ERC-20 are fundamental and which are products of Ethereum’s architecture.

What is fundamental is the need for a shared interface so wallets, applications, and exchanges can interoperate. What is conventional is the exact shape of approve/transferFrom, the absence or presence of receiver hooks, and whether assets are contract-defined or ledger-native.

Which ERC-20 extensions improve UX and approvals (for example, ERC-2612 permit)?

Because ERC-20 is minimal, many later standards extend it rather than replacing it outright. A useful example is ERC-2612, which adds [permit](https://scribe-topic-id.invalid/foundations.cryptography.signatures.digital_signature). With permit, a token holder can approve an allowance using an off-chain signature instead of sending an on-chain approval transaction directly. That improves UX because the user does not need to hold ETH just to authorize spending, and a relayer or protocol can submit the signed approval on-chain.

Mechanically, permit does not remove the allowance model. It changes how the allowance is granted. Instead of approve(spender, value) being called by the owner account on-chain, the owner signs a structured message, and someone else submits it. The token contract verifies the signature, checks a nonce and deadline, updates the allowance, and emits Approval.

This is an important example of how ERC-20 evolved in practice. The base standard was small enough to get universal adoption. The ecosystem then layered improvements on top where the original design showed friction.

Conclusion

ERC-20 is best understood as a coordination tool. It gave Ethereum a common language for fungible token contracts: balances, transfers, delegated spending, and standard events. That common language is why wallets, exchanges, and DeFi protocols can support so many tokens without custom integration every time.

Its design is powerful because it is minimal, and imperfect for the same reason. The allowance pattern enabled rich applications but introduced race-condition risk. Simple transfers enabled broad compatibility but made contract reception unsafe in some cases. So the enduring lesson of ERC-20 is not that a small standard solves everything. It is that a small standard can solve the biggest interoperability problem first; and leave the ecosystem to build safer patterns around it afterward.

How do you evaluate a token before using or buying it?

Evaluate a token’s mechanics before you buy or approve it so you understand supply, permissioned behavior, and approval quirks. On Cube Exchange, review the token’s contract and on-chain metadata from the asset page, then complete trading or approval flows from your funded Cube account.

  1. Open the token’s asset page on Cube and follow the contract link to a block explorer (Etherscan or equivalent).
  2. On the explorer, check totalSupply, decimals, verified source code, and whether the contract exposes owner/admin, mint/burn, pause, or blacklist functions.
  3. Check transfer/approval behavior and observability: look for ERC-2612 permit support, Transfer/Approval event emissions, and any nonstandard return/revert patterns; also read audits and recent community reports.
  4. Choose an approval strategy: use permit if available; otherwise approve only the exact amount needed, or use a zero-then-set flow and small allowances to limit exposure.
  5. Fund your Cube account with the required network asset, open the token market, place a limit (price control) or market (immediate) order, and when prompted complete the on-chain approval from your wallet following the strategy above.

Frequently Asked Questions

What exactly does ERC-20 standardize — the token logic or just the interface?
+
ERC-20 standardizes a small, mandatory smart‑contract interface (six functions like totalSupply, balanceOf, transfer, approve, allowance, transferFrom) plus two events (Transfer and Approval) so wallets, exchanges, and contracts can interoperate without bespoke integrations.
Is ERC-20 a native coin on Ethereum like ETH or something different?
+
ERC-20 tokens are contract state, not protocol-native assets like ETH; that means each token contract controls issuance, fees, blacklists, or pauses and bugs in the contract can affect token safety independently of Ethereum itself.
What is the ERC-20 approval race condition and how can it be mitigated?
+
The approve/transferFrom race occurs when an owner overwrites a nonzero allowance and a spender races to spend the old allowance before the change is mined; the standard’s recommended mitigation is a client-side zero‑then‑set update and many libraries provide increase/decreaseAllowance helpers to reduce the risk, but no fully backward‑compatible fix was imposed by the spec.
Can ERC-20 tokens get permanently stuck when sent to a smart contract, and how do protocols avoid that?
+
A plain transfer to a contract that does not expect ERC-20 tokens can leave those tokens stuck because ERC-20 has no receiver hook; protocols avoid this by using approve + transferFrom (so the contract actively pulls funds) or by choosing standards that include receiver callbacks (e.g., CW20 or ERC‑777).
Do ERC-20 transfer and approve calls always behave the same way, and what should integrators do about differences?
+
Although the spec defines boolean returns for transfer/approve/transferFrom, real tokens vary: some return false on failure, many revert, and others omit returns entirely; tooling like OpenZeppelin’s SafeERC20 wraps these behaviors so callers can handle tokens that revert, return false, or return no value.
Are name, symbol, and decimals guaranteed for every ERC-20 token, and what does decimals actually do?
+
Metadata methods such as name, symbol, and decimals are optional in ERC-20; decimals does not create fractional math—it only signals how to display the integer token units to users.
What does ERC-2612 permit do, and are there security or censorship limitations I should know?
+
ERC-2612’s permit lets an owner grant an allowance via an off‑chain signature instead of an on‑chain approve, improving UX (no ETH needed to approve), but permits can be censored by relayers and implementations must handle DOMAIN_SEPARATOR choices carefully to avoid replay across chain forks.
Why did ERC-20 become dominant beyond Ethereum, and is it the only way to design fungible tokens?
+
ERC-20’s minimal design spread because many chains reuse the EVM, but other ecosystems take different approaches (Cardano tracks native tokens in the ledger; Solana uses a shared token program; CosmWasm’s CW20 adapts the model), so ERC-20 is one interoperable solution among several architecture-dependent models.
How do wallets and explorers learn about token transfers and minting for ERC-20 tokens?
+
Because off‑chain observers rely on events, ERC-20 specifies emitting Transfer and Approval; minting is conventionally signaled by a Transfer event with the from address set to the zero address so indexers can detect token creation without re-executing contracts.
If a token doesn’t fully follow the ERC-20 spec, can libraries make interactions safe?
+
Libraries like OpenZeppelin’s SafeERC20 assume non‑reverting, no‑return calls are successful and provide helpers (safeIncreaseAllowance, safeDecreaseAllowance, forceApprove), but they also warn about edge cases such as ERC‑7674 temporary allowances and tokens that require zero‑first semantics, so using these helpers reduces risk but does not eliminate interoperability pitfalls.

Your Trades, Your Crypto