0xAA

发布于 2022-04-24到 Mirror 阅读

Solidity极简入门 ERC721专题:2. ERC721相关接口

我最近在重新学solidity,巩固一下细节,也写一个“Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。

欢迎关注我的推特:@0xAA_Science

WTF技术社群discord,内有加微信群方法:链接

所有代码和教程开源在github(1024个star发课程认证,2048个star发社群NFT): github.com/AmazingAng/WTFSolidity

不知不觉我已经完成了Solidity极简教程的前13讲(基础),内容包括:Helloworld.sol,变量类型,存储位置,函数,控制流,构造函数,修饰器,事件,继承,抽象合约,接口,库,异常。在进阶内容之前,我决定做一个ERC721的专题,把之前的内容综合运用,帮助大家更好的复习基础知识,并且更深刻的理解ERC721合约。希望在学习完这个专题之后,每个人都能发行自己的NFT


ERC721相关接口

ERC721的主合约一共引用了4个接口合约:IERC721.sol, IERC721Receiver.sol, IERC721Metadata.sol,和间接引用的ERC165IERC165.sol。这一讲我们将逐个介绍这4个接口合约。

IERC165接口

首先我们介绍一下EIP165以太坊改进建议第165条),他的目的是创建一个标准方法来发布和检测智能合约实现的接口。讲一个去年年底发生的真实事件,PeopleDAO有个朋友错转了4000w枚PEOPLE到代币合约。但合约没有实现转出代币的功能,只能进不能出,这些代币直接锁死在里面销毁了。试想一下,如果在转账的时候自动判断接收方合约是否实现了相应的接口,没实现的话就revert交易,很多错转代币的悲剧都不会发生。EIP165就是干这个的,而ERC165就是EIP165的实现。

IERC165ERC165的接口合约,只有一个函数supportsInterface(),输入想查询的接口的interfaceId,返回一个bool告诉你合约是否实现了该接口。

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

ERC721主合约对supportsInterface()的实现如下:

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

可以看到,ERC721实现了IERC721IERC721MetadataIERC165的接口,查询的时候会返回true;否则返回false。我会在进阶内容中更详细的介绍function selectorinterfaceId

IERC721

IERC721ERC721的接口合约,里面包括3个event和9个function

interface IERC721 is IERC165 {
    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 balance);

    function ownerOf(uint256 tokenId) external view returns (address owner);

    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    function transferFrom(address from, address to, uint256 tokenId) external;

    function approve(address to, uint256 tokenId) external;

    function getApproved(uint256 tokenId) external view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) external;

    function isApprovedForAll(address owner, address operator) external view returns (bool);

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

其中event包括:

  1. Transfer事件:在转账时被释放,记录代币的发出地址from,接收地址totokenid
  2. Approval事件:在授权时释放,记录approve的发出地址owner,被授权地址approvedtokenid
  3. ApprovalForAll事件:在批量授权时释放,记录approve的发出地址owner,被授权地址operator和是否被授权approved

其中function包括:

  1. balanceOf:参数为要查询的地address,返回该地址的NFT持有量balance
  2. ownerOf:参数为要查询的tokenId,返回这个tokenId的主人owner
  3. safeTransferFrom:安全转账(如果接收方是合约地址,会要求实现ERC721的接收接口)。参数为转出地址from,接收地址totokenId
  4. transferFrom:普通转账(不检查对方是否实现ERC721的接收接口),参数为转出地址from,接收地址totokenId
  5. approve:授权,批准另一个地址使用你的NFT。参数为被授权地址approvetokenId
  6. getApproved:查询NFT被批准给了哪个地址,参数为tokenId,返回被批准的地址approve
  7. setApprovalForAll:将自己持有的这类NFT批量授权给某个地址,参数为被授权的地址operator和是否授权approved
  8. isApprovedForAll:查询某人的NFT是否批量授权给了某个地址,参数为授权方owner和被授权地址operator,返回bool
  9. safeTransferFrom:安全转账,与3.不同的地方在于参数里面包含了data,可以做额外处理。

IERC721Receiver

interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

IERC721Receiver接口包含了一个函数onERC721Received()。这个函数会在safeTransferFrom()中被调用,代币的接收合约必须实现这个接口才能转账成功。

IERC721Metadata

interface IERC721Metadata is IERC721 {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function tokenURI(uint256 tokenId) external view returns (string memory);
}

IERC721MetadataERC721的拓展接口,实现了3个查询metadata的常用函数:

  1. name():返回代币名称。
  2. symbol():返回代币代号
  3. tokenURI():通过tokenId查询metadata所在url

总结

本文是ERC721专题的第二讲,我们介绍了ERC721主合约调用的4个接口合约IERC165IERC721IERC721ReceiverIERC721Metadata。下一讲终于该介绍ERC721主合约了!LFG!

延伸阅读

EIP165中文提案