Cryptocurrencies have recently become popular, opening endless possibilities to companies, individuals, and DAOs. If you want to learn how to create and deploy an ERC20 Token In 20 minutes, that’s the right place to be.
In this tutorial, you’re going to understand how to create a cryptocurrency using Solidity and the ERC20 Token standard (Ethereum request of comment) maintained by OpenZeppelin.
We will first write the Smart Contract using REMIX IDE, an online IDE specifically made for Ethereum development with Solidity. We’ll then set up a local environment using Hardhat to deploy your own cryptocurrency on the Mumbai Polygon Testnet.
By the end of this tutorial you’ll learn:
Develop and deploy an Ethereum Smart Contracts using the IX IDE.
How to create and deploy an ERC20 Token with Solidity.
Setup a local Ethereum development environment using Hardhat.
Deploy a cryptocurrency on Polygon Mumbai.
Visualize your own cryptocurrency on MetaMask.
How to start your own cryptocurrency.
It is not assumed any previous Solidity knowledge, although is suggested to have some previous programming knowledge before starting this tutorial. If you don’t know where to start, I highly suggest you go and check the complete web3 roadmap (Updated this year).
That said, let’s dig straight into how to develop and deploy an ERC20 token.
How To Create an ERC20 Token: Set up The Environment With REMIX
We’ll learn how to create and deploy an ERC20 Token Smart Contract using REMIX, an easy-to-use, free, with a great Solidity compatible IntelliJ feature, and decent compile-time errors, IDE.
Navigate to remix.ethereum.org, open the contacts folder, and create a new file called “Token.sol”:
How to Create and Deploy an ERC20 Token
Whenever a new Solidity file is created, it’s mandatory to add the License-identifier and the pragma to specify the Solidity version the compiler should use to build our code. In the Token.sol file, write the following code:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
The “^” means the code is compatible with any version of the compiler from Solidity 0.8.0 to 0.8.9.
Now we need to import the ERC20 token contract from OpenZeppelin, but first, let me briefly go through what is an ERC20 Token, important to understand if you want to create your own cryptocurrency.
If you’re already familiar with this concept, feel free to skip to the next paragraph.
How to Create and Deploy an ERC20 Token: What is an ERC20?
According to the official OpenZeppelin documentation:
“An ERC20 token contract keeps track of fungible tokens: any token is exactly equal to any other token; no tokens have special rights or behavior associated with them. This makes ERC20 tokens useful for things like a medium of exchange currency, voting rights, staking, and more.”
Simply put ERC20 is nothing more than a class, with its methods and members, that runs the logic of what we commonly call cryptocurrencies, with a broader meaning though, as it also finds applications in other use cases.
OpenZeppelin on the other hand is considered the standard library maintaining ERC contracts classes.
How to Create and Deploy an ERC20 Token
Import the OpenZeppelin ERC20 contract in the Token.sol file:
Token.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
And initialize the Token, inheriting from the ERC20.sol contract:
Token.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract DevToken is ERC20{
}
Here we’re declaring a new contract called “DevToken”, using the Solidity keyword contract, while inheriting from the ERC20 OpenZeppelin’s contract using the “is” keyword.
Inheriting from the ERC20 contract will give us access to methods like _mint() and balanceOf(). If you want to take a look through all the available methods, you can check the official ERC20 documentation.
The next step is to create a cryptocurrency is to call the contract’s constructor and provide the name and symbol of the Token. To do so, inside the contract, write the following code:
Token.sol
contract DevToken is ERC20{
constructor() ERC20("DevToken", "DVT"){}
}
At this point your code should look like this:
Token.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract DevToken is ERC20{
constructor() ERC20("DevToken", "DVT"){
}
}
**Great!**🎉 One last step before testing our own Cryptocurrency and moving to more complex topics, we now need to effectively deploy our ERC20 Token.
How To Create an ERC20 Token: Mint The Cryptocurrency
As said before, inheriting from the ERC20 contract, gives us access to the _mint() method used to create new tokens, and send them to a given address, exactly what we need now.
Minting is defined as the process of validating information, creating a new block, and recording that information into the blockchain. Simply put, “mint” means: creating something, like a number of Tokens, or an NFT, and saving it on the blockchain.
Let’s say we want to create 1000 tokens and send them to our wallet, to achieve this, we can add the following code in the constructor:
Token.sol
contract DevToken is ERC20{
constructor() ERC20("DevToken", "DVT"){
_mint(msg.sender,1000*10**18);
}
}
There’s a lot going on here, let’s take a second to understand it:
First of all, we’re calling the _mint() function, which is responsible to issue the tokens, and wants two parameters:
to: address of the wallet/contract that will receive the tokens,
amount: amount of tokens to send. The “to” argument, is taken from msg.sender, a special variable which value is the address of the wallet/contract calling the contract.
The amount, on the other hand, needs to take care of the decimals, and that’s why we’re passing such a big number, let me go through it for a second.
A Note On Decimals
When dealing with cryptocurrencies you may want to be able to send arbitrary amounts, like 0.004ETH. Unfortunately, Solidity and the Ethereum Virtual Machine do not support decimals: only integer numbers can be used. This means that only whole numbers can be sent (1, 4, 5), and this, of course, poses an issue. So what’s the workaround? It’s very simple, a token contract can use larger integer values (the EVM supports 256-bit integers) so that a balance of 1000000000000000000 represents 1 ETH with 18 decimal places, hence a transfer of 4000000000000000 will correspond to 0.004ETH being sent. We that in mind, when calculating our total supply, we have to take account of the total amount of tokens, including the decimal places we want to have. If you want a total max supply of 1.000.000.000 tokens, with 18 decimal places, like Ethereum and many other cryptocurrencies have, you want to pass 100000000010*18 that is (1000000000000000000000000000). On the other hand, when sending 2 tokens the method to call will actually be: transfer(recipient, 2 * 101**8);
Ok now that we understand what’s going on in the mint function, let’s test our ERC20 Token contract.
Deploy Your ERC20 Token Cryptocurrency
On REMIX, click on the Solidity icon on the left side of the screen, and click on compile. You might also want to activate auto compile, to allow REMIX to listen for code changes, and compile your code.
This will compile the Token.sol code, populating the artifacts folder with our Token’s Contract abi (application binary interface) and their binary version, used to deploy it on the blockchain. Now that we have our artifacts, click on the Ethereum logo under the Solidity icon, select your contract in the dropdown menu, and click on deploy:
Congratulations! 🎉 If everything worked as expected, you’ve just created and deployed an ERC20 token!
Interact With Your First Cryptocurrency Remember? When deployed, our smart contract should have issued 1000 tokens to our wallet! If you watch, right above the Deploy button, there’s the “account” field:
That’s the address of the wallet we used to deploy our ERC20 Token contract, we can say that because there’s some Ethereum missing, the Gas fees we paid to deploy the contract on the Ethereum Virtual Machine. If everything worked as expected, we should now see the issued amount of tokens in the balance of our wallet’s address. To test this out, as you can notice, right under the deploy button, and “Deployed Contracts”, there’s your deployed ERC20 token. Clicking on the dropdown menu will give you access to all of the ERC20 methods, that your contract has inherited or implemented:
The color of the buttons represents whether the representing function modifies any value on the blockchain, costing Gas (Orange), or it’s a simple view function just reading and returning a value (Blue). Between those buttons, there’s one saying “balanceOf“, it requires an address as an input and will retrieve the associated amount of ERC20 Tokens. Let’s use it:
Copy the wallet address clicking on the “copy” icon near the wallet address.
Scroll down in the token methods and search for “balanceOf”.
Paste the wallet address in the field.
Click the blue balanceOf button.
Check the amount.
Well done, you’ve just created your own cryptocurrency! 🎉
Unfortunately, though, there are two issues at the moment:
Our Token is not yet accessible from outside REMIX because currently deployed on the Remix EVM, a virtual machine that acts as a blockchain, not accessible by anything except your REMIX instance.
Instead of issuing all the tokens on deployment, as we’re doing now, we might want to issue the tokens as a reward, as a consequence of an action, or simply in small batches.
Let’s first address the first issue, how to handle token supply.
Note: REMIX uses a hosted virtual ethereum environment, that can be compared to a testnet but it’s not publicly accessible outside the environment itself. Your contract won’t be deployed on the actual Ethereum mainnet, nor in a publicly accessible testnet.
How to Develop an ERC20: Create A Token Supply That Works
When you need to create your own cryptocurrency supply, we have 3 main choices:
Fixed Supply
Uncapped Lazy Supply
Capped Lazy Supply
At this point, our token has a Fixed supply issued on deployment, let’s explore what it means, and the alternatives we have when developing our cryptocurrencies.
Fixed Supply
The total supply of the token is issued on deployment and sent to the deploying wallet address.
In this case, we choose a total supply beforehand and issue the whole amount to our wallet when the contract’s constructor gets called, leaving us the effort of distributing the tokens among different holders.
If we don’t want to issue all the tokens at once, though, we should opt for a lazy minting approach.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract DevToken is ERC20{
constructor() ERC20("DevToken", "DVT"){
_mint(msg.sender,1000*10**18);
}
}
Uncapped Lazy Supply
Tokens aren’t minted and issued in a unique batch on deployment, but in small quantities and sent to the specified wallet(s), consequently to one or more actions.
In this case, the total max supply is regulated through economic-driven principles and not on a hard-coded value.
Think of a Miner validating a transaction and getting tokens back as a reward, or a user stacking their tokens to receive periodic rewards.
The absence of a hardcoded Max supply, though, could make your token inflationary, incurring a loss of value over time, or worst putting its security at risk. Even if this goes outside the focus of this tutorial, is good to understand that we can, and should, cap our supply.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract DevToken is ERC20{
constructor() ERC20("DevToken", "DVT"){}
function issueToken(address receiver, uint256 amount) public{
_mint(receiver, amount);
}
}
Capped Lazy Supply
Like in the Uncapped Lazy Supply mechanism, the tokens are issued in small quantities, with the only difference that here the max-supply is decided beforehand and hardcoded in the smart contract, or passed on deployment.
In this tutorial, we’re going to broadly explore all the methods to create the supply of our Tokens.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
contract DevToken is ERC20Capped{
constructor(uint256 cap) ERC20("DevToken", "DVT") ERC20Capped(cap){
}
function issueToken() public{
_mint(msg.sender, 1000*10**18);
}
}
How to Create a ERC20 Token – Security and Access Control
Copying what the OpenZeppelin documentation on access-control tells us:
Access control, or “who is allowed to do this thing”, is incredibly important when dealing with smart contracts. The access control of your contract may govern who can mint tokens, vote on proposals, freeze transfers, and many other things**.**
It is therefore critical to understand how you implement it, lest someone else steals your whole system.
The most common and basic form of access control is the concept of ownership where there’s only an account allowed to perform sensitive tasks on a contract (the owner). This approach is perfectly reasonable for contracts that have a single administrative user.
OpenZeppelin provides Ownable for implementing ownership in contracts.
To use it, we’ll need to import the contract in our code, add it as a super-class of our Token contract, just like we did before, and add a function modifier to the issueToken() function ADD LINK:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract DevToken is ERC20, Ownable{
constructor() ERC20("DevToken", "DVT"){}
function issueToken() public onlyOwner{
_mint(msg.sender, 1000*10**18);
}
}
As we can notice, the Token contract is now inheriting both from the ERC20, and Ownable contract, this gives us access to the onlyOwner function modifier applied to the issueToken() function.
onlyOwner will run every time issueToken() gets called, verifying if the caller is the owner of the contract.
By default, the owner of an Ownable contract is the account that deployed it, which is usually exactly what you want.
Now that we have a reasonable understanding of how to design our token supply and how to secure its minting process, let’s learn how to deploy our token to a real and accessible blockchain, setting up a local development environment using Hardhat.
Here is the reference for local env set up:
[ref1]:
[ref2]: