ERC20

ERC20 token

ERC20 is the Ethereum token standard which is used for Ethereum smart contracts. Developed in 2015, ERC-20 defines a common list of rules that an Ethereum token has to implement. Giving developers the ability to program how new tokens will function within the Ethereum ecosystem. This token protocol became popular with crowdfunding companies via Initial Coin Offering (ICO).

Mercury Protocol’s Global Messaging Token is an example of an application based on ERC20 tokens.

The ERC20 token standard describes the functions and events that an Ethereum token contract has to implement.

Contents

The ERC20 Token Standard Interface

Following is an interface contract declaring the required functions and events to meet the ERC20 standard:

 1 // ----------------------------------------------------------------------------  2 // ERC Token Standard #20 Interface  3 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md  4 // ----------------------------------------------------------------------------  5 contract ERC20Interface {  6     function totalSupply() public constant returns (uint);  7     function balanceOf(address tokenOwner) public constant returns (uint balance);  8     function allowance(address tokenOwner, address spender) public constant returns (uint remaining);  9     function transfer(address to, uint tokens) public returns (bool success); 10     function approve(address spender, uint tokens) public returns (bool success); 11     function transferFrom(address from, address to, uint tokens) public returns (bool success); 12  13     event Transfer(address indexed from, address indexed to, uint tokens); 14     event Approval(address indexed tokenOwner, address indexed spender, uint tokens); 15 } 

Most of the major tokens on the Ethereum blockchain are ERC-20-compliant. The GNT Golem Network Token is only partially-ERC20 blockchain-compliant as it does not implement the approve(...), allowance(..) and transferFrom(...) functions, and the Approval(...) event.

Some of the tokens include further information describing the token contract:

1     string public constant name = "Token Name"; 2     string public constant symbol = "SYM"; 3     uint8 public constant decimals = 18;  // 18 is the most common number of decimal places 


How Does ERC-20 Token Contract Work?

Following is a fragment of a token contract to demonstrate how a token contract maintains the token balance of Ethereum accounts:

 1 contract TokenContractFragment {  2    3     // Balances for each account  4     mapping(address => uint256) balances;  5    6     // Owner of account approves the transfer of an amount to another account  7     mapping(address => mapping (address => uint256)) allowed;  8    9     // Get the token balance for account `tokenOwner` 10     function balanceOf(address tokenOwner) public constant returns (uint balance) { 11         return balances[tokenOwner]; 12     } 13   14     // Transfer the balance from owner's account to another account 15     function transfer(address to, uint tokens) public returns (bool success) { 16         balances[msg.sender] = balances[msg.sender].sub(tokens); 17         balances[to] = balances[to].add(tokens); 18         Transfer(msg.sender, to, tokens); 19         return true; 20     } 21   22     // Send `tokens` amount of tokens from address `from` to address `to` 23     // The transferFrom method is used for a withdraw workflow, allowing contracts to send 24     // tokens on your behalf, for example to "deposit" to a contract address and/or to charge 25     // fees in sub-currencies; the command should fail unless the _from account has 26     // deliberately authorized the sender of the message via some mechanism; we propose 27     // these standardized APIs for approval: 28     function transferFrom(address from, address to, uint tokens) public returns (bool success) { 29         balances[from] = balances[from].sub(tokens); 30         allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens); 31         balances[to] = balances[to].add(tokens); 32         Transfer(from, to, tokens); 33         return true; 34     } 35   36     // Allow `spender` to withdraw from your account, multiple times, up to the `tokens` amount. 37     // If this function is called again it overwrites the current allowance with _value. 38     function approve(address spender, uint tokens) public returns (bool success) { 39         allowed[msg.sender][spender] = tokens; 40         Approval(msg.sender, spender, tokens); 41         return true; 42     } 43 } 

Blockchain Token Balance

For an example, assume that this token contract has two token holders:

  • 0x1111111111111111111111111111111111111111 with a balance of 100 units
  • 0x2222222222222222222222222222222222222222 with a balance of 200 units

The token contract’s balances data structure will contain the following information:

balances[0x1111111111111111111111111111111111111111] = 100 balances[0x2222222222222222222222222222222222222222] = 200 

The balanceOf(...) function will return the following values:

tokenContract.balanceOf(0x1111111111111111111111111111111111111111) will return 100 tokenContract.balanceOf(0x2222222222222222222222222222222222222222) will return 200 

Transfer Token Balance

If 0x1111111111111111111111111111111111111111 wants to transfer 10 tokens to 0x2222222222222222222222222222222222222222, 0x1111111111111111111111111111111111111111 will execute the function:

tokenContract.transfer(0x2222222222222222222222222222222222222222, 10) 

The token contract’s transfer(...) function will alter the balances data structure to contain the following information:

balances[0x1111111111111111111111111111111111111111] = 90 balances[0x2222222222222222222222222222222222222222] = 210 

The balanceOf(...) function will now return the following values:

tokenContract.balanceOf(0x1111111111111111111111111111111111111111) will return 90 tokenContract.balanceOf(0x2222222222222222222222222222222222222222) will return 210 

Approve And TransferFrom Token Balance

ERC20 Source code If 0x1111111111111111111111111111111111111111 wants to authorise 0x2222222222222222222222222222222222222222 to transfer some tokens to 0x2222222222222222222222222222222222222222, 0x1111111111111111111111111111111111111111 will execute the function:

tokenContract.approve(0x2222222222222222222222222222222222222222, 30) 

The approve data structure will now contain the following information:

tokenContract.allowed[0x1111111111111111111111111111111111111111][0x2222222222222222222222222222222222222222] = 30 

If 0x2222222222222222222222222222222222222222 wants to later transfer some tokens from 0x1111111111111111111111111111111111111111 to itself, 0x2222222222222222222222222222222222222222 executes the transferFrom(...) function:

tokenContract.transferFrom(0x1111111111111111111111111111111111111111, 0x2222222222222222222222222222222222222222, 20) 

The balances data structure will be altered to contain the following information:

tokenContract.balances[0x1111111111111111111111111111111111111111] = 70 tokenContract.balances[0x2222222222222222222222222222222222222222] = 230 

And the approve data structure will now contain the following information:

tokenContract.allowed[0x1111111111111111111111111111111111111111][0x2222222222222222222222222222222222222222] = 10 

0x2222222222222222222222222222222222222222 can still spend 10 tokens from 0x1111111111111111111111111111111111111111.

The balanceOf(...) function will now return the following values:

tokenContract.balanceOf(0x1111111111111111111111111111111111111111) will return 70 tokenContract.balanceOf(0x2222222222222222222222222222222222222222) will return 230 


Sample Fixed Supply Token Contract

Following is a sample Fixed Supply Token contract with a fixed supply of 1,000,000 units that are initially assigned to the owner of the contract. This token has 18 decimal places: ERC20 Code:

  1 // SPDX-License-Identifier: MIT   2 // ----------------------------------------------------------------------------   3 // 'FIXED' 'Example Fixed Supply Token' token contract   4 //   5 // Symbol      : FIXED   6 // Name        : Example Fixed Supply Token   7 // Total supply: 1,000,000.000000000000000000   8 // Decimals    : 18   9 //  10 // Enjoy.  11 //  12 // (c) BokkyPooBah / Bok Consulting Pty Ltd 2018. The MIT Licence.  13 // ----------------------------------------------------------------------------  14   15 // ----------------------------------------------------------------------------  16 // Updated     : To support Solidity version 0.6.12  17 // Programmer  : Ts. Dr. Mohd Anuar Mat Isa, PhDs (EE & CS), iExplotech & IPTM Secretariat (www.iexplotech.com)  18 // Link        : https://github.com/iexplotech/SmartContract/blob/master/FixedSupplyToken_0.6.x.sol  19 // Tested      : Remix IDE, 10 Nov 2020  20 // ----------------------------------------------------------------------------  21   22 pragma solidity ^0.6.12;  23   24 // ----------------------------------------------------------------------------  25 // Safe maths  26 // ----------------------------------------------------------------------------  27 library SafeMath {  28     function add(uint a, uint b) internal pure returns (uint c) {  29         c = a + b;  30         require(c >= a);  31     }  32     function sub(uint a, uint b) internal pure returns (uint c) {  33         require(b <= a);  34         c = a - b;  35     }  36     function mul(uint a, uint b) internal pure returns (uint c) {  37         c = a * b;  38         require(a == 0 || c / a == b);  39     }  40     function div(uint a, uint b) internal pure returns (uint c) {  41         require(b > 0);  42         c = a / b;  43     }  44 }  45   46   47 // ----------------------------------------------------------------------------  48 // ERC Token Standard #20 Interface  49 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md  50 // ----------------------------------------------------------------------------  51 interface ERC20Interface {  52     function totalSupply() external view returns (uint);  53     function balanceOf(address tokenOwner) external view returns (uint balance);  54     function allowance(address tokenOwner, address spender) external view returns (uint remaining);  55     function transfer(address to, uint tokens) external returns (bool success);  56     function approve(address spender, uint tokens) external returns (bool success);  57     function transferFrom(address from, address to, uint tokens) external returns (bool success);  58   59     event Transfer(address indexed from, address indexed to, uint tokens);  60     event Approval(address indexed tokenOwner, address indexed spender, uint tokens);  61 }  62   63   64 // ----------------------------------------------------------------------------  65 // Contract function to receive approval and execute function in one call  66 //  67 // Borrowed from MiniMeToken  68 // ----------------------------------------------------------------------------  69 interface ApproveAndCallFallBack {  70     function receiveApproval(address from, uint256 tokens, address token, bytes memory data) external;  71 }  72   73   74 // ----------------------------------------------------------------------------  75 // Owned contract  76 // ----------------------------------------------------------------------------  77 contract Owned {  78     address payable public  owner;  79     address payable public newOwner;  80   81     event OwnershipTransferred(address indexed _from, address indexed _to);  82   83     constructor() public {  84         owner = msg.sender;  85     }  86   87     modifier onlyOwner {  88         require(msg.sender == owner);  89         _;  90     }  91   92     function transferOwnership(address payable _newOwner) public onlyOwner {  93         newOwner = _newOwner;  94     }  95     function acceptOwnership() public {  96         require(msg.sender == newOwner);  97         emit OwnershipTransferred(owner, newOwner);  98         owner = newOwner;  99         newOwner = address(0); 100     } 101 } 102  103  104 // ---------------------------------------------------------------------------- 105 // ERC20 Token, with the addition of symbol, name and decimals and a 106 // fixed supply 107 // ---------------------------------------------------------------------------- 108 contract FixedSupplyToken is ERC20Interface, Owned { 109     using SafeMath for uint; 110  111     string public symbol; 112     string public  name; 113     uint8 public decimals; 114     uint _totalSupply; 115  116     mapping(address => uint) balances; 117     mapping(address => mapping(address => uint)) allowed; 118  119  120     // ------------------------------------------------------------------------ 121     // Constructor 122     // ------------------------------------------------------------------------ 123     constructor() public { 124         symbol = "FIXED"; 125         name = "Example Fixed Supply Token"; 126         decimals = 18; 127         _totalSupply = 1000000 * 10**uint(decimals); 128         balances[owner] = _totalSupply; 129         emit Transfer(address(0), owner, _totalSupply); 130     } 131  132     // ------------------------------------------------------------------------ 133     // Total supply 134     // ------------------------------------------------------------------------ 135     function totalSupply() public view virtual override returns (uint) { 136         return _totalSupply.sub(balances[address(0)]); 137     } 138  139  140     // ------------------------------------------------------------------------ 141     // Get the token balance for account `tokenOwner` 142     // ------------------------------------------------------------------------ 143     function balanceOf(address tokenOwner) public view virtual override returns (uint balance) { 144         return balances[tokenOwner]; 145     } 146  147  148     // ------------------------------------------------------------------------ 149     // Transfer the balance from token owner's account to `to` account 150     // - Owner's account must have sufficient balance to transfer 151     // - 0 value transfers are allowed 152     // ------------------------------------------------------------------------ 153     function transfer(address to, uint tokens) public virtual override returns (bool success) { 154         balances[msg.sender] = balances[msg.sender].sub(tokens); 155         balances[to] = balances[to].add(tokens); 156         emit Transfer(msg.sender, to, tokens); 157         return true; 158     } 159  160  161     // ------------------------------------------------------------------------ 162     // Token owner can approve for `spender` to transferFrom(...) `tokens` 163     // from the token owner's account 164     // 165     // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md 166     // recommends that there are no checks for the approval double-spend attack 167     // as this should be implemented in user interfaces 168     // ------------------------------------------------------------------------ 169     function approve(address spender, uint tokens) public virtual override returns (bool success) { 170         allowed[msg.sender][spender] = tokens; 171         emit Approval(msg.sender, spender, tokens); 172         return true; 173     } 174  175  176     // ------------------------------------------------------------------------ 177     // Transfer `tokens` from the `from` account to the `to` account 178     // 179     // The calling account must already have sufficient tokens approve(...)-d 180     // for spending from the `from` account and 181     // - From account must have sufficient balance to transfer 182     // - Spender must have sufficient allowance to transfer 183     // - 0 value transfers are allowed 184     // ------------------------------------------------------------------------ 185     function transferFrom(address from, address to, uint tokens) public virtual override returns (bool success) { 186         balances[from] = balances[from].sub(tokens); 187         allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens); 188         balances[to] = balances[to].add(tokens); 189         emit Transfer(from, to, tokens); 190         return true; 191     } 192  193  194     // ------------------------------------------------------------------------ 195     // Returns the amount of tokens approved by the owner that can be 196     // transferred to the spender's account 197     // ------------------------------------------------------------------------ 198     function allowance(address tokenOwner, address spender) public view virtual override returns (uint remaining) { 199         return allowed[tokenOwner][spender]; 200     } 201  202  203     // ------------------------------------------------------------------------ 204     // Token owner can approve for `spender` to transferFrom(...) `tokens` 205     // from the token owner's account. The `spender` contract function 206     // `receiveApproval(...)` is then executed 207     // ------------------------------------------------------------------------ 208     function approveAndCall(address spender, uint tokens, bytes memory data) public returns (bool success) { 209         allowed[msg.sender][spender] = tokens; 210         emit Approval(msg.sender, spender, tokens); 211         ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, address(this), data); 212         return true; 213     } 214  215  216     // ------------------------------------------------------------------------ 217     // Don't accept ETH 218     // ------------------------------------------------------------------------ 219     fallback () external { 220         revert("Not Accepting Ether"); 221     } 222  223  224     // ------------------------------------------------------------------------ 225     // Owner can transfer out any accidentally sent ERC20 tokens 226     // ------------------------------------------------------------------------ 227     function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) { 228         return ERC20Interface(tokenAddress).transfer(owner, tokens); 229     } 230 } 

See How to issue your own token on Ethereum in less than 20 minutes for steps to deploy a token contract.

Further Information On ERC20 network and platform for tokens

See Also on BitcoinWiki

Source

http://wikipedia.org/