ERC721协议详解 --Solidity

pragma solidity ^0.4.20;

/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.

    interface ERC721 /* is ERC165 */ {

//变更NFT所有权
//NFT的创建和销毁时触发
//除外情况:创建合约时,不需要transfer也可以创建和分配NFT
//发起transfer时,approved address会被重置为none

        event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

//在NFT的approved address变更或重新确认时被触发。
//zero address代表没有approved address。
//当i一个transfer事件发生时,approved address会被重置为none。

        event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

//operator被授权或撤权时触发。
//operator可以管理owner 的所有NFT。

        event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

//计数owner名下的所有NFT。
//分配NFT给zero address 是无效的。同时,query zero address 的时候,函数抛出异常。
//参数是发起查询的人。
//返回NFT数量,可能是0。

        function balanceOf(address _owner) external view returns (uint256);

//获取NFT所有者。
//分配NFT给zero address 是无效的。同时,query zero address 的时候,函数抛出异常。
// 参数 _tokenId 是NFT的标识符identifier。
//返回owner地址。

        function ownerOf(uint256 _tokenId) external view returns (address);

//将NFT的所有权从一个地址转移到另一个地址。
//抛出异常的情况包括:
// _from 不是当前所有者,
// _to 是zero address,
//_tokenId 不是有效NFT,
//当转移完成,函数会校验_to 是不是一个合约。
//如果是,就会使用_to 来调用onERC721Received 方法,
//并且这个方法,在返回值不是 bytes4(keccak256(“onERC721Received(address,address,uint256,bytes)”)) 时抛出异常。
// _from 是NFT当前所有者,
// _to 是新所有者,
// _tokenId 是要被转移的NFT ,
// data是没有特定格式的数据,用来sent in call to _to

        function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;

//如上,只是将data参数置空,“”。

        function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;

//转移NFT所有权。
//调用方有责任检查 _to 是否能够有效接收NFT,如果无作为可能会导致永久丢失。
//抛出异常:当msg.sender不是当前owner,不是approved address,不是authorized operator。
//三个参数任一无效,则抛出异常。

        function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

//为NFT设置或重新确认approved address。
//zero address代表没有approved address。
//抛出异常:当msg.sender不是当前owner,不是approved address,不是authorized operator。
//_approved 将被设为owner的角色。
//_tokenId 当前被操作的币。

        function approve(address _approved, uint256 _tokenId) external payable;

//授权或撤销权利,对第三方operator,对msg.sender所有资产的操作的权利。
//触发ApprovalForAll事件。
//合约必须允许每个owner有多个operator。
//参数 _operator 添加到authorized operators里面。
//参数bool值,true表示允许,false表示撤销。

        function setApprovalForAll(address _operator, bool _approved) external;

//获取单个NFT的approved address。
//抛出异常:_tokenId无效时。
//_tokenId指代哪个币。
//返回approved address

        function getApproved(uint256 _tokenId) external view returns (address);

//查询address是否是另一个address的authorized operator 。
//interfaceID是接口标识符,(ERC-165中规定的)。
//ERC-165中规定了,对接口的鉴别。
//返回值为true,代表合约实现了interfaceID这个接口。并且interfaceID 不是 0xffffffff。
//false代表没实现。

        function isApprovedForAll(address _owner, address _operator) external view returns (bool);
    }

================================================================================================

    interface ERC165 {

//查询一个合约是否实现了这个接口。

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

================================================================================================
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.

    interface ERC721TokenReceiver {

//处理NFT的收据。
//ERC721合约在transfer执行后,对接收者recipient调用这个方法。
//如果传值不对,函数会抛出异常以回复或拒绝这个transfer。而这将导致整个交易被拒绝。
//合约地址总是message sender。
// _operator, 调用函数safeTransferFrom的地址。
//_from,之前的token拥有者。
//_tokenId,被转移的NFT。
//data,无规定格式的additional数据。
//返回bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")),不然就抛出异常。

        function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
     }

================================================================================================
//metadata extension是erc721合约的可选项。它允许其他人对智能合约发出有关NFT所代表资产的name和details。
/// Note: the ERC-165 identifier for this interface is 0x5b5e139f.
interface ERC721Metadata / is ERC721 / {
//对NFT的描述性名称。

function name() external view returns (string _name);

//合约中NFT的简短名称。

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

//对指定资产的唯一URI。
//抛出异常:tokenId不正确时,
//URI可能指向(符合元数据JSON模型的)JSON file。。

function tokenURI(uint256 _tokenId) external view returns (string);

}

//这是上面提到的”ERC721 Metadata JSON Schema”。
{

"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.",
    }
}

}

//enumeration extension是erc721合约的可选项。它能使合约提供完整列表和和可发现。
/// Note: the ERC-165 identifier for this interface is 0x780e9d63.
interface ERC721Enumerable / is ERC721 / {
//计数合约追踪的NFT。
//合约追踪的有效NFT,每个NFT都是已分配和可查询的地址(不能是zero address)

function totalSupply() external view returns (uint256);

//枚举有效NFT。
//抛出异常: _index >= totalSupply()时。
//(不指定排列顺序。)

function tokenByIndex(uint256 _index) external view returns (uint256);

//计算属于某个owner的NFT数量。
//抛出异常:_index >= balanceOf(_owner) 或zero address。

function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);

}

//关于NFT标识符 NFT Identifiers。
//每个NFT在合约内都有唯一的ID。这个号码不会变更。这个mapping会全局唯一并呵护规范。
//有些合约会从ID 0 开始自增1。
//调用者不应假设ID号有任何特殊含义,应建议将ID视为“black box”一般。

//NFT可能会出现失效情况(被销毁)。

//元数据选择(元数据扩展)
//在metadata extension里面需要有name和symbol函数。
//上述两个函数返回值为空也可以。 //合约可以使用相同的名字和标识。
//提示:其他人合约名称可能相同。
//NFT和URI相关联。
//我们希望每个实现都可以受益于此,并给每个NFT都提供metadata。
//URI可能是可变的。
//元数据是以string返回的。当前只在web3调用有效。但前还行,因为暂时链上应用没有特定需求去发出这样的请求。

//可以有的其他考虑:1,把每个资产的元数据都放在链上(过于昂贵)2使用url模版请求元数据(url模版并不适用于所有的url模式)3,多地址网络地址(还不成熟)。

//erc721指向total supply的两个函数:addTokenTo()和 _mint().
//在完全实现的合约里面,调用addTokenTo(),之后super.addTokenTo()允许我们调用addTokenTo()函数。
//在这两个函数之后,就可以更新全局的ownership变量了。

The functions take in two parameters _to or the address to which the token will be owned and _tokenId or the unique id of the token — chosen by whomever you allow to call this function, you’d likely limit this call to the owner of the contract. In this case, the user can choose any unique number id. First, in the ERC721BasicToken contract, we check that the token id is not already owned. Then we set the token owner of the requested token id, and add one to the number of owned tokens of that individual account. Going back to the full implementation contract, we also update the array of the new owner’s (_to)tokens by adding this new token to the end of their ownedTokens array and saving the index of that new token.

luckycoin可能用到的erc721接口
1,生成NFT /发放:

2,查询NFT:

3,交易NFT,使用NFT参与游戏时发起转账,或给其他地址转NFT:(下面两个函数二选一使用都可以)

以下函数同上一摸一样,除了可以加一个类似于备注的data(上面这个函数等同于data置空。)

4,设置合约对单个NFT的操作权限:to是合约。

5设置对某address名下的所有NFT可操作的权限:

    原文作者:kakushao
    原文地址: https://segmentfault.com/a/1190000017440787
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