ERC-20 Token Template

A template for creating compliant ERC-20 tokens on AERE Network with additional features. This template provides a secure foundation for creating your own token with best practices implemented.

Download Template

Features

Note: This template uses OpenZeppelin contracts which have been thoroughly audited and follow security best practices.

Getting Started

Prerequisites

Make sure you have the following installed:

Installation


# Clone the repository
git clone https://github.com/aere-network/erc20-template.git my-token

# Navigate to the project directory
cd my-token

# Install dependencies
npm install
# or
yarn install
    

Configuration

Create a .env file in the root directory with the following variables:


PRIVATE_KEY=your_wallet_private_key
AERE_RPC_URL=https://api.aere.network/rpc
ETHERSCAN_API_KEY=your_etherscan_api_key
    
Warning: Never commit your .env file or expose your private key. Make sure to add .env to your .gitignore file.

Token Customization

Modify the MyToken.sol contract in the contracts/ directory to customize your token:


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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

contract MyToken is ERC20, ERC20Burnable, ERC20Pausable, AccessControl {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    
    uint256 public immutable maxSupply;
    
    constructor(
        string memory name,
        string memory symbol,
        uint256 initialSupply,
        uint256 _maxSupply
    ) ERC20(name, symbol) {
        require(_maxSupply >= initialSupply, "Max supply must be >= initial supply");
        
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);
        
        maxSupply = _maxSupply;
        _mint(msg.sender, initialSupply);
    }
    
    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        require(totalSupply() + amount <= maxSupply, "Exceeds maximum supply");
        _mint(to, amount);
    }
    
    function pause() public onlyRole(PAUSER_ROLE) {
        _pause();
    }
    
    function unpause() public onlyRole(PAUSER_ROLE) {
        _unpause();
    }
    
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal override(ERC20, ERC20Pausable) {
        super._beforeTokenTransfer(from, to, amount);
    }
}
    

Configuration Parameters

Update the deployment script scripts/deploy.js with your token parameters:


// scripts/deploy.js
async function main() {
  const [deployer] = await ethers.getSigners();
  console.log("Deploying contracts with the account:", deployer.address);
  
  const MyToken = await ethers.getContractFactory("MyToken");
  
  // Configure your token here
  const name = "My Token";
  const symbol = "MTK";
  const initialSupply = ethers.utils.parseEther("1000000"); // 1 million tokens
  const maxSupply = ethers.utils.parseEther("10000000"); // 10 million tokens
  
  const token = await MyToken.deploy(name, symbol, initialSupply, maxSupply);
  await token.deployed();
  
  console.log("Token deployed to:", token.address);
}
    

Deployment

Deploying to AERE Network


npx hardhat run scripts/deploy.js --network aere
    

Verifying the Contract


npx hardhat verify --network aere DEPLOYED_CONTRACT_ADDRESS "My Token" "MTK" "1000000000000000000000000" "10000000000000000000000000"
    

Token Standards Compliance

The template ensures compliance with the ERC-20 standard, which defines the following methods:

Function Description
totalSupply() Returns the amount of tokens in existence.
balanceOf(address) Returns the amount of tokens owned by a specific address.
transfer(address, uint256) Transfers a specified amount of tokens to the recipient address.
allowance(address, address) Returns the remaining number of tokens that a spender is allowed to spend on behalf of an owner.
approve(address, uint256) Sets the allowance of a spender over the caller's tokens.
transferFrom(address, address, uint256) Transfers tokens from one address to another, using the allowance mechanism.

Advanced Functionality

Role-Based Access Control

The template uses OpenZeppelin's AccessControl contract to manage permissions:

Adding Custom Functionality

You can extend the token contract with additional features:

Testing

Run the test suite to ensure your token works as expected:


npx hardhat test
    

Support and Resources

For additional help and resources: