ERC721协议详解 –Solidity

25次阅读

共计 6224 个字符,预计需要花费 16 分钟才能阅读完成。

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 可操作的权限:

正文完
 0