Create ERC-20 Contract Using Foundry

·

Creating an ERC-20 token is a foundational skill for blockchain developers, especially in the rapidly evolving ecosystem of EVM-compatible chains like Berachain. With Foundry—a powerful, fast, and modern Ethereum development toolkit—you can write, test, and deploy smart contracts efficiently using Solidity. This guide walks you through every step of creating a fully functional ERC-20 token using Foundry, from project setup to deployment on Berachain.

Whether you're building a community token, launching a DeFi project, or experimenting with blockchain development, this tutorial provides a clear and practical path forward.


Setting Up Your Development Environment

Before diving into code, ensure your system has Foundry installed. Foundry simplifies smart contract development with built-in tools like forge (for compiling, testing, and deploying) and cast (for interacting with the blockchain).

👉 Get started with Foundry and streamline your smart contract workflow today.

To install Foundry, run:

curl -L https://foundry.paradigm.xyz | bash

Then launch the installer and follow the prompts. Once installed, verify it works by running:

foundry --version

Initializing the Project

Start by creating a dedicated directory for your ERC-20 project:

mkdir create-erc20-contract-using-foundry
cd create-erc20-contract-using-foundry

Now initialize a new Foundry project:

forge init

This command generates a standard project structure:

.
├── README.md
├── foundry.toml
├── lib
│   └── forge-std
├── script
│   └── Counter.s.sol
├── src
│   └── Counter.sol
└── test
    └── Counter.t.sol

You now have a working Solidity environment ready for customization.


Installing OpenZeppelin Contracts

ERC-20 tokens require standardized implementations for functions like transfer, approve, and balanceOf. Instead of writing these from scratch, use OpenZeppelin Contracts, a trusted library for secure smart contract development.

Install it via Foundry:

forge install OpenZeppelin/openzeppelin-contracts

This adds OpenZeppelin’s contracts to your lib/ directory, enabling you to import ERC20.sol directly in your code.


Writing the ERC-20 Token Contract

Rename the default Counter.sol to reflect your token:

mv src/Counter.sol src/BingBongToken.sol

Replace its content with the following Solidity code:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

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

contract BingBongToken is ERC20 {
    /**
     * @dev Initializes token with name, symbol, and initial supply
     */
    constructor(string memory name_, string memory symbol_, uint256 mintedTokens_) ERC20(name_, symbol_) {
        _mint(msg.sender, mintedTokens_);
    }
}

This contract inherits from OpenZeppelin’s ERC20, automatically implementing all standard methods. The _mint call in the constructor issues the initial supply to the deployer.


Updating Test Files

Since we renamed the source file, update the test file accordingly:

mv test/Counter.t.sol test/BingBongToken.t.sol

Replace its content with a comprehensive test suite:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console2, stdError} from "forge-std/Test.sol";
import {BingBongToken} from "../src/BingBongToken.sol";

contract BingBongTokenTest is Test {
    BingBongToken public token;
    address supplyOwnerAddress = makeAddr("BerachainWalletUser");
    address randomWalletAddress = makeAddr("GiveMeTokens");
    address anotherWalletAddress = makeAddr("AnotherAddress");

    function setUp() public {
        vm.prank(supplyOwnerAddress);
        token = new BingBongToken("BingBong Token", "BBT", 10000);
    }

    function test_name() public {
        assertEq(token.name(), "BingBong Token");
    }

    function test_symbol() public {
        assertEq(token.symbol(), "BBT");
    }

    function test_decimals() public {
        assertEq(token.decimals(), 18);
    }

    function test_totalSupply() public {
        assertEq(token.totalSupply(), 10000);
    }

    function test_balanceOfAddressSupplyOwner() public {
        assertEq(token.balanceOf(supplyOwnerAddress), 10000);
    }

    function test_transfer() public {
        vm.prank(supplyOwnerAddress);
        token.transfer(randomWalletAddress, 100);
        assertEq(token.balanceOf(randomWalletAddress), 100);
        assertEq(token.balanceOf(supplyOwnerAddress), 9900);
    }

    function test_transferRevertInvalidReceiver() public {
        vm.prank(supplyOwnerAddress);
        vm.expectRevert(abi.encodeWithSignature("ERC20InvalidReceiver(address)", address(0)));
        token.transfer(address(0), 100);
    }
}

Run the tests:

forge test -vvv

A successful output confirms all tests pass—your token behaves as expected.


Creating the Deployment Script

Navigate to the script/ folder and rename the default script:

mv script/Counter.s.sol script/BingBongToken.s.sol

Update it with the deployment logic:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script} from "forge-std/Script.sol";
import "../src/BingBongToken.sol";

contract BingBongTokenScript is Script {
    function run() public {
        uint256 deployerPrivateKey = vm.envUint("WALLET_PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        BingBongToken newToken = new BingBongToken("BingBongToken", "BBT", 5678);

        console2.log("Token deployed at:", address(newToken));
        console2.log("Total supply:", newToken.totalSupply());

        vm.stopBroadcast();
    }
}

This script reads your private key from an environment variable and deploys the contract.


Deploying to Berachain Testnet

Create a .env file to store your private key securely:

WALLET_PRIVATE_KEY=your_private_key_here

Ensure your wallet has BERA tokens for gas fees on Berachain Testnet.

Deploy using:

forge script script/BingBongToken.s.sol \
--rpc-url https://rpc.berachain.com/ \
--broadcast

Upon success, you’ll see the transaction hash and deployed contract address.

👉 Secure your deployment process with best practices and tools for managing keys and transactions.


Verifying the Contract (Coming Soon)

Currently, contract verification via forge verify-contract may face limitations on Berachain due to API compatibility. However, once supported, you can verify your contract using:

forge verify-contract <CONTRACT_ADDRESS> BingBongToken \
--verifier-url https://berascan.com/api \
--constructor-args $(cast abi-encode "constructor(string,string,uint256)" "BingBongToken" "BBT" 5678)

Verification enhances trust by making your source code publicly auditable.


Core Keywords

These terms naturally appear throughout this guide, supporting SEO while maintaining readability and relevance.


Frequently Asked Questions

Q: What is Foundry used for in blockchain development?
A: Foundry is a complete toolkit for Ethereum and EVM-compatible chains that enables developers to write, test, compile, and deploy smart contracts using Solidity—all from the command line.

Q: Why use OpenZeppelin for ERC-20 tokens?
A: OpenZeppelin provides secure, community-audited implementations of ERC standards. Using their contracts reduces bugs and vulnerabilities in custom token logic.

Q: Can I deploy to Berachain mainnet using this method?
A: Yes. Replace the RPC URL with Berachain’s mainnet endpoint and ensure your wallet holds enough BERA for gas fees.

Q: How do I handle private keys securely?
A: Never hardcode keys in source files. Use environment variables (like WALLET_PRIVATE_KEY) and consider hardware wallets or key management solutions for production use.

Q: What if my deployment fails?
A: Check that your RPC URL is correct, your wallet has sufficient funds, and your private key is properly formatted. Use anvil locally to simulate deployments first.

Q: Is Foundry better than Hardhat?
A: Foundry offers faster execution (written in Rust), no need for JavaScript/TypeScript, and native Solidity testing. It's ideal for developers who prefer minimal tooling overhead.


With this guide, you’ve learned how to build, test, and deploy an ERC-20 token on Berachain using Foundry—a modern, efficient approach to blockchain development. As ecosystems like Berachain grow, mastering these tools positions you at the forefront of Web3 innovation.

👉 Accelerate your blockchain journey with powerful tools and resources.