• 以太坊代币标准ERC20、ERC165、ERC721


    两个概念

    • ERC(Ethereum Request for Comment) 以太坊意见征集稿
    • EIP(Ethereum Improvement Proposals)以太坊改进提案

    ERC和EIP用于使得以太坊更加完善;在ERC中提出了很多标准,用的最多的标准就是它的Token标准;
    有哪些标准详细见https://eips.ethereum.org/erc

    常见ERC标准

    ERC-20Token Standard
    ERC-721Non-Fungible Token Standard
    ERC-165Standard Interface Detection
    ERC-777Token Standard
    ERC-1155Multi Token Standard

    ERC-20

    主要是指同质化代币标准(不同人持有的一个代币是等值的)。
    ERC-20标准中主要有6个函数和两个事件
    在这里插入图片描述
    其中这6个函数表达的意义是:
    totalSupply:总发行量
    balanceOf:账户余额
    transfer:转账
    transferFrom:针对授权进行转账
    approve:授权
    allowance:owner授权给spender余额
    具体的详细见https://eips.ethereum.org/EIPS/eip-20

    实现ERC20标准代币

    想要发现ERC20标准的代币,就需要实现ERC20标准接口中的函数

    先写ERC20标准接口

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    interface IERC20 {
        function name() external  view returns (string memory);
        function symbol() external view returns (string memory);
        function decimals() external view returns (uint8);
        function totalSupply() external view returns (uint256);
        function balanceOf(address _owner) external view returns (uint256 balance);
        function transfer(address _to, uint256 _value) external returns (bool success);
        function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
        function approve(address _spender, uint256 _value) external returns (bool success);
        function allowance(address _owner, address _spender) external view returns (uint256 remaining);
        
    	//_from和_to两个参数有indexed关键字修饰,表示这些参数可以作为过滤条件来搜索事件。
        event Transfer(address indexed _from, address indexed _to, uint256 _value);
        event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    再实现ERC20标准代币

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    import "./IERC20.sol";
    
    contract ERC20 is IERC20{
    
        string ercName;
        string ercSymbol;
        uint8 ercDecimals;
        uint256 ercTotalSupply;
        mapping(address=>uint256) ercBalances;
        //一个人可以有多个委托人:授权者=>被授权者=>授权金额
        mapping (address=>mapping (address=>uint256)) ercAllowance;
    
        //合约部署者
        address public owner;
    
        constructor(string memory _name, string memory _symbol,uint8 _decimals){
            ercName=_name;
            ercSymbol=_symbol;
            ercDecimals=_decimals;
            owner=msg.sender;
        }
    
        //token名称
        function name() override  external  view returns (string memory){
            return ercName;
        }
    
        //token符号
        function symbol() override external view returns (string memory){
            return ercSymbol;
        }
    
        //token可以拆分到的精度
        function decimals() override external view returns (uint8){
            return ercDecimals;
        }
    
        //token发行总量
        function totalSupply() override external view returns (uint256){
            return ercTotalSupply;
        }
    
        //账户余额
        function balanceOf(address _owner) override external view returns (uint256 balance){
            return ercBalances[_owner];
        }
    
        //给某人转账
        function transfer(address _to, uint256 _value) override external returns (bool success){
            require(_value>0,"_value must >0");
            require(_to!=address(0),"_to is null");
            require(ercBalances[msg.sender]>=_value,"user's balance not enough");
            ercBalances[msg.sender]-=_value;
            ercBalances[_to]+=_value;
         
            emit Transfer(msg.sender, _to, _value);
    
            return true;
        }
    
        //被授权用户用我的token转账;_from: 授权者,_to:转给谁
        function transferFrom(address _from, address _to, uint256 _value) override external returns (bool success){
            require(ercBalances[_from] >= _value,"user's balance not enough");
            require(ercAllowance[_from][msg.sender]>=_value,"approve's balance not enough");
            require(_value>0,"_value must > 0");
            require(_to!=address(0),"_to is null");
            ercBalances[_from]-=_value;
            ercBalances[_to]+=_value;
            ercAllowance[_from][msg.sender]-=_value;
            
            emit Transfer(_from, _to, _value);
            return true;
        }
    
        //授权其他用户可以花费我多少token
        function approve(address _spender, uint256 _value) override external returns (bool success){
            // require(_value>0,"value must >0");//让_value可以等于0,当其为0时表示收回授权
            require(_spender!=address(0),"_spender can not be null");
            require(ercBalances[msg.sender]>=_value,"user's balance not enough");
            ercAllowance[msg.sender][_spender]=_value; 
    
            emit Approval(msg.sender, _spender, _value);
            
            return true;
    
        }
    
        //获取授花费的余额token
        function allowance(address _owner, address _spender) override external view returns (uint256 remaining){
            return ercAllowance[_owner][_spender];
        }
    
        //代币发行机制
        function mint(address _to,uint256 _value) public{
            require(msg.sender==owner,"only owner can mint");
            require(_value>0,"_value must > 0");
            require(_to!=address(0),"_to is invalid"); 
            ercBalances[_to]+=_value;
            ercTotalSupply+=_value;
            emit Transfer(address(0), _to, _value);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105

    ERC165

    是一个标准接口检测的标准;用于检测合约是否符合规范

    注意:函数选择器:
    函数参数只保留类型,计算 hash("函数名(类型1, 类型2, ...)"),并取哈希结果的前4个字节
    举例,如下函数的函数选择器是:计算hash(“Transfer(address,uint256)”),并取哈希结果的前4个字节

    function Transfer(address to,uint256 value){
    	//函数体
    }
    
    • 1
    • 2
    • 3

    注意:接口ID:
    将一个接口里面的所有函数选择器做异或处理,得到接口的ID

    如何判断一个接口支持了ERC165?

    ERC-721

    主要是指非同质化代币标准(不同人持有的一个代币的价值不一样,如,艺术品)

  • 相关阅读:
    学习CANopen --- [10] 汽车外接OBD模块原理
    读书笔记: 这就是搜索引擎
    Node+Vue3+mysql+ant design实现前后端分离——表格的添加、修改和删除
    C. Minimum Varied Number
    GIT教程
    redis高可用、redis集群、redis缓存优化
    通俗易懂了解什么是docker以及docker的各种安装环境
    SCT82A30 6V-100V宽输入电压范围同步降压控制器,P2P替代LM5145
    现代检测技术课程实验编程:最小二乘法应用编程
    淘宝/Tmall商品详情页视频数据接口(视频数据,销量数据,sku属性数据,页面上有的数据均可以拿到,支持高并发)
  • 原文地址:https://blog.csdn.net/qxjswl/article/details/130372624