ERC20代币标准源码解析
ERC是Ethereum Request for Comments的首字母缩写。它就像技术文档,定义了适用于一群想要利用以太坊生态系统的开发者和用户的方法、行为、创新和研究。ERC-20介绍了在以太坊区块链上创建可互换代币的代币标准,在该协议下的相同的代币完全一致。
/ SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
interface IERC20 {
// 定义Transfer事件,在发生交易转移时触发。Solidity event在 EVM 的日志记录功能之上提供了一个抽象。应用程序可以通过以太坊客户端的 RPC 接口订阅和监听这些事件
event Transfer(address indexed from, address indexed to, uint256 value);
// 定义Approval事件,在发生代币授权时触发该事件
event Approval(address indexed owner, address indexed spender, uint256 value);
// 获取当前代币的总供应量
function totalSupply() external view returns (uint256);
// 获取当前账户的代币余额
function balanceOf(address account) external view returns (uint256);
// 代币转移函数,将amount数量的代币转移到to地址
function transfer(address to, uint256 amount) external returns (bool);
//获取owner地址账号授权(approve方法进行授权)给spender地址的代币数量
function allowance(address owner, address spender) external view returns (uint256);
// 授权给spender地址 amount数量的代币,spender账户可以转移该数量代币通过调用
function approve(address spender, uint256 amount) external returns (bool);
// 从from地址转移amounts数量到to地址
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
// 合约继承IERC20、Context、IERC20Metadata
contract ERC20 is Context, IERC20, IERC20Metadata {
// _balances用于存储地址与其对应的代币余额
mapping(address => uint256) private _balances;
// _allowances用于保存from地址 授权给 to地址的代币数量
mapping(address => mapping(address => uint256)) private _allowances;
// 代币总供应量
uint256 private _totalSupply;
// 代币名称
string private _name;
// 代币标志
string private _symbol;
// 构造函数 初始化 name symbol
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
// 获取代币名称
function name() public view virtual override returns (string memory) {
return _name;
}
// 获取代币标志
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
// 获取小数点位数
function decimals() public view virtual override returns (uint8) {
return 18;
}
//获取代币总供应量
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
// 获取account地址的代币余额
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
// 转移amount数量的代币到to地址
function transfer(address to, uint256 amount) public virtual override returns (bool) {
// 获取函数调用者owner账户地址
address owner = _msgSender();
// 从owner地址转移amount代币到to地址
_transfer(owner, to, amount);
return true;
}
// 获取owner对spender的授权的代币数量
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
// 给spender地址授权amount数量代币
function approve(address spender, uint256 amount) public virtual override returns (bool) {
// 获取当前调用合约的账户地址
address owner = _msgSender();
// 将owner地址的amount数量代币授权给spender
_approve(owner, spender, amount);
return true;
}
// 从from地址转移amount代币到to地址
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
// 获取当前合约调用者的地址
address spender = _msgSender();
// 将from地址授权给spender地址的代币数量减少amount
_spendAllowance(from, spender, amount);
// 从from地址转移amount数量代币到to地址
_transfer(from, to, amount);
return true;
}
// 增加授权给spender的代币数量addedValue
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
// 获取当前调用合约的账号地址
address owner = _msgSender();
// 重新授权增加过后的代币数量从owner地址给spender地址
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
// 减少授权给spender的代币数量subtractedValue
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
// 获取当前调用合约的账号地址
address owner = _msgSender();
// 获取当前owner授权给spender代币数量
uint256 currentAllowance = allowance(owner, spender);
// 检查 当前以授权代币数量 currentAllowance 是否大于等于subtractedValue
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
// 重新授权减少过后的代币数量从owner地址给spender地址
// unchecked 关闭默认的溢出检查check,可以较少gas费
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
// 转移amount数量代币从from地址到to地址
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
// 检查 from地址是否为空地址
require(from != address(0), "ERC20: transfer from the zero address");
// 检查 to地址不为空地址
require(to != address(0), "ERC20: transfer to the zero address");
// 转移前调用的函数
_beforeTokenTransfer(from, to, amount);
// 获取from账户余额
uint256 fromBalance = _balances[from];
//检查账户余额 fromBalance 是否大于 要转移的代币数量amount
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
// 增加from地址代币数量
_balances[from] = fromBalance - amount;
// 增加to地址代币数量
_balances[to] += amount;
}
// 触发Transfer事件 记录转移事件
emit Transfer(from, to, amount);
// 转移代币之后定义的函数
_afterTokenTransfer(from, to, amount);
}
// 铸造新代币 并将代币转移到account地址
function _mint(address account, uint256 amount) internal virtual {
// 检查 account 是否为空地址
require(account != address(0), "ERC20: mint to the zero address");
// 转移代币前定义的函数
_beforeTokenTransfer(address(0), account, amount);
// 增加总供应量
_totalSupply += amount;
unchecked {
// 增加account地址代币余额
_balances[account] += amount;
}
// 触发代币转移事件,记录代币转移信息
emit Transfer(address(0), account, amount);
// 转移代币之后定义的函数
_afterTokenTransfer(address(0), account, amount);
}
// 销毁account账户amount数量的代币
function _burn(address account, uint256 amount) internal virtual {
// 检查地址不为空
require(account != address(0), "ERC20: burn from the zero address");
// 转移代币前定义的函数
_beforeTokenTransfer(account, address(0), amount);
//获取地址代币余额
uint256 accountBalance = _balances[account];
//检查地址代币余额 是否大于等于 要销毁的数量
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
// 减少账户余额
_balances[account] = accountBalance - amount;
// 减少总供应量
_totalSupply -= amount;
}
// 触发代币转移事件,记录代币转移信息
emit Transfer(account, address(0), amount);
// 转移代币之后定义的函数
_afterTokenTransfer(account, address(0), amount);
}
// 将owner的代币授权给spender
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
// 检查地址不为空
require(owner != address(0), "ERC20: approve from the zero address");
// 检查地址不为空
require(spender != address(0), "ERC20: approve to the zero address");
// 授权amount数量代币
_allowances[owner][spender] = amount;
// 触发代币授权事件,记录代币授权信息
emit Approval(owner, spender, amount);
}
// 将授权的的代币数量减少amout,用在transfer函数内调用
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
// 获取当前授权代币数量
uint256 currentAllowance = allowance(owner, spender);
// 判断当前代币数量是否等于uint256代币最大值
if (currentAllowance != type(uint256).max) {
// 检查 授权代币余额是否大于减少的代币数量
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
// 减少代币授权数量
_approve(owner, spender, currentAllowance - amount);
}
}
}
// 在转移代币发生前的函数,包含mint 和 burn
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
// 在转移代币发生后的函数,包含mint 和 burn
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!