1. ERC20
ERC20(Ethereum Request for Comments 20)一种代币标准。EIP-20 中提出。它实现了代币转账的基本逻辑:
- 账户余额
- 转账
- 授权转账
- 代币总供给
- 代币信息(可选):名称,代号,小数位数
2. IERC20
IERC20是ERC20代币标准的接口合约,规定了ERC20代币需要实现的函数和事件。 之所以需要定义接口,是因为有了规范后,就存在所有的ERC20代币都通用的函数名称,输入参数,输出参数。 在接口函数中,只需要定义函数名称,输入参数,输出参数,并不关心函数内部如何实现。 由此,函数就分为内部和外部两个内容,一个重点是实现,另一个是对外接口,约定共同数据。 这就是为什么需要ERC20.sol和IERC20.sol两个文件实现一个合约。
OpenZepplin 为我们提供了相应的库,方便开发者导入即用。
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
interface IERC20 {
// *************************** 事件 ***************************
// 1. 转账事件
event Transfer(address indexed from, address indexed to, uint256 value);
// 2. 授权事件
event Approval(address indexed owner, address indexed spender, uint256 value);
// *************************** 函数 ***************************
// 1. 查询发行总量
function totalSupply() external view returns (uint256);
// 2. 查询账户余额
function balanceOf(address account) external view returns (uint256);
// 3. 转账
function transfer(address to, uint256 value) external returns (bool);
// 4. 获取授权额度
function allowance(address owner, address spender) external view returns (uint256);
// 5. 授权
function approve(address spender, uint256 value) external returns (bool);
// 6. 授权转账
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
3. ERC20标准代币简单实现
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract ERC20Sample is IERC20 {
mapping (address account => uint256) public balanceOf;
mapping (address account => mapping (address spender => uint256)) public allowance;
// 总发行量
uint256 public totalSupply;
// 名称
string public name;
// 符号
string public symbol;
// 构造函数
constructor (string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
}
// 转账
function transfer(address to, uint256 value) external returns (bool) {
balanceOf[msg.sender] -= value;
balanceOf[to] += value;
emit Transfer(msg.sender, to, value);
return true;
}
// 授权
function approve(address spender, uint256 value) external returns (bool) {
allowance[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
// 授权转账
function transferFrom(address from, address to, uint256 value) external returns (bool) {
allowance[from][msg.sender] -= value;
balanceOf[from] -= value;
balanceOf[to] += value;
emit Transfer(from, to, value);
return true;
}
// mint函数:发行代币,示例代码,直接mint到msg.sender
function mint(uint256 value) external {
balanceOf[msg.sender] += value;
totalSupply += value;
emit Transfer(address(0), msg.sender, value);
}
// burn函数:销毁代币,示例代码,直接从msg.sender中销毁
function burn(uint256 value) external {
balanceOf[msg.sender] -= value;
totalSupply -= value;
emit Transfer(msg.sender, address(0), value);
}
}