ERC721标准是在ERC20标准上建立的代币标准,是针对不可互换代币(non-fungible tokens 简称NFTs)做的智能合约标准。目前为止只是在草稿阶段(Draft),还未最终定稿。什么是不可互换资产呢,现在正火的加密猫(CryptoKitties)就是一个典型的应用,每只猫都有一个唯一的id。在这个场景下,不仅需要跟踪每个账户下的资产数量,而且需要跟踪每个资产id的转移。
与ERC20标准相同部分
与ERC20标准兼容部分不做详细介绍,想了解ERC20可以看ERC-20代币标准
function name() constant returns (string name);
function symbol() constant returns (string symbol);
function totalSupply() constant returns (uint256 totalSupply);
function balanceOf(address _owner) constant returns (uint256 balance);
与ERC20标准不同部分
方法
ownerOf
function ownerOf(uint256 _tokenId) constant returns (address owner)
- 本方法必须实现
- 返回代币id为
_tokenId
的拥有者账户owner
- 如果查询的
_tokenId
不存在,抛出throw
- 如果是已经销毁的NFS(不可互换代币),抛出
throw
,而不是返回0
approve
function approve(address _to, uint256 _tokenId)
- 本方法必须实现
- 批准id为
_tokenId
的NFS转移到新账户_to
下 - 如果
msg.sender != ownerOf(_tokenId)
,抛出throw
- 如果
_tokenId
不存在,抛出throw
- 如果
msg.sender != _to
,抛出throw
- 方法成功完成必须发出一个Approval事件
- 状态变更与事件对应表
动作 | 前状态 | _to 地址 | 新状态 | 事件 |
---|---|---|---|---|
清除未设置 | 清除 | 0 | 清除 | 无 |
设置 | 清除 | X | 设置为X | Approval(owner,X,tokenID) |
更改 | X | Y | 设置为Y | Approval(owner,Y,tokenID) |
重复设置 | X | X | 设置为X | Approval(owner,X,tokenID) |
清除 | X | 0 | 清除 | Approval(owner,0,tokenID) |
takeOwnership
function takeOwnership(uint256 _tokenId)
- 本方法必须实现
- 取得所有权
- 将id为
_tokenId
的NFT的所有权分配给msg.sender - 只有在msg.sender已获取批准的情况下才能成功执行
- msg.sender未获得
_tokenId
的批准,抛出throw
- 如果
_tokenId
不存在,抛出throw
- msg.sender 已经拥有
_tokenId
,抛出throw
- 成功转移必须触发Transfer事件
tokenOfOwnerByIndex
function tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId)
- 可选的(OPTIONAL)
- 建议实现此方法以提高钱包和交易所的使用体验,但是接口或者其它合约不应依赖于此方法的存在。
- 返回账户
_owner
的第n个NFT,n由_index
参数指定 - 如果
_index >= balanceOf(_owner)
,抛出throw
- 示例代码
uint256 ownerBalance = nonFungibleContract.balanceOf(owner);
uint256[] memory ownerTokens = new uint256[](ownerBalance);
for (uint256 i = 0; i < ownerBalance; i++) {
ownerTokens[i] = nonFungibleContract.tokenOfOwnerByIndex(owner, i);
}
NFT 元数据
tokenMetadata
function tokenMetadata(uint256 _tokenId) constant returns (string infoUrl)
- 可选的(OPTIONAL)
- 建议实现此方法以提高钱包和交易所的使用体验,但是接口或者其它合约不应依赖于此方法的存在。
- 返回一个引用外部资源包的多地址字符串
- 该外部资源包包含与NFT关联的元数据
- 多地址字符串必须是一个IPFS或HTTP的路径,包含多个子路径
标准子路径:
- name(必需):包含NFT的名称(UTF-8编码),每个NFT都有唯一的name。不超过50个字符,可以包含空白,但不能包含换行。name可能是一个带数字的名称,以区分一组中的其它NFT。例如:"Happy Token #157"
- image(可选):包含一个PNG,JPEG或SVG图像,每个维度至少有300个像素。图像宽高比应该在16:9(风景模式)和2:3(人像模式)之间。图像应该用一个“安全区域”来构建,这样将图像裁剪到一个最大的中心方块不会消除任何关键信息。(要达到这个要求,最简单的方法就是使用1:1的图像宽高比。
- description(可选):包含NFT的UTF-8编码文本描述。描述可以包含多行,使用一个换行符来分隔行,两个换行符来分隔段落。描述可以使用Markdown格式。不超过1500个字符。
- other metadata(可选):可以选择包括任意数量的其它子路径。
事件
Transfer
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId)
- 必须实现
- 当NFT所有权通过任何机制转移时,必须触发此事件。
- 创建新NFT时必须为每个新创建的NFT触发Transfer事件,
_from
地址为0,_to
地址匹配新NFT(可能是智能合约本身)的所有者。 - 删除(或消耗)NFT时必须触发Transfer事件,_to地址为0 ,_from是NFT删除前的所有者。
- Transfer事件
_from == _to
是有效的。
Approval
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId)
- 必须实现
- 所有成功调用
approve(address _spender, uint256 _value)
方法,都必须触发此事件
标准创建日期:2017-09-20
参考文档 https://github.com/ethereum/EIPs/issues/721