My first ERC20 token (2023)

The token I developed is an ERC20 token called $MTK, implementing the EIP-20 token standard:

We can say that ERC20 is the standard implementation of the Ethereum Improvement Proposal EIP-20, but this definition may not be formally correct.

Anyway, the important thing is that the ERC20 standard is probably the most used standard for fungible token on Ethereum and most of the tokens developed on the Ethereum blockchain are ERC20 token (e.g. $LINK, $USDT, $SHIB, $BAT among others).

The world “fungible” means that any $MTK token has the same value of any other $MTK token. This is the same that happens to standard FIAT currency, where for example 1 EUR coin has the same value as all the 1 EUR coins in circulation.

In the following section I analyze the source code of the smart contracts implementing all the functionalities of the ERC20 token $MTK. The smart contract are written in Solidity programming language and almost all of the functionalities are inherited from OpenZeppelin library, so an analysis of the source code of the library will be performed.

OpenZeppelin Web Site:

Finally, we will deploy the smart contract on a local blockchain for testing and make transactions of $MTK from one wallet to another.

The token source code can be found on the Github Repo:

Implementation of the ERC20 Token Standard is contained in ERC20.sol and IERC20.sol source files of OpenZeppelin.

Specifically, the IERC20.sol interface defines the ERC20 functions while ERC20.sol implements them.


