Learn about two types of blockchain tokens: fungible and non-fungible. Learn how to use the ERC-20 token standard. Learn how to use the MetaMask digital wallet.
By the end of this post, readers will be able to:
Some tokens represent assets that have interchangeable and exchangeable values. These are called fungible tokens. Tokens that represent fiat currency or cryptocurrency often fall into this category.
Tokens representing stores of value that aren’t directly comparable and interchangeable are called non-fungible tokens, or NFTs. NFTs depend more on which assets someone owns rather than on how many.
Both types have value, but the value of each NFT is unique. This leads to different sets of rules, processes, and implementations for fungible and non-fungible tokens. The smart contracts that create NFTs follow different standards than those that create fungible tokens.
Developers form standards that outline best practices for the platform to prevent bugs and security vulnerabilities. In Ethereum, these standards are known as Ethereum Improvement Proposals, or EIPs. The Ethereum Foundation officially refers to an EIP as “a design document providing information to the Ethereum community, or describing a new feature for Ethereum or its processes or environment.”
Although there are several categories of EIPs, we’ll focus on Ethereum Request for Comments (ERC). This type of EIP sets standards at the application level. This means that the standards apply to the code for applications, such as smart contracts and tokens.
Most EIPs, including ERCs, follow a similar workflow, which includes the following stages:
Many ERC token standards exist, but we’ll focus on two of the most popular:
We use the ERC-20 standard for fungible Ethereum tokens that store value. The ERC-20 standard defines rules for how the tokens get used, how transactions get made, and how new tokens get created (or minted).
The ERC-20 standard serves as the basis for many cryptocurrencies and coins, especially stablecoins, that exist today. These include Chainlink (LINK), Wrapped Bitcoin (WBTC), Binance Coin (BNB), USD Coin (USDC), and Dai (DAI) for example.
The OpenZeppelin library provides a wide variety of contracts that relate to the ERC-20 token standard. Each of the OpenZeppelin ERC-20 contracts is designed to accomplish something slightly different. And, we can further customize each contract for our particular purposes.
The Ethereum ERC-20 standard defines some mandatory functions for a fungible token contract, including _transfer
, _mint
, balanceOf
, and totalSupply
. These functions provide critical functionality for any ERC-20 token.
We want our ArcadeToken
contract to become a version of the OpenZeppelin ERC20
contract. But, we also want ArcadeToken
to include the optional functions from ERC20Detailed
. So, we’ll import and inherit both the ERC20
and ERC20Detailed
contracts. This will tell Solidity that ArcadeToken
is a version of the ERC20
contract and that it’s also a version of the ERC20Detailed
contract.
pragma solidity ^0.5.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC20/ERC20Detailed.sol";
contract ArcadeToken is ERC20, ERC20Detailed {
}
After we save or compile our contract in the Remix IDE, the ERC20.sol
and ERC20Detailed.sol
contracts that we imported will get downloaded and listed in the Remix files list.
Navigate to the constructor
function inside the ERC20Detailed
contract. This function should appear as follows:
constructor (string memory name, string memory symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
The constructor is a programming technique that many programming languages use. With constructors, you can quickly customize code with your own initial values.
ERC20Detailed
contract. The name
parameter contains the human-friendly name of the token, the symbol
parameter contains the ticker symbol of the token, and the decimals
parameter contains the number of decimal places that this token will use.Using decimal places allows customers to purchase or transfer fractions of a token.
All ETH transactions get conducted in wei. Similarly, all token transactions get conducted in the smallest denomination of a token, which OpenZeppelin calls a bit.
The final token contract appears as follows:
pragma solidity ^0.5.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v2.5.0/contracts/token/ERC20/ERC20Detailed.sol";
contract ArcadeToken is ERC20, ERC20Detailed {
address payable owner;
modifier onlyOwner {
require(msg.sender == owner, "You do not have permission to mint these tokens!");
_;
}
constructor(uint initial_supply) ERC20Detailed("ArcadeToken", "ARCD", 18) public {
owner = msg.sender;
_mint(owner, initial_supply);
}
function mint(address recipient, uint amount) public onlyOwner {
_mint(recipient, amount);
}
}
To deploy and test our contract, we will use the test blockchain application Ganache and an integrated wallet called MetaMask. The purpose of this section is to get familiarized with the high-level integration among Ganache, MetaMask, and Remix.
MetaMask is a wallet that people can use to interact with the Ethereum blockchain or with various Ethereum-related test blockchains. First add a custom Ganache network in MetaMask. Include the information below:
HTTP://127.0.0.1:7545
We can import an account from Ganache into MetaMask. To do that, we first click the My Accounts button in Metamask, and then on the menu that displays, we select Import Account. We make sure that Private Key is selected on the Select Type drop-down menu. We then copy the private key from the Account Information page in Ganache and paste it into the Paste your private key string here box. We then click the Import button.
Open the deployment page in Remix, and then deploy the contract using by the Injected Web environment. Once we select Injected Web3, the MetaMask Chrome extension automatically opens and displays accounts from which we can choose for testing. Select each of the accounts that you just imported from Ganache to import into Remix.
In the Deploy & Run Transactions pane, in the initial_supply box, type an arbitrary amount. This sets the value of the initial_supply
constructor parameter. Then click the transact button.
Once the contract is deployed in Remix, navigate back to Ganache, and then click the Transactions button (which appears along the top of the page). The Transactions page opens and displays the transaction details. This includes the transaction hash, the account address, and the created contract address, as the following image shows:
To summarize this section:
Until next time, here’s a twitter thread summary of this post: