Understanding ERC20 ( Ethereum Request for Comments)

It’s 2025 and cryptocurrencies are creating a bigger buzz than ever! Since the launch of Bitcoin in 2009, and its massive boom in 2017, thousands of altcoins ( alternative coins that are not Bitcoin) and fungible ( something interchangeable and identical in value) tokens have emerged

Since the blockchain is a decentralized system that allows anyone to build and deploy applications. Ethereum introduced a standard to ensure all tokens followed a universal framework. This would allow tokens to be interchangeable, bug-free, and compatible across different platforms.

What exactly is ERC20?

ERC20 stands for Ethereum Request for Commenst and 20 is a unique identifier assigned to this token standard. This standard set by Ethereum allows users to easily create tokens that seamlessly integrate into dapps and can interact with other tokens.

ERC20s are built on Ethereum so they utilize Ethereum’s smart contract capabilities and infrastructure. All transactions are recorded on the blockchain and gas fees are paid in ETH ( Ethereum’s native currency). Before the advent of ERC20, token creators created tokens without guidelines, meaning that each of the tokens differed, they weren’t swappable and they had serious security risks. The main purpose of this standard was to battle these issues. The ERC20 standard makes tokens, swappable, fungible, allows for automatic transfer, secure and programmable.

Use cases of ERC20

ERC20 can be used across many facets of blockchain development for examples

ERC-20 tokens play a crucial role in various sectors of the blockchain ecosystem, including DeFi (Decentralized Finance), gaming, governance, and payments. These tokens provide the foundation for a wide range of applications and services, enabling several key functionalities:

  • Stablecoins: ERC-20 tokens like USDT (Tether) and USDC (USD Coin) facilitate smooth and efficient transactions by maintaining a stable value pegged to traditional currencies like the US dollar. This stability makes them ideal for everyday transactions and trading within the crypto space.

  • DeFi Lending & Borrowing: Platforms such as AAVE and Compound leverage ERC-20 tokens to offer decentralized lending and borrowing services. Users can lend their tokens to earn interest or borrow tokens by providing collateral, all without the need for traditional financial intermediaries.

  • Governance Voting: In decentralized autonomous organizations (DAOs), ERC-20 tokens like UNI (Uniswap) and MKR (Maker) are used to enable governance voting. Token holders can participate in decision-making processes, influencing the future direction and policies of the projects they are invested in.

  • In-game Rewards: Blockchain-based games, such as Axie Infinity, utilize ERC-20 tokens to reward players for their achievements and participation. These tokens can be traded or used within the game, creating a vibrant in-game economy that enhances the gaming experience.

Overall, ERC-20 tokens have become an integral part of the blockchain landscape, driving innovation and expanding the possibilities of decentralized applications.

What are these standards anyway?

A token that follows the ERC20 standard should have the following functions and events

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0; // Specifies the Solidity version to use

// Interface for the ERC20 token standard
interface IERC20 {
    // Events

    // Emitted when tokens are transferred from one account to another
    event Transfer(address indexed from, address indexed to, uint256 value);

    // Emitted when an account approves another to spend tokens on its behalf
    event Approval(address indexed owner, address indexed spender, uint256 value);

    // Functions

    // Returns the total supply of tokens in circulation
    function totalSupply() external view returns (uint256);

    // Returns the balance of a specific account
    function balanceOf(address account) external view returns (uint256);

    // Transfers a specific amount of tokens to another account
    function transfer(address to, uint256 amount) external returns (bool);

    // Returns the remaining number of tokens that a spender is allowed to spend on behalf of the owner
    function allowance(address owner, address spender) external view returns (uint256);

    // Allows an account (spender) to withdraw a certain amount of tokens from the caller's account
    function approve(address spender, uint256 amount) external returns (bool);

    // Transfers tokens from one account to another, using an allowance mechanism
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

How to create your own ERC20 token

there are different ways to create erc20 tokens

  1. Using a Token Factory:
    A token factory is a platform that simplifies the process of creating ERC-20 tokens. These platforms provide a user interface where you can input the necessary details for your token, such as its name, symbol, and total supply. The token factory then automatically generates the smart contract code and deploys it on the Ethereum blockchain. No coding knowledge is needed in this method

  2. Using OpenZeppelin's Library:
    OpenZeppelin offers a robust library of smart contract templates that are widely used in the Ethereum community. By utilizing OpenZeppelin's library, you can create an ERC-20 token by extending their pre-audited and secure smart contract code. This approach allows you to customize your token by adding specific features or functionalities while ensuring that your token adheres to industry standards. It is a great option for developers who want a balance between customization and security.

  3. Coding from Scratch:
    Creating an ERC-20 token from scratch involves writing the entire smart contract code yourself. This method provides the highest level of customization, allowing you to design your token with unique features and functionalities tailored to your specific needs. However, it also requires a deep understanding of Solidity, the programming language for Ethereum smart contracts, and a thorough knowledge of blockchain security best practices. This approach is best suited for experienced developers who want complete control over their token's design and functionality.

Creating an ERC20 from scratch

In this tutorial, I will be showing you how to create, and deploy your ERC20

Setting up the environment

