大概会先把ERC20、ERC721、ERC1155、ERC165、EIP2612、EIP712、ERC511_SBT、ERC1820看一下。
ERC20
标准接口
// 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
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
// 转账事件
event Transfer(address indexed from, address indexed to, uint256 value);
// 授权事件
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev 返回总的发行数量.
*/
function totalSupply() external view returns (uint256);
/**
* @dev 查询账号余额
*/
function balanceOf(address account) external view returns (uint256);
/**
* 币的持有人直接调用,进行转账
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
*1. 我这个owner对合约进行approve,此时approve内部会修改allowance变量
* 2. 合约内部调用transferFrom来支配owner的token
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
/**
* spender: 是指定帮助花费的代理人(被授权的人)
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* 持有人对spender进行授权,在approve内部,会调用msg.sender来知道owner是谁
*/
function approve(address spender, uint256 amount) external returns (bool);
}
以上是OpenZeppelin ERC20的接口,下面是调用ERC20接口的案例。
案例:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "./IERC20.sol";
contract ERC20 is IERC20 {
// 定变量
// 代币总供给
uint256 public override totalSupply;
// 记录账户余额
mapping(address => uint256) public override balanceOf;
// 授权的额度
mapping(address => mapping(address => uint256)) public override allowance;
// 代币的名字
string public name = "WalnutTTTT ";
// 代币的简写
string public symbol = "Walnut";
// 小数位
uint8 public decimals = 18;
// 构造函数
constructor(string memory name_, string memory symbol_){
name = name_;
symbol = symbol_;
}
// @dev 实现`transfer`函数,代币转账逻辑
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;
}
// @dev 实现 `approve` 函数, 代币授权逻辑
function approve(address spender, uint amount) external override returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
// @dev 实现`transferFrom`函数,代币授权转账逻辑
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;
}
// @dev 铸造代币,从 `0` 地址转账给 调用者地址
function mint(uint amount) external {
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Transfer(address(0), msg.sender, amount);
}
// @dev 销毁代币,从 调用者地址 转账给 `0` 地址
function burn(uint amount) external {
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Transfer(msg.sender, address(0), amount);
}
}
资料:
https://dukedaily.github.io/solidity-expert/03_token%E5%8D%8F%E8%AE%AE/01_ERC20.html
文档信息
- 本文作者:WalnutTTTT
- 本文链接:https://walnutTTTT.com/2023/02/05/ERC20/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)