【BlockChain】ERC-721标准和ERC-20标准

ERC-20

以太坊中的代币ETH是同质化代币(FT),一个ETH和另一个ETH两者是等价的这使得 ERC20 代币可用于交换投票权、质押等媒介。因此我们需要使用一种同质化代币ERC-20标准。ERC-20接口如下:

pragma solidity ^0.8.0;
 
interface IERC20 {
    
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
     
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}
  • totalSupply() :返回总共的Token数量。
  • balanceOf(address account) :返回 account 地址拥有的Token数量。
  • transfer(address to, uint256 amount) :将 amount 数量的Token发送给 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
  • allowance(address owner, address spender) :返回授权花费者 spender 通过 transferFrom 代表所有者花费的剩余Token数量。默认情况下为零。当 approvetransferFrom 被调用时,值将改变。
  • approve(address spender, uint256 amount) :授权 spender 可以花费 amount 数量的Token,返回布尔值告知是否执行成功。触发 Approval 事件。
  • transferFrom(address from, address to, uint256 amount) :将 amount 数量的Token从 from 地址发送到 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。

事件(定义中的 *indexed* 便于查找过滤):

  • Transfer(address from, address to, uint256 value) :当代币被一个地址转移到另一个地址时触发。注意:转移的值可能是 0 。
  • Approval(address owner, address spender, uint256 value) :当代币所有者授权别人使用代币时触发,即调用 approve 方法。

ERC-721

非同质化代币(NFT)用于以唯一的方式标识某人或者某物。与同质化代币(FT)不同,NFT具有独特、不可交换、不可分割的特性。**举个简单的例子,我的羽毛球拍和你的乒乓球拍之间存在差异,即不能直接进行简单的等价交换。而且我也无法给你0.5个羽毛球拍。**因此NFT需要一个适当的ERC-721标准。ERC-721接口如下:

pragma solidity ^0.4.20;

/// @title ERC-721 NFT标准
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// 	 继承自ERC-165标准
interface ERC721 is ERC165 {
    
    
 
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    function balanceOf(address _owner) external view returns (uint256);
    function ownerOf(uint256 _tokenId) external view returns (address);
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function approve(address _approved, uint256 _tokenId) external payable;
    function setApprovalForAll(address _operator, bool _approved) external;
    function getApproved(uint256 _tokenId) external view returns (address);
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

其中:

  • balanceOf(): 返回_owner持有的NFTs的数量。
  • ownerOf(): 返回_tokenId代币持有者的地址。
  • approve(): 授予地址to具有tokenId的控制权,方法成功后需触发Approval事件。
  • setApprovalForAll(): 授予地址_operator具有所有NFTs的控制权,成功后需触发ApprovalForAll事件。
  • getApproved()、isApprovedForAll(): 用来查询授权。
  • safeTransferFrom(): 转移NFT所有权,一次成功的转移操作必须发起 Transer 事件。**在转账时需要做安全检查,防止因授权地址无效或错误转账导致用户的损失。**函数的实现需要做一下几种检查:
  1. 调用者msg.sender应该是当前tokenId的所有者或被授权的地址

  2. _from 必须是 _tokenId的所有者

  3. _tokenId 应该是当前合约正在监测的NFTs 中的任何一个

  4. _to 地址不应该为 0

  5. 如果_to 是一个合约应该调用其onERC721Received方法, 并且检查其返回值,如果返回值不为bytes4(keccak256("onERC721Received(address,uint256,bytes)"))抛出异常。

    一个可接收NFT的合约必须实现ERC721TokenReceiver接口:

    interface ERC721TokenReceiver {
    
    
        /// @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
        function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
    }
  • transferFrom(): 用来转移NFTs, 方法成功后需触发Transfer事件。调用者自己确认_to地址能正常接收NFT,否则将丢失此NFT。此函数实现时需要检查上面条件的前4条。

ERC-165

ERC721标准同时要求必须符合ERC165标准 ,其接口如下:

interface ERC165 {
    
    
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

ERC165同样是一个合约标准,这个标准要求合约提供其实现了哪些接口,这样再与合约进行交互的时候可以先调用此接口进行查询。
interfaceID为函数选择器,计算方式有两种,如:bytes4(keccak256('supportsInterface(bytes4)'));ERC165.supportsInterface.selector,多个函数的接口ID为函数选择器的异或值。

总结

ERC-20标准和ERC-721标准的最大区别在于Token之间是否可以进行直接、简单的互换以及分割。

猜你喜欢

转载自blog.csdn.net/Keikei419/article/details/127659624