  1. we will be using hardhat to compile and deploy our token. The first line initializes npm in our project and the second line installs hardhat

     npm init -y
     npm install --save-dev hardhat
    
  2. initialize hardhat by running the following.(I choose the typescript project.)

     npx hardhat init
    

    you should get a result like this. the sample project comes with the perfect folder structure equipped with all you need. Delete the lock.sol file in the contracts folder and lock.ts file in the test folder as it won’t be needed.

  3. create a file named ERC20.sol in the contracts folder

Writing the contract

  1. we start stating the license and the solidity version we are using

     // SPDX-License-Identifier: UNLISCENSED
     pragma solidity ^0.8.20;
    
  2. Declare your contract and state variables and events

  3. define the constructor to allow the person deploying the contract to set the initial supply for the token

  4. this function gets the initial supply that has been set for the token

  5. returns the total amount of tokens the owner is allowed to spend

  6. this enables the transfer of tokens on behalf of the sender’s address. it checks if the address that is calling this function i.e the msg.sender is allowed to send the amount taken by the contract and then uses the transfer function to send the amount to the recipient

  7. Approves a spender to spend a specified number of tokens on behalf of the caller and sets the allowance of the spender

  8. Transfer function that takes in the sender’s address and moves the amount from the sender to the recipient

      function _transfer(address sender, address recipient, uint256 amount) internal {
             require(sender != address(0), "ERC20: transfer from the zero address");
             require(recipient != address(0), "ERC20: transfer to the zero address");
             require(_balances[sender] >= amount, "ERC20: Not enough funds.");
    
             _balances[sender] -= amount;
             _balances[recipient] += amount;
    
             emit Transfer(sender, recipient, amount);
         }
    
  9. Transfers tokens from one address to another by calling the _transfer function

  10. Gets the balance of the owner

full code below

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

contract ERC20 {
    string public name = "MYERC20";
    string public symbol = "MC2";
    uint8 public immutable decimals= 18;
    uint256 private _totalSupply;
    uint256 public constant MAX_SUPPLY = 1000000 * 10**18;


    mapping(address => uint256) private _balances;
    mapping(address => mapping (address => uint256)) private _allowances;

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


    constructor(uint256 initialSupply) {
        _totalSupply = initialSupply;
        _balances[msg.sender] = initialSupply;

    }

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }


    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

        function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        require(_allowances[sender][msg.sender] >= amount, "ERC20: Allowance not high enough.");
        _allowances[sender][msg.sender] -= amount;
        _transfer(sender, recipient, amount);
        return true;
    }
    function approve(address spender, uint256 amount) public returns (bool) {
        require(spender != address(0), "ERC20: approve to the zero address");
        _allowances[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

        function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");
        require(_balances[sender] >= amount, "ERC20: Not enough funds.");

        _balances[sender] -= amount;
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

     function balanceOf(address tokenOwner) public view returns (uint256 balance) {
        return _balances[tokenOwner];
    }
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

}

following these guidelines will help you successfully create your own ERC20 token

Compiling and deploying your ERC20

Compiling: to compile your erc20 run the following code in your terminal

npx hardhat compile

you should get this

PS C:\Users\OSENI OLUWABUNMI\Desktop\smart\erc20> npx hardhat compile
Generating typings for: 1 artifacts in dir: typechain-types for target: ethers-v6
Successfully generated 6 typings!

you will find more details of this in your artifacts folder

Deploy

thereare two waysyou can deply on hardhat. either buy writing an ignition script or a deployment script. in this example i will be using the built in hardhat ignition. We can also deply on a local hardhat network or a live testnet environment. In this example we will be deploying on a local hardhat network

  1. create a deployment script: Navigate to the ignition folder, then to the modules sub folder, and create a new file ERC20.ts

     import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
    
     const ERC20Module = buildModule("ERC20Module", (m) => {
       const initialSupply = m.getParameter("initialSupply", 1000000n * 10n ** 18n); // 1 million tokens
    
       const erc20 = m.contract("ERC20", [initialSupply]);
    
       return { erc20 };
     });
    
     export default ERC20Module;
    

    this script just deploys the contract and takes in the custructor parameters to set the initial of the token then exports the build module

  2. Deployment: run the following codein your terminal to deploy

     npx hardhat ignition deploy ignition/modules/ERC2
    

    you should get an output like this

     PS C:\Users\OSENI OLUWABUNMI\Desktop\smart\erc20> npx hardhat ignition deploy ignition/modules/ERC2
    
     You are running Hardhat Ignition against an in-process instance of Hardhat Network.
     This will execute the deployment, but the results will be lost.
     You can use --network <network-name> to deploy to a different network.
    
     Hardhat Ignition 🚀
    
     Deploying [ ERC20Module ]
    
     Batch #1
       Executed ERC20Module#ERC20
    
     [ ERC20Module ] successfully deployed 🚀
    
     Deployed Addresses
    
     ERC20Module#ERC20 - 0x5FbDB2315678afecb367f032d93F642f64180aa3
    

if you check your ignition folder you hsould see a new folder called deployments. There you would find all the details about your deployed contracts