ERC20(一):代币标准、接口和简单实现

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 {
    /**
    * @dev _balance变量,用于记录地址余额:address => uint256 
    */
    mapping (address account => uint256) public balanceOf;

    /**
    * @dev _allowances变量,用于记录地址余额:address => (address => uint256 )
    */
    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);
    }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容