第1节:ERC20(标准Token)
- EIP: Ethereum Improvement Propose
- 任何遵从EIP-20协议(ERC20标准)的Contract都属于ERC20 Token
标准接口
// 6 REQUIRED FUNCTIONS
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
// 2 REQUIRED EVENTS
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
// 3. OPTIONAL FUNCTIONS
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
分析
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
interface IERC20 {
// 6 REQUIRED FUNCTIONS
// 总发行量
function totalSupply() external view returns (uint); // -> 总发行量 100000000 * 10**decimals
// 标准decimal: 18
// USDT: 6
// WBTC: 8
function balanceOf(address account) external view returns (uint); // 指定账户的余额
// 币的持有人直接调用,进行转账
function transfer(address recipient, uint amount) external returns (bool);
// 最常用的!!
// 1. 我这个owner对合约进行approve,此时approve内部会修改allowance变量
// 2. 合约内部调用transferFrom来支配owner的token
function transferFrom( // spender就是这个合约
address sender, // owner
address recipient, // 转给谁
uint amount // 金额
) external returns (bool);
// owner: 币的持有人
// spender: 是指定帮助花费的代理人(被授权的人)
function allowance(address owner, address spender) external view returns (uint); // 授权的额度
// decimals view,这是一个public 的变量,自动提供了一个读取的方法 // 返回精度
// 持有人对spender进行授权,在approve内部,会调用msg.sender来知道owner是谁
function approve(address spender, uint amount) external returns (bool);
// 2 REQUIRED EVENTS
// 事件
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
// 3. OPTIONAL FUNCTIONS
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
}
以下是ERC20的案例:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "./IERC20.sol";
contract ERC20 is IERC20 {
uint public totalSupply;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
string public name = "Solidity by Example";
string public symbol = "SOLBYEX";
uint8 public decimals = 18;
function transfer(address recipient, uint amount) external returns (bool) {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint amount) external returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool) {
allowance[sender][msg.sender] -= amount;
balanceOf[sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
function mint(uint amount) external {
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Transfer(address(0), msg.sender, amount);
}
function burn(uint amount) external {
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Transfer(msg.sender, address(0), amount);
}
}
可以使用openzeppelin库进行创建自己的token:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
// import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
// Mint 100 tokens to msg.sender
// Similar to how
// 1 dollar = 100 cents
// 1 token = 1 * (10 ** decimals)
_mint(msg.sender, 100 * 10**uint(decimals()));
}
// 默认是18,可以进行override
function decimals() public view override returns (uint8) {
return 6;
}
}