Now that we know what ERC-20 tokens are and how they work, let’s see how we can build and deploy our own token.
We’ll deploy our contract on the Ropsten testnet. To get started, you will need the
Metamask browser extension to create an ETH wallet and some test ETH, which you can get by going to the
Ropsten faucet. You'll need to select Ropsten Test Network on your Metamask wallet and copy-paste the wallet address into the text field in the faucet, then click Send me test Ether.
Head over to the
Ethereum Remix IDE and make a new Solidity file, for example - token.sol
Paste the following code into your new Solidity script:
pragma solidity ^0.4.24;
//Safe Math Interface
contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
c = a + b;
require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
require(b <= a);
c = a - b;
}
function safeMul(uint a, uint b) public pure returns (uint c) {
c = a * b;
require(a == 0 || c / a == b);
}
function safeDiv(uint a, uint b) public pure returns (uint c) {
require(b > 0);
c = a / b;
}
}
//ERC Token Standard #20 Interface
contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
//Contract function to receive approval and execute function in one call
contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}
//Actual token contract
contract QKCToken is ERC20Interface, SafeMath {
string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
constructor() public {
symbol = "QKC";
name = "QuikNode Coin";
decimals = 2;
_totalSupply = 100000;
balances[YOUR_METAMASK_WALLET_ADDRESS] = _totalSupply;
emit Transfer(address(0), YOUR_METAMASK_WALLET_ADDRESS, _totalSupply);
}
function totalSupply() public constant returns (uint) {
return _totalSupply - balances[address(0)];
}
function balanceOf(address tokenOwner) public constant returns (uint balance) {
return balances[tokenOwner];
}
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = safeSub(balances[msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
balances[from] = safeSub(balances[from], tokens);
allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
emit Transfer(from, to, tokens);
return true;
}
function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
return allowed[tokenOwner][spender];
}
function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
return true;
}
function () public payable {
revert();
}
}
Replace the symbol and name with your own:
62 symbol = "QKC";
63 name = "QuikNode Coin";
set the decimal (value in which tokens can be divided, 0to8 decimal units can be used) and establish a total supply value as you wish:
64 decimals = 2;
65 _totalSupply = 100000;
Please change YOUR_METAMASK_WALLET_ADDRESS to your own wallet address (same wallet you specified to obtain test currency):
66 balances[YOUR_METAMASK_WALLET_ADDRESS] = _totalSupply;
67 emit Transfer(address(0), YOUR_METAMASK_WALLET_ADDRESS, _totalSupply);
Note: The total supply value must have additional trailing zeros as specified by the decimals field. For example, the decimals value in this contract is 2 and we need a total supply of 1000 tokens, so we’ll have to set the total supply variable to 100000 (simply because it won’t allow a decimal point).
Explanation of the code above:
Line 1: Declaring the solidity version
Line 3-4: Calling the Safe Math interface to use math functions in our contract.
Line 29-41: Calling the ERC-20 Interface to implement its functions.
Line 44-48: A Contract function to receive approval and execute a function in one call.
Line 52-56: Starting our QKCToken contract, creating a variable symbol of string type to hold our token’s symbol, a variable name of string type to hold our token’s name, variable decimals of unsigned integer type to hold the decimal value for the token division.
Line 58-59: Creating two mapping functions that will grant users the ability to spend these tokens.
Line 61-68: Initializing the constructor, setting symbol, name, decimals, and total supply value for our token. Declaring the total supply of the token to be equal to your wallet’s balance for this token.
Line 70-72: Function totalSupply which will govern the total supply of our token.
Line 74-76: Function balanceOf which will check the balance of a wallet address.
Line 78-83: Function transfer which will execute the transfer of tokens from the total supply to users.
Line 85-89: Function approve which will check if the total supply has the amount of token which needs to be allocated to a user.
Line 91-97: Function transferFrom which will facilitate the transfer of token between users.
Line 99-101: Function allowance which will check if a user has enough balance to perform the transfer to another user.
Line 103-108: Function approveAndCall which executes the transactions of buying and spending of tokens.
Line 110-112: Fallback function to prevent accounts from directly sending ETH to the contract, this prevents the users from spending gas on transactions in which they forget to mention the function name.
Compile the smart-contract and deploy it using injected Web3 (make sure to select Ropsten testnet on Metamask before compiling the contract). Approve the transaction from metamask.
Note: We need to deploy the main token contract, select the name of the contract appropriately under the contracts section before deploying the contract (QKCToken here).
If you receive an error message before deployment “This contract may be abstract”, make sure to select the appropriate contract under the Contract tab.
Confirm the transaction in Metamask
That’s it! your token contract is now deployed on Ethereum’s Ropsten testnet!
To get the token in Metamask, go to the “Deployed Contracts” section in Remix and copy the deployed contract’s address using the copy button near the contract’s name.
Open Metamask and click on the Add Token button, select the Custom Token option and paste the contract’s address in the first field. Metamask will fetch the Token Symbol and decimals automatically.
Click on next and your token will be added to the wallet, it will be available under the assets section in Metamask.