Project Scenario
In this 2-part series, I’ll show you how I built my own ERC-20 token like ETH in this project. I share this because you may want to do the same and learn from my experience.
I use Solidity to write a smart contract for my ERC-20 token, and then the contract will be deployed on a test net, for starters.
The token balance will be displayed on the user interface along with the wallet address. The front end will be formed with React & Tailwind CSS.
In the next part of this series, I’ll show you how to transfer tokens with the help of the ether.js
library. You’ll be able to check the details regarding the transaction by using the transaction hash on the Etherscan website.
Create the Smart Contract
We will use the Openzeppelin framework to build our ERC-20 token.
👉 Recommended: How Does the ERC-20 Token Work?
OpenZeppelin is a secured open-source framework that is used to build, manage, and inspect all aspects of software development for decentralized applications. OpenZeppelin’s ERC-20 solidity file contains all the code to build the token.
Move to the Remix IDE and create a solidity file inside the contract folder. I am naming it as “SilverToken.sol
”. Declare the solidity version number in the first line.
So, import Openzeppelin’s ERC-20 Solidity file.
pragma solidity >= 0.5.0 < 0.9.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
If you want to learn more about the OpenZeppelin implementation, you can follow this link.
Now create the contract named SilverToken
. This token inherits the token structure from the ERC-20 implementation of Openzeppelin.
contract SilverToken is ERC20 { constructor (uint256 initialSupply) ERC20("silver", "SLV"){ _mint(msg.sender, initialSupply); } function decimals() public pure override returns (uint8) { return 2; } }
As our token is a child of the ERC-20 class, we can access the different methods of that class now. We are calling the constructor method first. This method asks for the initial supply amount to the contract.
We called the base contractor ERC-20 with name and symbol parameters. This will pass the name and symbol of our token to the parent constructor. Silver is the name of our token, and SLV is the symbol.
To create the initial supply, we started minting tokens. The initial supply of the token will be minted to the msg.sender
which is the address of the person who deploys the contract.
We usually can see the 18th decimal of precession for the ETH value. But here, for simplicity, we override that decimal function. We will get up to 2 decimal values.
Deploy the Smart Contract
Let’s compile the contract and move to the deployment section.
We will deploy this on the Goerli testnet. It would be best if you had the goerli test network added to your browser.
If you don’t have the goerli test network on your browser, then move to the “add network” option of the Metamask and add the goerli test net from the networks option.
The configuration for the goerli network is given below:
- Network name: Goerli test network
- New RPC URL: https://goerli.infura.io/v3/
- Chain ID: 5
- Currency symbol: GoerliETH
- Block explorer URL (Optional): https://goerli.etherscan.io
Goerli testnet must be added to your browser by this time.
You can create a new account by clicking the create account
option of Metamask.
We need some goerli Eth in your wallet for the deployment cost. You can quickly get some free goerli eth from goerliFaucet.com.
You may need to sign up in Alchemy to avail the opportunity. Just sign up on Alchemy and create an app. Move back to the goerli faucet and transfer some ETH to your wallet. It’s that simple.
Now get back to the Remix IDE. Choose the “Injected provider- Metamask” option from the environment dropdown menu. Make sure you are logged into the goerli testnet in Metamask.
You must see the goerli wallet address on the account section if you get connected to Remix IDE. Choose any account. You have to set an initial amount to supply at this address.
I am setting the initial supply amount as a million goerli ETH. Deploy the contract, and you will see all the functions and data types available under the menu.
If you want to check the balance, you can check it from the balanceOf
menu. Just enter the wallet address and press the menu. The current token balance will be displayed there.
If you don’t see the token balance in the Metamask, move to the assets option In the Metamask and click on the import tokens
option. Then paste the contract address from the Remix IDE, and the tokens will be automatically imported.
You will get the contract address from the deployed contracts section of the Remix IDE.
So, our simple, smart contract is ready. Now let’s build the front end to do transactions to other accounts.
Create a React App and Tailwind CSS
We will use React and Tailwind CSS to build our front end. So, create our react app first.
Open the command prompt from your directory. Then type
npx create-react-app silver_wallet
Now the react is installed. But before initializing react, move to the installed directory and install the tailwind CSS for react.
cd silver_wallet npm install -D tailwindcss npx tailwindcss init
Inside the tailwind.config.js
file, configure the template paths
content: [ "./src/**/*.{js,jsx,ts,tsx}", ],
And inside the index.css file, add the tailwind directives.
@tailwind base; @tailwind components; @tailwind utilities;
Tailwind is installed.
Now initiate the React App.
npm start
The React app should be running on the browser in the port 3000.
Now move to the app.js
file and clear it for writing the contracts.
Connect to Metamask
The first thing we need to do is to establish a connection with the Metamask wallet.
Create a button and a container to show the account address to which we would be connected. The wallet’s address will be shown in the UI when connected to the wallet.
Let’s apply some styles also at the same time when we proceed. Get a nice button from the Flowbite website. Flowbite is one of the open-source UI libraries that will help us to build a front-end design faster.
<div> <div className="text-center mt-10"> <button type="button" onClick={connectMetamask} className="text-white bg-gradient-to-r from-cyan-500 to-blue-500 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-cyan-300 dark:focus:ring-cyan-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2" > Connect to Metamask </button> {errorMessage} </div> <div className="items-center mt-5 py-3 px-4 text-sm font-medium text-center text-white bg-sky-500 rounded-lg hover:bg-sky-500 focus:ring-4 focus:outline-none focus:ring-blue-300 w-1/2 m-auto"> <h3>Wallet Address: {activeAccount} </h3> </div> </div> </div>
Our button is visible in the UI, and we need to add some functionalities to the connectMetamask event handler to make it work.
const connectMetamask = async () => { try { if (window.ethereum) { await window.ethereum .request({ method: "eth_requestAccounts" }) .then((result) => { setActiveAccount(result[0]); }); } else { console.log("Need to install Metamask"); } } catch (error) { console.log(error); } };
An “if-else” condition is introduced to confirm if the Metamask is injected into the browser.
Inside the if condition, the eth_requestAccounts
method of the Ethereum library is used to request the accounts of the Metamask. From the results, we choose the results[0]
, that is, the connected account of Metamask.
We need to declare a state variable outside the event handler to show our account address to the UI. A useState
hook of React would be helpful here. Import useState
from React.
import React, { useState } from "react";
Now create a state variable to store the value of the active account address.
const [activeAccount, setActiveAccount] = useState(null);
Now set the results[0]
as the active account.
If the event handler fails to connect to Metamask, It will throw an error message in the console.
Now if you run the code you must get the wallet address displayed on the User Interface.
At the same time, we need to show the token balance. Under the address section, we can create another <div>
container to show the balance of that wallet address. Let’s do this.
<div className="items-center mt-5 py-3 px-4 text-sm font-medium text-center text-white bg-sky-500 rounded-lg hover:bg-sky-500 focus:ring-4 focus:outline-none focus:ring-blue-300 w-1/2 m-auto"> <h3>Token Balance: {tokenBalance} </h3> </div>
Create another state variable outside the function to show balance in the UI.
const [tokenBalance, setTokenBalance] = useState(null);
Our balance
state variable is ready, but we need to connect with the contract to fetch the balance from the wallet.
We get connected with the smart contract and transfer some balance into a specific account in the next part: