WTF Solidity 31. ERC20
Recently, I have been revisiting Solidity, consolidating the finer details, and writing "WTF Solidity" tutorials for newbies.
Twitter: @0xAA_Science | @WTFAcademy_
Community: Discord|Wechat|Website wtf.academy
Codes and tutorials are open source on GitHub: github.com/AmazingAng/WTFSolidity
In this lecture, we will introduce the ERC20 token standard on Ethereum and issue our own test tokens.
ERC20
ERC20 is a token standard on Ethereum, which originated from the EIP20
proposed by Vitalik Buterin in November 2015. It implements the basic logic of token transfer:
- Account balance
- Transfer
- Approve transfer
- Total token supply
- Token Information (optional): name, symbol, decimal
IERC20
IERC20
is the interface contract of the ERC20
token standard, which specifies the functions and events that ERC20
tokens need to implement. The reason for defining an interface is that with the standard, there are universal function names, input and output parameters for all ERC20
tokens. In the interface functions, only the function name, input parameters, and output parameters need to be defined, and it does not matter how the function is implemented internally. Therefore, the functions are divided into two contents: internal implementation and external interface, focusing on implementation and agreement of shared data between interfaces. This is why we need two files ERC20.sol
and IERC20.sol
to implement a contract.
Event
The IERC20
defines 2
events: the Transfer
event and the Approval
event, which are emitted during token transfers and approvals, respectively.
/**
* @dev Triggered when `value` tokens are transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Triggered whenever `value` tokens are approved by `owner` to be spent by `spender`.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
Functions
IERC20
defines 6
functions, providing basic functionalities for transferring tokens, and allowing tokens to be approved for use by other third parties on the chain.
totalSupply()
returns the total token supply.
/**
* @dev Returns the total amount of tokens.
*/
function totalSupply() external view returns (uint256);
balanceOf()
returns the account balance.
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
transfer()
means transfer of funds.
/**
* @dev Transfers `amount` tokens from the caller's account to the recipient `to`.
*
* Returns a boolean value indicating whether the operation succeeded or not.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
The allowance()
function returns the authorized amount.
/**
* @dev Returns the amount authorized by the `owner` account to the `spender` account, default is 0.
*
* When {approve} or {transferFrom} is invoked,`allowance` will be changed.
*/
function allowance(address owner, address spender) external view returns (uint256);
approve()
Authorization
/**
* @dev Allows `spender` to spend `amount` tokens from caller's account.
*
* Returns a boolean value indicating whether the operation succeeded or not.
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
transferFrom()
authorized transfer.
/**
* @dev Transfer `amount` of tokens from `from` account to `to` account, subject to the caller's
* allowance. The caller must have allowance for `from` account balance.
*
* Returns `true` if the operation is successful.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
Implementation of ERC20
Now we will write an ERC20
contract and implement the functions defined in the IERC20
interface.
State Variables
We need state variables to record account balances, allowances, and token information. Among them, balanceOf
, allowance
, and totalSupply
are of type public
, which will automatically generate a same-name getter
function, implementing balanceOf()
, allowance()
and totalSupply()
functions defined in IERC20
. name
, symbol
, and decimals
correspond to the name, symbol, and decimal places of tokens.
Note: adding override
modifier to public
variables will override the same-name getter
function inherited from the parent contract, such as balanceOf()
function in IERC20
.
mapping(address => uint256) public override balanceOf;
mapping(address => mapping(address => uint256)) public override allowance;
uint256 public override totalSupply; // total supply of the token
string public name; // the name of the token
string public symbol; // the symbol of the token
uint8 public decimals = 18; // decimal places of the token
Functions
- Constructor Function: Initializes the token name and symbol.
constructor(string memory name_, string memory symbol_){
name = name_;
symbol = symbol_;
}
transfer()
function: Implements thetransfer
function inIERC20
, which handles token transfers. The caller deductsamount
tokens and the recipient receives the corresponding tokens. Some coins will modify this function to include logic such as taxation, dividends, lottery, etc.
function transfer(address recipient, uint amount) external override returns (bool) {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
approve()
function: Implements theapprove
function inIERC20
, which handles token authorization logic. Thespender
specified in the function can spend the authorizedamount
of tokens from the authorizer. Thespender
can be an EOA account or a contract account, for example, when you trade tokens onUniswap
, you need to authorize tokens to theUniswap
contract.
function approve(address spender, uint amount) external override returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
transferFrom()
function: Implements thetransferFrom
function inIERC20
, which is the logic for authorized transfer. The authorized party transfersamount
of tokens fromsender
torecipient
.
function transferFrom(
address sender,
address recipient,
uint amount
) external override returns (bool) {
allowance[sender][msg.sender] -= amount;
balanceOf[sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
mint()
function: Token minting function, not included in theIERC20
standard. For the sake of the tutorial, anyone can mint any amount of tokens. In actual applications, permission management will be added, and only theowner
can mint tokens.
function mint(uint amount) external {
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Transfer(address(0), msg.sender, amount);
}
burn()
function: Function to destroy tokens, not included in theIERC20
standard.
function burn(uint amount) external {
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Transfer(msg.sender, address(0), amount);
}
Issuing ERC20 Tokens
With the ERC20
standard in place, it is very easy to issue tokens on the ETH
chain. Now, let's issue our first token.
Compile the ERC20
contract in Remix
, enter the constructor's parameters in the deployment section, set name_
and symbol_
to WTF
, and then click the transact
button to deploy.
Now, we have created the WTF
token. We need to run the mint()
function to mint some tokens for ourselves. Open up the ERC20
contract in the Deployed Contract
section, enter 100
in the mint
function area, and click the mint
button to mint 100
WTF
tokens for ourselves.
You can click on the Debug button on the right to view the logs like below.
There are four key pieces of information:
- The
Transfer
event - The minting address
0x0000000000000000000000000000000000000000
- The receiving address
0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
- The token amount
100
We use the balanceOf()
function to check the account balance. By inputting our current account, we can see the balance of our account is 100
which means minting is successful.
The account information is shown on the left like below image, and the details of the function execution are indicated on the right side.
Summary
In this lesson, we learned about the ERC20
standard and its implementation on the Ethereum network, and issued our own test token. The ERC20
token standard proposed at the end of 2015 greatly lowered the threshold for issuing tokens on the Ethereum network and ushered in the era of ICO
. When investing, carefully read the project's token contract to effectively avoid risks and increase investment success rate.