一、EIP
全称Ethereum Improvement Proposal,Ethereum改进提案,是对以太坊网络的功能、协议或规范进行改进的提案文档。
EIP可以在Ethereum 生态中任意领域 提出改进意见,比如新特性、ERC、协议改进、编程工具等等。
二、ERC
全称Ethereum Request for Comments,以太坊请求评论,是对以太坊网络上的特定标准或协议进行规范化的提案文档。ERC通常涉及以太坊智能合约的标准和接口,以促进不同智能合约之间的互操作性。ERC可以被认为是以太坊的标准化提案。
1) 生命周期
-
ERC 和 EIP 都有4个阶段:
-
- Draft:草稿,处于讨论状态的提案。
-
- Accept:接受,可能在下一个块或分叉中生效。
-
- Final:定稿。已经生效的,比如ERC20,ERC721等。
-
- Deffered:延期,不会马上被接受,也许在将来被接受。
-
-
ERC 和 EIP 的关系
- 所有的ERC都是EIP。
三、ERC20
ERC20 标准只包括接口,并非指标准的代码,而是只要满足了ERC20的接口,你接口包含ERC20 所列出的所有的接口,就代表你满足了ERC20的标准。至于合约中的方法是如何实现的并不关心,合约逻辑如何实现没有强制要求。
ERC20: 同质化代币,意味着每个代币的价值和性质是相同的,可以互换。
Code
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.20;
interface IERC20 {
// token总量
function totalSupply() external view returns (uint); // 函数可见性声明:在 interface 中,不需要明确标注函数为 public,默认是 external。不过在实现合约中需要明确标注函数的可见性。
// 某一个账户当前余额
function balanceOf(address _owner) external view returns (uint balance);
// 转账
// params 将 _value数量的代币 转移到 地址_to
function transfer(address _to, uint _value) external returns (bool success);
// params 将 _value数量的代币 从 地址_from 转移到 地址_to
function transferFrom(address _from, address _to, uint _value) external returns (bool success);
// params 允许 _spender 提取 _value数量的代币
function approve(address _spender, uint _value) external returns (bool success);
//params 检查 _spender 消费 _owner 代币数量
// returns 返回代币数量
function allowance(address _owner, address _spender) external view returns (uint remaining);
// 事件
// _from: 代币的发送者地址
// _to: 代币的接收者地址
// _value: 转移的代币数量
event Transfer(address indexed _from, address indexed _to, uint _value);
// _owner: 代币的所有者
// _spender: 被授权消费代币的账户地址
// _value:授权给_spender的代币数量
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
contract ERC20 is IERC20 {
uint private _totalSupply; // 当前合约的token总量
mapping(address => uint) private _balances; // 账本:地址 => 余额
mapping(address => mapping(address => uint)) private _allowances; // 映射批准信息 _owner => ( _spender => _value )
// 这里必须使用override来标明此函数是重写自IERC20接口的
function totalSupply() external view override returns (uint) {
return _totalSupply;
}
function balanceOf(address _owner) external view override returns (uint balance) {
return _balances[_owner];
}
function transfer(address _to, uint _value) external override returns (bool success) {
require(_balances[msg.sender] >= _value, "Insufficient balance"); // 检查余额
require(_to != address(0), "Invalid recipient address"); // 检查地址是否为0地址
_balances[msg.sender] -= _value;
_balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true; }
function transferFrom(address _from, address _to, uint _value) external override returns (bool success) {
require(_balances[_from] >= _value, "Insufficient balance"); // 检查 _from 的余额
require(_allowances[_from][msg.sender] >= _value, "Allowance exceeded"); // 检查授权额度
require(_to != address(0), "Invalid recipient address"); // 检查地址是否为0地址
_balances[_from] -= _value;
_balances[_to] += _value;
_allowances[_from][msg.sender] -= _value; // TODO 支持委托转账
emit Transfer(_from, _to, _value);
return true; }
function approve(address _spender, uint _value) external override returns (bool success) {
require(_spender != address(0), "Invalid spender address"); // 检查地址是否为0地址
_allowances[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true; }
function allowance(address _owner, address _spender) external view override returns (uint remaining) {
return _allowances[_owner][_spender];
}
}