pragma solidity ^0.8.0;interface IERC20 {
// returns the amount of token in circulation.
function totalSupply() external view returns (uint256);
//returns the balance of an account, i.e. the amount of token the account owns.
function balanceOf(address account) external view returns (uint256);
//send amount of token to the recipient address
function transfer(address recipient, uint256 amount) external returns (bool);
//returns how much the owner of the token has allowed another account to transfer the token he owns. (ignore for now)
function allowance(address owner, address spender) external view returns (uint256);
//the owner of tokens allows another account to transfer the token he owns by amount (ignore for now)
function approve(address spender, uint256 amount) external returns (bool);
//transfer token from one account to another. The owner of the token is not the calling address (ignore for now)
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
// event emitted during a transfer (ignore for now)
event Transfer(address indexed from, address indexed to, uint256 value);

// event emitted during an approval (ignore for now)
event Approval(address indexed owner, address indexed spender, uint256 value);



// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {[ . . . ]

The following three functions are also part of ERC20 but are not declared in IERC20.sol:

// returns the name of the token i.e. MyToken
function name() public view virtual override returns (string memory);
// return the symbol of the token i.e. MTK
function symbol() public view virtual override returns (string memory);
// Returns the number of decimals used to get its user representation (see below).
function decimals() public view virtual override returns (uint8);

I don’t know the specific reason why OpenZeppelin decided to not declare also these 3 functions in IERC20.sol, but defined them directly in the ERC20.sol smart contract.

You can find the source code here:


The _mint() function is defined in ERC20.sol at line 251.

function _mint(address account, uint256 amount) internal virtual {
[ . . . ]
_totalSupply += amount;
_balances[account] += amount;
[ . . . ]

the _mint function creates new “amount” of token and increases the total supply. It assigns the new token to the “account” that is calling the function. This function is useful in order to mantain the synchronization between the totalSupply and the balance of the minted account (which increases by amount) and should always be used when increasing the total amount of an ERC20 token.


The _burn() function is defined in ERC20.sol at line 274.

function _burn(address account, uint256 amount) internal virtual {
[ . . . ]
uint256 accountBalance = _balances[account];
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
[ . . . ]

the _burn() function is exactly the opposite of the _mint() function. In fact it is used in order to decrease the total supply of token. The amount of token will be burned from the account balance. When this operation is performed by developers, usually it results in a price increase of remaining tokens. The opposite is true for minting, which usually decreases the price of token.

Transferring tokens between accounts.

It is important to note that when transferring tokens between accounts, the only transaction that happens on the blockchain is the contract call. In fact, when transferring tokens from one account to another (by using transfer() or transferFrom()) what the token contract does is simply update its own internal variable “_balances”, which contains for each account the amount of tokens it owns. This is showed in the snippets of code below.


mapping(address => uint256) private _balances;

The “_balances” variable contains for each address the amount of token it owns, expressed in unsigned integer.

The transfer() function of the ERC20 smartcontract updates this mapping, as shown in the following code.

function _transfer(address sender, address recipient, uint256 amount ) internal virtual {
[ . . . ]
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
_balances[recipient] += amount;
[ . . . ]

This is the transfer() function which is implemented at line 220 of ERC20.sol.

A note about decimals.

You may have noticed the following function defined in ERC20.sol:

function decimals() public view virtual override returns (uint8) {
return 18;

What is its purpose?

Unfortunately, the solidity language and EVM does not support floating point number data-type: which means that all arithmetic operations in smart contracts happens between integers types. But what happens if you want to transfer 1.5 token? It is not possible in Solidity, so the EIP-20 Token Standard provides the decimals property, which defines how many 0s must be considered for the token.

For example, suppose an EOA wants to transfer 1.5 tokens to another EOA. In the user interface of the wallet it specifies the 1.5 tokens as the amount to transfer, but in reality the amount of token transferred is 1.5 * decimals. To be able to transfer 1.5 tokens, decimals must be at least 1, since that number has a single decimal place.

(Video) Create your First ERC20 TOKEN & SELL IT - React, Solidity & Truffle

In OpenZeppelin decimals by default are set to 18, so when transferring 1.5 token, in reality the calculation is performed on 1.5*10¹⁸ = 1500000000000000000.

For more information: (

Extensions provide useful utilities for token management after the smart contract is deployed. Extensions are smart contract implemented in Solidity language and are part of the OpenZeppein library. I’ve used the extensions in order to give to my token the following capabilities:

  • dinamically minting new token;
  • dinamically burning token;
  • dinamically pausing all token’s operation.

Excluding pausing, the minting and burning capabilities are already implemented in the ERC20.sol smart contract so what is the reason to implement them in another contract? Because the functions in ERC20.sol are internal, thus them can not be called after the contract is deployed. In order for a function to be called by a transaction, the function must be declared public.


The ERC20PresetMinterPauser.sol contract provides the public mint() function, which can be called by an account with role MINTER_ROLE in order to increase the total supply of the token.


function mint(address to, uint256 amount) public virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
_mint(to, amount);


The public mint() function calls the internal _mint() function of ERC20.sol.


The ERC20Burnable.sol contract provides the public burn() function, which can be called by an account with role BURNER_ROLE in order to decrease the total supply of token.


function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);



the ERC20PresetMinterPauser.sol contract, by inerithing from ERC20Pausable.sol, provides the pause() function which pauses all the token transfers until unpause() is called. This can be useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug.


function pause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");


function unpause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");

The contract Pausable.sol defines the _pause variable:

bool private _paused;

Which is initially set to “false” in the constructor.

constructor() {
_paused = false;

And updated by calling the public functions “pause()” and “unpause()”.


function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());


function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());

In myERC20Token it is implemented a Role-Based Access Control mechanism ( using the AccessControl.sol smart contract of the OpenZeppelin library.

A role authorizes an account to call a specific function inside the token’s smart contract. Accounts can have 0 or more roles.

Defining roles.

Three roles were defined in the MyTokenERC20 implementation:

  • Burner role
  • Minter role
  • Pauser role

The Minter and Pauser roles are defined in the ERC20PresetMinterPauser.sol smart contract at line 26 and 27.

bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

And the Burner role is defined in MyTokenERC20.sol smart contract, at line 9.

bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");

Using roles.

Roles are saved inside the AccessControl.sol smart contract using the “_roles” mapping and the “RoleData” structure, defined at line 49–54.

[ . . . ]
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
mapping(bytes32 => RoleData) private _roles;
[ . . . ]

In the above code, the “RoleData” structure contains a mapping between an address and a boolean value. The “_roles” member of the AccessControl smart contract is a mapping between a role and the account having that role. Given an account and a role, you can test if the account has the role by looking at the “members” field of “RoleData”. This is what the “hasRole” function does at line 83 of AccessControl.sol.

function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];

Finally, the field “adminRole” in “RoleData” contains the admin role for the role. In fact, in OpenZeppelin’s implementation of Access Control mechanism, for each role there is an admin role: an account with admin role has permission to grant or revoke the role to all accounts.

For example: suppose the admin role for the BURNER_ROLE role is called BURNER_ADMIN_ROLE. Account A has the BURNER_ADMIN_ROLE role. Thus account A can grant and revoke the role BURNER_ROLE to any account of the token, including himself.

Granting and revoking roles.

We have already encountered the functions grantRole() and revokeRole() of AccessControl.sol in the section above. As their name says, these functions are used respectively to grant a role to an account and to revoke a role. Remember that only the admin role for the role can grant or revoke the role to other account. However, roles can also be assigned during the smart contract creation, i.e. in the contructor; in this case the internal : _setupRole() function is used.

constructor(string memory name, string memory symbol) ERC20(name, symbol) {
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
_setupRole(MINTER_ROLE, _msgSender());
_setupRole(PAUSER_ROLE, _msgSender());

The contructor of ERC20PresetMinterPauser smart contract assigns the DEFAULT_ADMIN_ROLE, the MINTER_ROLE and the PAUSER_ROLE to the creator of the contract. Than calls the _setupRole() function of AccessControl.sol

(Video) ERC20 Token Tutorial | Create Your Own Cryptocurrency

function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);

Which in turn calls the internal _grantRole() function.

function _grantRole(bytes32 role, address account) private {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());

Checking the role of accounts to authorize operations on smart contract.

In order to check that an account has the role to perform the specific action the require() function is used. It can be used in two ways:

  • by directly calling require() inside the function body of the privileged function;
  • by defining the require() statement inside a modifier and including the modifier inside the privileged function.

I prefer the “modifier” way, because I think is less error-prone.


function burn(uint256 value) public onlyRole(BURNER_ROLE) override {
super._burn(msg.sender, value);

In the OpenZeppelin library, both approaches are used. Specifically, ERC20PresetMinterPauser.sol uses the first approach while AccessControl.sol uses the second approach, as can be seen in the snippet of code below.


function mint(address to, uint256 amount) public virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
_mint(to, amount);


function pause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");


function unpause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");


function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);


function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);

Note about TimeLock.

Please note that OpenZeppelin provides also a TimeLock mechanism to enforce the security policy, specifically this mecanism can be used in order to not let an administrator perform a malicious task. However i’ve not implemented this mechanism in myERC20Token because…

For example, the timelock security mechanism can be used by legitimate projects to prevent “rug pull” scams.


The base contract that I have personally implemented is MyERC20Token.sol and is composed by a few lines of code, because has we have seen allthe functionalities are implemented in the OpenZeppelin library, which the contract includes.

Specifically, the file includes the ERC20PresetMinterPauser.sol contract, which in turn includes ERC20.sol. ERC20PresetMinterPauser.sol also includes AccessControlEnumerable, ERC20Burnable and ERC20Pausable, the smart contracts providing the functionalities explained in the previous sections.

Here is the source code of MyTokenERC20.sol.

// contracts/MyTokenERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";contract MyTokenERC20 is ERC20PresetMinterPauser { bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");constructor(uint256 initialSupply) ERC20PresetMinterPauser("MyToken", "MTK") {
_mint(msg.sender, initialSupply);
grantRole(BURNER_ROLE, msg.sender);
function burn(uint256 value) public onlyRole(BURNER_ROLE) override {
super._burn(msg.sender, value);
fallback() external payable { revert(); }

The source code can be found here:

Analysis of the contract.

The MyERC20Token.sol defines the BURNER_ROLE role at line 9.

bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");

An account having this role can burn tokens thus decreasing the total number of token in circulation.

The contructor for my token is at line 11.

constructor(uint256 initialSupply) ERC20PresetMinterPauser("MyToken", "MTK") {
_mint(msg.sender, initialSupply);
grantRole(BURNER_ROLE, msg.sender);

The token we will deploy is called “MyToken” with symbol MTK. The constructor assigns the BURNER_ROLE to the creator of the smart contract (i.e. msg.sender). The constructor takes one argument, which is the total supply of the token, expressed in uint256. To assign the initial supply, the _mint() function provided by the contract ERC20.sol is used.

The contract defines the burn() function at line 16.

function burn(uint256 value) public onlyRole(BURNER_ROLE) override {
super._burn(msg.sender, value);

Accounts with the BURNER_ROLE role can “burn” tokens. In order to check that the account calling the function burn() has the right role, it uses the “onlyRole” modifier. An account burns tokens from its balance, thus when burning tokens the balance of account must be >= to the quantity of token burned, and this line in the _burn() function of ERC20.sol at line 280 does the check:

require(accountBalance >= amount, "ERC20: burn amount exceeds balance");

Finally, the contract implements the fallback() function at line 21.

// REJECT any incoming ether
fallback() external payable { revert(); }

The fallback() function in Solidity is a function invoked in the absence of data or a declared function name in the transaction. In this case I implemented this function in order to prevent locking forever ether in the smart contract. For example, if an account wants to send ethers to another account, but by mistake inserts the contract’s address in the destination address, the ether will be locked forever and no one can withdrawal them from the contract, because the contract does not provide any “withdrawal” function. In order to prevent this scenario, the fallback() function calls revert() thus canceling the transaction and saving the ethers of the caller.

Deploy the myERC20Token on Ethereum blockchain

Smart contracts can be deployed on different networks. The main Ethereum network is called “mainnet” where you use real ETH, so real money. In order to test smart contracts, developers can use other Ethereum test networks. “Ropsten” is the principal test network on Ethereum that provides an environment which works the same way as the main blockchain. Another valid alternative for testing is to use the “ganache” blockchain, which is an Ethereum blockchain that runs on localhost.

For demonstration purpose I will deploy myERC20Token on “ganache” which you can download from the following URL:

Once downloaded run the ganache binary. It shows the following page:

My first ERC20 token (1)

Click on the “Quickstart Ethereum” button and ganache will instantiate a new blockchain which runs on localhost on port 7545.

My first ERC20 token (2)

In the above screenshot you can see that ganache creates 10 new wallets, each one having a balance of 100 ETH.

The “ganache” software is part of “truffle suite”, which essentially is a node.js framework that help developers deploy smart contracts and interact with them by using the web3.js JavaScript library.

Truffle Web Site:

In order to deploy the token, clone the token source code from github repo ( and run the following commands inside the repo directory:

$ npm install
$ truffle deploy --network ganache

The output of truffle shows information about the transaction:

Compiling your contracts...
> Everything is up to date, there is nothing to compile.
Starting migrations...
> Network name: 'ganache'
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)
Replacing 'Migrations'
> transaction hash: 0xcc061045784b2b6dc332035b6d01bdcdbfe12313e12472369949d48b9f4597bd
> Blocks: 0 Seconds: 0
> contract address: 0xF1FF9a87e6a270A88C5651222053C9B7C93d3799
> block number: 1
> block timestamp: 1638093841
> account: 0x4526fC5171752CC3eA6A3173E75625553cbC8D1f
> balance: 99.9969218
> gas used: 153910 (0x25936)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0030782 ETH
> Saving migration to chain.
> Saving artifacts
> Total cost: 0.0030782 ETH
Replacing 'MyTokenERC20'
> transaction hash: 0x44dd2e171a86b3e6fde7ff8980d6b3b7d6f4a6dbe44f792a3b2eb2fc823c6ef1
> Blocks: 0 Seconds: 0
> contract address: 0x3c0acBad62C03443953c521FBe16375777A1dF80
> block number: 3
> block timestamp: 1638093841
> account: 0x4526fC5171752CC3eA6A3173E75625553cbC8D1f
> balance: 99.95611126
> gas used: 1998237 (0x1e7d9d)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.03996474 ETH
> Saving migration to chain.
> Saving artifacts
> Total cost: 0.03996474 ETH
> Total deployments: 2
> Final cost: 0.04304294 ETH

The amount of ETH spent for the two transaction was 0.04304294 ETH.

We can see that 2 contracts where deployed: Migrations and MyTokenERC20.

Migrations is a smart contract provided by truffle that helps managing deployment of all other smart contracts. The Migrations.sol smart contract has the following source code:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract Migrations {
address public owner = msg.sender;
uint public last_completed_migration;
modifier restricted() {
msg.sender == owner,
"This function is restricted to the contract's owner"
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;

See the doc of truffle for more information on migrations:

Basically, when you to deploy a smart contract using the “truffle deploy” command you first make a transaction to the Migrations smart contract as can be seen in the above screenshot.

My first ERC20 token (3)

Interacting with the smart contract

In order to interact with the deployed smart contract by using web3.js, run the following command:

$ truffle console --network ganache

This will open a console where you can issue JavaScript code using web3.js. For example, now I will transfer 1000 token from one account (the account that received the total supply of 10¹⁸ MyTokenERC20) to another account. The account are available in the “accounts” array:

truffle(ganache)> accounts
[ '0x4526fC5171752CC3eA6A3173E75625553cbC8D1f',
'0x69A8432E6720d4B4a642b6e7217DaB741F5e0133' ]

In order to interact with the MyTokenERC20 smart contract we need an instance.

truffle(ganache)> var mytoken = await MyTokenERC20.deployed()

If we call the balanceOf() ERC20 method on mytoken, we can see the balance of accounts.

Balance of accounts[0]:

(Video) Exercise 8: Create an ERC20 Token (new HARDHAT)

truffle(ganache)> mytoken.balanceOf(accounts[0]).then(a => a.toString())

Balance of accounts[1]:

truffle(ganache)> mytoken.balanceOf(accounts[1]).then(a => a.toNumber())

Now we send 1000 token from accounts[0] to account [1]:

truffle(ganache)> mytoken.transfer(accounts[1], 1000)
{ tx:
{ transactionHash:
transactionIndex: 0,
blockNumber: 5,
from: '0x4526fc5171752cc3ea6a3173e75625553cbc8d1f',
to: '0x3c0acbad62c03443953c521fbe16375777a1df80',
gasUsed: 52354,
cumulativeGasUsed: 52354,
contractAddress: null,
logs: [ [Object] ],
status: true,
rawLogs: [ [Object] ] },
[ { logIndex: 0,
transactionIndex: 0,
blockNumber: 5,
address: '0x3c0acBad62C03443953c521FBe16375777A1dF80',
type: 'mined',
id: 'log_ca948418',
event: 'Transfer',
args: [Result] } ] }

The transaction details are returned inside the “tx” object. The transaction was successful and the balances are now updated.

Balance of accounts[0]:

truffle(ganache)> mytoken.balanceOf(accounts[0]).then(a => a.toString())

Balance of accounts[1]:

truffle(ganache)> mytoken.balanceOf(accounts[1]).then(a => a.toString())

Join Coinmonks Telegram Channel and Youtube Channel learn about crypto trading and investing

Also Read

An ultimate guide to Leveraged Token [Bull Token]Leveraged tokens are ERC20 tokens with leveraged exposure without taking care of the margin, requirements, management…
Best Crypto Lending Platform in 2021 | Top 6 Bitcoin Lending PlatformsGet the best lending interest rates for Bitcoin and other
Best FREE Crypto Trading Bots in 2021Best crypto trading bots for Binance, Coinbase, Kucoin, and other crypto exchanges in 2021. Quadency, Bitsgap…
Best 4 Crypto Trading Signals Telegram ChannelsIt is tedious to find the right crypto trading signals provider. So, in this article, we will be talking about the best…


How do I start my own ERC20 token? ›

Create an ERC20 Token on Kaleido
  1. Step 1: Create a Kaleido account. If you haven't already, sign up for a Kaleido account here. ...
  2. Step 2: Create a blockchain network. To get started, create a blockchain network. ...
  3. Step 3: Create a Token pool. ...
  4. Step 4: ERC20 Transactions. ...
  5. Step 5: Transferring Tokens.
Jan 27, 2023

How do I find my ERC20 tokens? ›

To view your ETH or ERC-20 address, navigate and select the Deposit Ether Directly tab. Then click on View Account to see and copy your address. You can now paste the Ethereum address on airdrop portals requesting an ERC-20 address to receive free tokens.

What was the first Ethereum token? ›

A total of 60 million Ether (the primary cryptocurrency of the Ethereum platform) were created to sell; this is also known as the Genesis issuance, as these are the first ever Ether tokens created. The price was 2,000 Ether (ETH) = one Bitcoin (BTC) for the first 14 days of the sale.

How do I convert my ERC20 tokens to cash? ›

Withdraw ETC from MyEtherWallet:
  1. Unlock the wallet that held DAO Tokens.
  2. Enter the address you want to withdraw to.
  3. Enter the amount you want to donate to the WHG (the people who spent a huge amount of time trying to get the ETC into a contract so you could withdraw it)
  4. Press button.
  5. Go to send tab.
  6. Enter exc.

How much does it cost to launch ERC20 token? ›

On average if you are looking to start a decent ICO project, it will cost you between $500-$2000 for creating millions of ERC20 tokens.

How much does it cost to deploy ERC20 token to Mainnet? ›

Deploying your token on the Mainnet​

As of December 2021 this cost is less than $0.01 US. You can learn how to get Celo here. You can read about how to add your new token to the Celo Wallet here.

How can I recover my ERC token? ›

To recover funds, customers must provide their Ethereum transaction identification for the lost assets and the contract address of the lost asset. The recovery tool only works for select ERC-20 tokens sent into Coinbase.

Can you withdraw ERC20 tokens? ›

Select Tether USDT ERC20 from the Withdrawal section of your PA. Choose the trading account you wish to withdraw from and the amount in USD, as well as your private wallet address; take care to provide this exact or funds may be lost and irrecoverable.

How do I get my ERC20 token from MetaMask? ›

Add token to MetaMask
  1. Open the MetaMask extension in your web browser.
  2. Select the Assets tab.
  3. Scroll down and click Import tokens.
  4. Select the Custom Token tab.
  5. Insert the contract address of the token to the field Token Contract Address. ...
  6. Click Add Custom Token. ...
  7. Click Import Tokens.
Sep 15, 2022

When was Ethereum worth $1? ›

Since its creation in 2015, Ethereum was under $1 for the major part of 2015, but by March 2016 Ether crossed the $10 mark, when it briefly reached $10.03 on March 4, 2016.

Is ERC20 the same as ETH? ›

What's the Difference Between ETH and ERC-20? Ether (ETH) is the native token used by the Ethereum blockchain and network as a payment system for verifying transactions. ERC-20 is the standard for creating smart contract-enabled fungible tokens to be used in the Ethereum ecosystem.

How many ERC20 token are there? ›

So how many ERC20 tokens are there and Types of ERC20 tokens to buy in 2022. If you do not know yet, let's take a look at the article below. How many ERC20 tokens are there? As such, there are currently over 450,000 ERC20 token contracts, according to Etherscan.

How much is 1 ERC20 in usd? ›

Conversion tables

The current value of 1 ERC20 is $0.01 USD.

Can you send ERC20 tokens to Coinbase? ›

Coinbase Wallet supports thousands of tokens, including all ERC-20 tokens and all tokens on EVM-compatible chains, such as Avalanche C-Chain and Polygon. This includes stablecoins (like USDC and DAI) on all of Coinbase Wallet's supported networks. Coinbase Wallet also supports tokens hosted on the Solana Network.

What can you do with your own ERC20 token? ›

An ERC20 token is a standard used for creating and issuing smart contracts on the Ethereum blockchain. Smart contracts can then be used to create smart property or tokenized assets that people can invest in.

Is it free to create ERC20 token? ›

Create crypto tokens with zero code. Mint ERC20, BEP20 tokens & NFT's on the blockchain, right now, for free.

How long does it take to create an ERC20 token? ›

In this guide, Toptal Freelance Ethereum Developer Gilad Haimov demonstrates how you can create and deploy your own ERC20 token in under an hour. The humble ERC20 token specification has become the de facto standard for Ethereum tokens. If you come across an Ethereum smart contract, chances are it's ERC20-compliant.

Do ERC20 tokens need to be mined? ›

ERC-20 tokens, unlike Ethereum and its native coins (ether), cannot be mined.

How do I make my own token coin? ›

  1. Create a MetaMask Account. Metamask wallet serves as a gateway to blockchain apps, and this is one of the first things that you have to do to get started. ...
  2. Add some Ether to your Wallet. ...
  3. Let's Create the Token. ...
  4. Edit the Code. ...
  5. Compiling the code. ...
  6. Add Token to Your Wallet.


1. Create and Transfer My First 1 Million ERC20 Tokens
(Citizen Inventor)
2. Deploy An ERC20 Token In 5 Minutes With OpenZeppelin and Remix
(Crypto Scraper)
3. Setup Your First ERC-20 Smart Contract Token for Ethereum & Unity
4. How to Identify ERC20 Tokens
(Crypto Tips)
5. How to create and deploy an ERC20 token
6. How to create your own Ethereum(ERC20) Token
Top Articles
Latest Posts
Article information

Author: Terrell Hackett

Last Updated: 12/15/2022

Views: 6645

Rating: 4.1 / 5 (52 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Terrell Hackett

Birthday: 1992-03-17

Address: Suite 453 459 Gibson Squares, East Adriane, AK 71925-5692

Phone: +21811810803470

Job: Chief Representative

Hobby: Board games, Rock climbing, Ghost hunting, Origami, Kabaddi, Mushroom hunting, Gaming

Introduction: My name is Terrell Hackett, I am a gleaming, brainy, courageous, helpful, healthy, cooperative, graceful person who loves writing and wants to share my knowledge and understanding with you.