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
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 methodUsing 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.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
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
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.
create a file named ERC20.sol in the contracts folder
Writing the contract
we start stating the license and the solidity version we are using
// SPDX-License-Identifier: UNLISCENSED pragma solidity ^0.8.20;
Declare your contract and state variables and events
define the constructor to allow the person deploying the contract to set the initial supply for the token
this function gets the initial supply that has been set for the token
returns the total amount of tokens the owner is allowed to spend
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
Approves a spender to spend a specified number of tokens on behalf of the caller and sets the allowance of the spender
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); }
Transfers tokens from one address to another by calling the _transfer function
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
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
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
Subscribe to my newsletter
Read articles from Oluwabunmi Oseni directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
