Table of Contents

Introduction

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. 

  • Proposal Date: November 19, 2015
  • Release Date: Accepted as an Ethereum standard on November 19, 2015, the same day it was proposed.
  • Authors:

What is ERC-20?

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. 

What problem does ERC-20 solve?

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’s solution

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.

How does ERC-20 work?

The ERC-20 standard provides a unified set of functions and events that all Ethereum-based tokens must implement to ensure consistency. 

Core Functions

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)

Events

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) 

Impact of ERC-20

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.

Smart contract implementations

These are libraries that provide developers with well-audited, reusable implementations of the ERC-20 standard: 

  1. OpenZeppelin implementation
    • OpenZeppelin is a widely used library offering secure smart contract development tools. Their ERC-20 contract is community-reviewed and includes several features beyond the base ERC-20 standard. 
    • It provides additional functionality such as plausible tokens, minting, and burning capabilities, making it suitable for various advanced use cases. 
  2. ConsenSys implementation
    • ConsenSys offers a simple and reliable ERC-20 implementation, ideal for developers looking for an easy-to-understand contract template. This implementation is often used as an educational reference for learning and integrating the ERC-20 standard in real-world projects. 
  3. Solmate implementation
    • Solmate is a gas-optimized library designed for efficiency, reducing gas costs through low-level Solidity optimizations. 
    • This implementation is frequently used by developers looking to deploy tokens cost-effectively, particularly in high-frequency trading or gas-sensitive environments.

Real-world tokens

These tokens have been successfully deployed using the ERC-20 standard and are widely used across the Ethereum network:

  1. USD Coin (USDC)
    • USDC is a popular stablecoin pegged 1:1 to the US dollar. It is backed by a combination of dollars and other cash-equivalent reserves, ensuring its value remains stable.
    • Widely adopted in decentralized finance (DeFi), USDC is also a common choice for remittances due to its reliability and fiat backing.
  2. Uniswap (UNI)
    • UNI is the governance token for Uniswap, one of the largest decentralized exchanges (DEX) built on Ethereum. UNI holders participate in voting on protocol changes, enabling decentralized governance and community-driven decision-making in the Uniswap ecosystem. 
  3. Aave (AAVE)
    • AAVE is the governance token for the Aave protocol, a decentralized lending platform. Holders of AAVE tokens can participate in protocol governance and use the token as collateral when borrowing or lending on the platform. 
  4. Chainlink (LINK)
    • LINK is the native token of the Chainlink decentralized oracle network. LINK tokens are used to pay for data services within the Chainlink ecosystem and to incentivize accurate data delivery by node operators. 
  5. Arbitrum (ARB)
    • ARB is the governance token of the Arbitrum network, a Layer 2 scaling solution for Ethereum. ARB holders can vote on proposals that influence the direction of the Arbitrum ecosystem, contributing to its decentralized governance structure.
  6. Optimism (OP)
    • OP is the governance token of the Optimism Layer 2 network. OP holders can vote on protocol upgrades and participate in decentralized decision-making processes, shaping the future of the Optimism ecosystem.

ERC-20 implementation

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.

Conclusion

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. 

Related Terms

No items found.