How to Build an ERC-20 Token Using Solidity

·

Creating an ERC-20 token on the Ethereum blockchain is a foundational skill for developers entering the decentralized application space. This guide provides a clear, step-by-step approach to building your own token using Solidity.


Understanding the ERC-20 Token Standard

The ERC-20 standard is a technical specification used for creating fungible tokens on the Ethereum network. It defines a common set of rules that all Ethereum tokens must follow, ensuring compatibility across wallets, exchanges, and other smart contracts.

Key functions mandated by the standard include:

This standardization is what allows different tokens to be traded and interact with each other seamlessly within the Ethereum ecosystem.


Prerequisites for Token Development

Before writing any code, you need to set up your development environment. Here’s what you’ll need:


Writing Your ERC-20 Smart Contract

Instead of building every function from scratch, it's best practice to use established libraries like OpenZeppelin Contracts. These audited and community-reviewed contracts provide a secure and gas-efficient implementation of the ERC-20 standard.

Here’s a basic example of a token contract built using OpenZeppelin:

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

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

contract MyCustomToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("My Custom Token", "MCT") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}

This concise code does the following:

  1. Specifies the License and Compiler Version: The pragma directive tells the compiler which Solidity version to use.
  2. Imports the OpenZeppelin ERC-20 Implementation: This single import gives your contract all the standard functions and events.
  3. Defines the Constructor: The constructor function is executed once upon deployment. It:

    • Calls the ERC20 constructor to set the token's name and symbol.
    • Mints the initialSupply of tokens and sends them to the address that deployed the contract. The decimals() function (default 18) is used to handle the token's granularity.

👉 Explore advanced token deployment strategies


Compiling and Deploying Your Contract

With your contract written, the next steps are to compile it into bytecode and deploy it to the Ethereum network.

  1. Compilation: Use your development framework (e.g., Hardhat) to compile the Solidity code. This will check for errors and generate the necessary artifacts, including the Application Binary Interface (ABI), which is essential for interaction.
  2. Deployment: Write a simple deployment script. In Hardhat, it might look like this:

    const hre = require("hardhat");async function main() {
      const initialSupply = hre.ethers.parseEther("1000000"); // Mint 1 million tokens
      const MyToken = await hre.ethers.getContractFactory("MyCustomToken");
      const myToken = await MyToken.deploy(initialSupply);      await myToken.waitForDeployment();      console.log("Token deployed to:", await myToken.getAddress());
    }
    main().catch((error) => {
      console.error(error);
      process.exitCode = 1;
    });
  3. Execution: Run this script against a network configured in your hardhat.config.js file. For testing, you can deploy to a local Hardhat network or a public testnet.

Testing and Verification

Thorough testing is non-negotiable for smart contracts due to their immutable nature. Write comprehensive tests for all critical functions: transfers, approvals, and allowances.

Sample Test (using Hardhat and Waffle):

const { expect } = require("chai");describe("MyCustomToken", function () {
  it("Should deploy with the correct initial supply", async function () {
    const [owner] = await ethers.getSigners();
    const initialSupply = ethers.parseEther('1000000');    const MyToken = await ethers.getContractFactory("MyCustomToken");
    const myToken = await MyToken.deploy(initialSupply);    const ownerBalance = await myToken.balanceOf(owner.address);
    expect(await myToken.totalSupply()).to.equal(ownerBalance);
  });  it("Should transfer tokens between accounts", async function () {
    const [owner, addr1] = await ethers.getSigners();
    const initialSupply = ethers.parseEther('1000000');
    const transferAmount = ethers.parseEther('100');    const MyToken = await ethers.getContractFactory("MyCustomToken");
    const myToken = await MyToken.deploy(initialSupply);    await expect(() =>
      myToken.transfer(addr1.address, transferAmount)
    ).to.changeTokenBalances(myToken, [owner, addr1], [-transferAmount, transferAmount]);
  });
});

After deployment, it's highly recommended to verify your contract's source code on a block explorer like Etherscan. This provides transparency and allows users to trust your contract's code.


Frequently Asked Questions

What is the difference between ERC-20 and other token standards like ERC-721?
ERC-20 is a standard for fungible tokens, meaning each token is identical and interchangeable, like traditional currency. ERC-721 is a standard for non-fungible tokens (NFTs), where each token is unique and not interchangeable, representing ownership of a unique asset.

How much does it cost to create an ERC-20 token?
The cost is primarily the gas fee required to deploy the smart contract to the Ethereum mainnet. This fee fluctuates based on network congestion and the complexity of your contract. Deploying a simple token can cost anywhere from $50 to $500 worth of ETH, depending on conditions. Testing on testnets is free.

Can I change the total supply of my token after it's deployed?
This depends on how you write your contract. A basic token with a fixed supply, like the example above, cannot mint new tokens after deployment. However, you can write a contract with a mint function (often restricted to the owner) to increase the supply. This adds significant economic and security considerations.

Is OpenZeppelin safe to use for my project?
Yes, OpenZeppelin Contracts are considered the gold standard in the industry. They are extensively audited, battle-tested by countless projects, and follow best practices for security and efficiency. Using them is much safer than writing a token contract from scratch.

What are the most common security pitfalls when creating a token?
Common issues include:

Where can I learn more about adding advanced features to my token?
You can extend your basic token with features like minting, burning, governance, or staking rewards. 👉 Discover comprehensive developer resources for tutorials and documentation on implementing these advanced functionalities. The OpenZeppelin documentation is an excellent starting point for understanding extensible contracts.