目录
🥕写在前面:本文属搬运博客,自己留存学习。
ERC721 作为一个合约标准,提供了在实现 ERC721 代币时必须要遵守的协议,要求每个 ERC721 标准合约需要实现「ERC721」及「ERC165」接口。ERC721 标准的合约一旦被部署,它将负责跟踪在以太坊上创建的代币。
ERC721 的接口定义如下。
- interface ERC721 {
- /// event
- /// function
- }
- 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);
接口说明:
也就是说,transferFrom( ) 满足调用 safeTransferFrom( ) 的条件的前四条即可。
调用 safeTransferFrom( ) 的条件:
一个可接收 NFT 的合约必须实现 ERC721TokenReceiver 接口:
- interface ERC721TokenReceiver {
- /// @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
- function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
- }
ERC165 的接口定义如下:
- interface ERC165 {
- function supportsInterface(bytes4 interfaceID) external view returns (bool);
- }
ERC165 同样是一个合约标准,这个标准要求合约提供其实现了哪些接口,这样在与合约进行交互的时候可以先调用此接口进行查询。
interfaceID 为函数选择器,计算方式有两种,如:bytes4(keccak256('supportsInterface(bytes4)')); 或 ERC165.supportsInterface.selector,多个函数的接口 ID 为函数选择器的异或值。
就是说可以通过 ERC165 查询 ERC721 实现了哪些接口?
ERC721Metadata 接口用于提供合约的元数据:name,symbol 以及 URI,其接口定义如下:
- interface ERC721Metadata {
- function name() external pure returns (string _name);
- function symbol() external pure returns (string _symbol);
- function tokenURI(uint256 _tokenId) external view returns (string);
- }
接口说明:
外部资源文件需要包含名字、描述、图片,其格式的要求如下:
- {
- "title": "Asset Metadata",
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "description": "Identifies the asset to which this NFT represents",
- },
- "description": {
- "type": "string",
- "description": "Describes the asset to which this NFT represents",
- },
- "image": {
- "type": "string",
- "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.",
- }
- }
- }
采用的是 JSON 格式。
ERC721Enumerable 的主要目的是提高合约中 NTF 的可访问性,其接口定义如下:
- interface ERC721Enumerable {
- function totalSupply() external view returns (uint256);
- function tokenByIndex(uint256 _index) external view returns (uint256);
- function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
- }
接口说明:
NFT 总量应该就是该 NFT 合约铸造的 NFT 代币的总量吧?
NTF 的 ID,即 tokenId,在合约中用唯一的 uint265 进行标识,每个 NFT 的 ID 在智能合约的生命周期内不允许改变。推荐的实现方式有:
ERC721 标准尽可能遵循 ERC-20 的语义,但由于同质代币与非同质代币之间的根本差异,并不能完全兼容 ERC-20 。
在实现 transter 相关接口时除了满足上面的的条件外,我们可以根据需要添加自己的逻辑,如加入黑名单等。同时挖矿、销毁尽管不是标准的一部分,我们可以根据需要实现。