100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

ERC-20 Token Standard

The interface and mechanics behind fungible tokens on Ethereum, covering core functions, the approve/allowance pattern, events, and safe implementation.

Security & StandardsBeginner10 min readJul 10, 2026
Analogies

What ERC-20 Defines

ERC-20 is the Ethereum standard for fungible tokens, meaning every unit is identical and interchangeable, like currency. It specifies a common interface, a set of function signatures and events, that any compliant token contract must implement so that wallets, exchanges, and other contracts can interact with it uniformly. Because the interface is standardized, a single wallet can hold thousands of different ERC-20 tokens without custom code for each. The standard governs how balances are tracked, how transfers occur, and how one account can delegate spending authority to another.

🏏

Cricket analogy: Every run scored is identical and interchangeable, a run is a run, just as every ERC-20 unit is fungible and worth the same as any other.

Core Functions and Events

The mandatory ERC-20 functions are totalSupply (the total number of tokens), balanceOf(account) (an account's balance), transfer(to, amount) (move your own tokens), approve(spender, amount) and allowance(owner, spender) (delegated spending), and transferFrom(from, to, amount) (a spender moving someone else's tokens). Two events are required: Transfer, emitted on every token movement including mint and burn, and Approval, emitted when an allowance is set. Wallets and block explorers rely on these events to display balances and histories, so emitting them correctly is part of compliance, not an optional extra.

🏏

Cricket analogy: The scoreboard tracks each batsman's runs like balanceOf, the team total like totalSupply, and every scored run moving the tally like a transfer.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    // decimals() defaults to 18; 1 token = 10**18 base units
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}

// The interface every ERC-20 must satisfy (abbreviated):
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

The Approve and Allowance Pattern

Contracts cannot pull tokens from your wallet without permission, so ERC-20 uses a two-step delegation: you call approve(spender, amount) to authorize a spender up to a cap, and the spender later calls transferFrom to draw against that allowance. This underpins decentralized exchanges and staking contracts. It carries a well-known hazard, the approve race condition: changing a non-zero allowance to another non-zero value can let a watchful spender spend both the old and new amounts. The recommended mitigations are to set the allowance to zero first, or to use increaseAllowance and decreaseAllowance which adjust the value atomically.

🏏

Cricket analogy: A captain pre-authorizes a runner to complete runs on a batsman's behalf up to a limit; approve sets an allowance the spender draws against via transferFrom.

ERC-20 amounts are integers scaled by decimals(), which conventionally returns 18. A balance of 1,500000000000000000 (1.5 * 10**18) represents 1.5 tokens. There is no fractional type in the EVM, so front-ends divide by 10**decimals to display human-readable values.

Do not assume every ERC-20 returns true on transfer or reverts on failure, some non-standard tokens (famously USDT) do not. Use OpenZeppelin's SafeERC20 wrapper (safeTransfer, safeTransferFrom, forceApprove) to handle these inconsistencies safely when integrating arbitrary tokens.

  • ERC-20 standardizes an interface for fungible, interchangeable tokens so tooling works across all of them.
  • Core functions: totalSupply, balanceOf, transfer, approve, allowance, and transferFrom.
  • The Transfer event fires on every movement (including mint/burn) and Approval fires when an allowance is set.
  • approve plus transferFrom enables delegated spending used by DEXes and staking contracts.
  • The approve race condition is mitigated by zeroing first or using increaseAllowance/decreaseAllowance.
  • Amounts are integers scaled by decimals() (usually 18); the EVM has no native fractions.
  • Use SafeERC20 to safely integrate non-standard tokens that misreport success.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#SolidityStudyNotes#ERC20TokenStandard#ERC#Token#Standard#Defines#StudyNotes#SkillVeris#ExamPrep