ERC-20 is the technical standard that governs the creation and interaction of fungible tokens on the Ethereum blockchain. It enables the easy development of tokens representing digital assets like cryptocurrencies, voting rights, and membership tokens.
This standard has played a crucial role in Ethereum's growth by promoting interoperability between different projects and services.
ERC-20, or “Ethereum Request for Comment 20”, is a technical standard used to define the rules and functionality of tokens on the Ethereum blockchain. It ensures that all ERC-20 tokens adhere to a consistent set of guidelines, allowing them to interact with wallets, decentralized exchanges (DEXs), and other decentralized applications (dApps) within the Ethereum ecosystem.
By standardizing token functionality, such as transferring tokens, checking balances, and managing approvals, ERC-20 simplifies token development and interaction between tokens and platforms.
ERC-20 addresses the fragmented, inconsistent, and unpredictable behavior of tokens across the Ethereum ecosystem.
Before the introduction of ERC-20, creating tokens on the Ethereum blockchain was inconsistent and fragmented. Developers faced challenges ensuring their tokens could interact reliably with wallets, exchanges, and other smart contracts.
Early token implementations lacked uniformity in essential functions like transferring tokens or checking balances, leading to compatibility issues across decentralized applications (dApps). This inconsistency made it difficult to develop interoperable systems, as tokens often behaved unpredictably when integrated into different platforms.
Without a unified token standard, tokens could behave unpredictably, making it harder to support token transactions across different platforms.
Developers often had to write custom code, which led to higher risks of incompatibility and bugs.
ERC-20 introduced a universal set of rules for creating tokens on Ethereum, making it easier for developers to ensure their tokens could work seamlessly with wallets, exchanges, and other applications. This ensures that ERC-20 tokens operate consistently across different platforms by providing functions like transfer()
, balanceOf()
, and approve()
.
This standard helped prevent issues like compatibility problems and errors, allowing developers to focus on building new applications without needing to worry about token functionality.
The ERC-20 standard provides a unified set of functions and events that all Ethereum-based tokens must implement to ensure consistency.
transfer(address _to, uint256 _value)
Transfers _value
amount of tokens to address _to
and triggers the Transfer
event. If the sender’s balance is insufficient, the transaction is reverted.
The uint256
is an unsigned integer, meaning it only stores positive numbers and can hold values up to 2^256-1
.
Note: Transfers of zero value are considered valid and must trigger the Transfer
event.
function transfer(address _to, uint256 _value) public view returns (bool success)
approve(address _spender, uint256 _value)
This function authorizes _spender
to withdraw up to _value
tokens from your account.
If it's called again, it overwrites the current allowance.
Note: To prevent potential attack vectors, interfaces should first set the allowance to 0 before changing it to another value. The contract itself should not enforce this to maintain compatibility with older implementations.
function approve(address _spender, uint256 _value) public view returns (bool success)
allowance(address _owner, address _spender)
This function returns the number of tokens that a spender is still allowed to withdraw from the owner’s account.
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
transferFrom(address _from, address _to, uint256 _value)
This function allows a specified amount of tokens to be transferred from one address to another, as long as it has been approved. It must trigger the Transfer
event.
This method is often used in scenarios where a contract needs to withdraw tokens from a user’s account, such as paying for a service.
This function will revert if the transferFrom allowance is not properly set.
function transferFrom(address _from, address _to, uint256 _value) public view returns (bool success)
totalSupply()
Returns the total supply of tokens in circulation.
In the case of inflationary tokens, this value will increase as new tokens are minted through mechanisms such as staking rewards or governance decisions.
The contract dynamically updates the total supply to reflect these additions.
function totalSupply() public view returns (uint256)
balanceOf(address _owner)
This function returns the balance of a specified address (_owner
)
function balanceOf(address _owner) public view returns (uint256 balance)
name()
This function returns the name of the token, such as MyToken
.
Optional: Not mandatory but helps improve the usability of tokens by giving them a recognizable name.
function name() public view returns (string)
symbol()
This function returns the token’s symbol, like MYT
.
Optional: Similar to name()
function, it enhances the user experience but is not a requirement.
function symbol() public view returns (string)
decimals()
It defines the number of decimal places the token uses. For example, a value of 8
would mean that the smallest unit of the token is 0.00000001
. This means that token transfer amounts can be broken down to this level, allowing for fractional ownership and precise transactions.
Optional: Helps users by showing token amounts in an easier-to-read format.
function decimals() public view returns (uint8)
Transfer
This event is triggered whenever tokens are transferred, including zero-value transfers.
When minting (creating new tokens), the Transfer
event is triggered with the _from
address set to 0x0.
event Transfer(address indexed _from, address indexed _to, uint256 _value)
Approval
This event is triggered whenever a call to approve()
is successful, signaling that a spender has been approved to withdraw tokens from an owner’s account.
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
The introduction of the ERC-20 standard has significantly influenced the Ethereum ecosystem. It simplified the process of creating and issuing digital assets, leading to a surge in interest in Initial Coin Offerings (ICOs) and the overall growth of blockchain technology.
Since its adoption, over 350,000 ERC-20 tokens have been deployed on Ethereum, including well-known assets like USDC, Polygon (MATIC), and Shiba Inu Coin (SHIB).
ERC-20 tokens have diverse applications, representing fungible assets such as governance tokens, stablecoins, and rewards tokens. These tokens are stored in Ethereum-compatible wallets and can be seamlessly transferred to any Ethereum address.
Tokens powered by ERC-20 have driven liquidity, innovation, and mass participation in decentralized finance (DeFi) and broader applications across various industries.
These are libraries that provide developers with well-audited, reusable implementations of the ERC-20 standard:
These tokens have been successfully deployed using the ERC-20 standard and are widely used across the Ethereum network:
The ERC-20 standard can be implemented using a Solidity contract that defines a set of key functions and events.
Here’s a basic implementation of the ERC-20 standard:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
// ERC-20 Interface
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}
// ERC-20 Contract Implementation
contract ERC20 is IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
string public name;
string public symbol;
uint8 public decimals;
constructor(string memory _name, string memory _symbol, uint8 _decimals) {
name = _name;
symbol = _symbol;
decimals = _decimals;
}
function transfer(address recipient, uint256 amount) external returns (bool) {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) external returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) {
allowance[sender][msg.sender] -= amount;
balanceOf[sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
function _mint(address to, uint256 amount) internal {
balanceOf[to] += amount;
totalSupply += amount;
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal {
balanceOf[from] -= amount;
totalSupply -= amount;
emit Transfer(from, address(0), amount);
}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
function burn(address from, uint256 amount) external {
_burn(from, amount);
}
}
For detailed guidance on compiling, deploying, and interacting with the ERC-20 contract, check out Cyfrin Updraft, which provides an in-depth tutorial and additional resources for ERC-20 implementation.
The ERC-20 standard is expected to remain a driving force behind the continued growth of the Ethereum ecosystem. By providing developers with a standardized framework for creating and managing tokens, ERC-20 has facilitated the creation of a vast network of assets, contributing to Ethereum’s widespread adoption.
As the Ethereum ecosystem evolves and expands, the ERC-20 standard will likely continue to play a vital role in shaping its future, supporting the development of decentralized applications, governance tokens, and other tokenized assets.