ERC998
在开始之前,你可能需要了解一下区块链,比特币,以太坊,ERC20和ERC721的相关知识,因为整篇文章也是在此基础上的一个应用的开始。
ERC998目前状态Draft,创建于2018/7/7
具体信息可访问ERC998。
特性:可组合(composable)。ERC20和ERC721仅仅是单一的物品的应用,而ERC998可以组合不同的ERC721和ERC20,使之产生更丰富的应用。可以类比主机(ERC721) + 显示器(ERC20)+ 外设(ERC721)= 电脑(ERC998);通过这样的组合我们就能够创建出更加复杂,高级的功能。
ERC998的两种实现
ComposableTopDown和ComposableBottonUp,本次结合我实际的应用只讲介绍前者,具体的不同可以参考官网,当然这里有一篇作者更详细的介绍:
Top-Down and Bottom-Up Composables, What’s the Difference and Which One Should You Use?
ERC998接口分析
原作者已经写得非常详细了,具体就不在具体分析了。这里结合avatar(ERC998的实现的虚拟形象)和clothes(ERC721的实现的衣服)简单的看看ComposableTopDown的实现吧。(ComposableBottonUp的原理也类似)
interface ERC998ERC721TopDown
event ReceivedChild(address indexed _from, uint256 indexed _tokenId, address indexed _childContract, uint256 _childTokenId)
当avatar接收到一件clothes会触发的一个事件
_from : clothes的原始owner address
_tokenId : 哪一个avatar来穿这件衣服,即avatar id
_childContract: clothes contract address
_childTokenId: 哪一件衣服,即clothes id
event TransferChild(uint256 indexed tokenId, address indexed _to, address indexed _childContract, uint256 _childTokenId);
当avatar脱下一件clothes时会发出的一个事件
tokenId : 将要脱下clothes的avatar id
_to : 接收clothes address,在项目中
_childContract: clothes 合约地址
_childTokenId: clothes id
function rootOwnerOf(uint256 _tokenId) external view returns (bytes32 rootOwner);
rootOwner:获得clothes的owner address,实际上是调用的下面的这个函数
返回的是加上ERC998的特殊值加上owner的address,可以通过address(_rootOwner)得到owner的address
_tokenId 需要查找的avatar id
function rootOwnerOfChild(address _childContract, uint256 _childTokenId) external view returns (bytes32 rootOwner);
rootOwner:cloth对应的owner address
这里注意一下,此处返回的 root owner有可能是contract address ,也有可能是user address。根据作者的设计总共有四种可能
_childContract : clothes contract address
_childTokenId : clothes id
function ownerOfChild(address _childContract, uint256 _childTokenId) external view returns (bytes32 parentTokenOwner, uint256 parentTokenId);
parentTokenOwner: 返回的是加上ERC998的特殊值加上owner address
parentTokenId : avatar id
_childContract: clothes contract address
_childTokenId: clothes id
function onERC721Received(address _operator, address _from, uint256 _childTokenId, bytes _data) external returns (bytes4);
bytes4: 返回的一个bytes4的值 用于更新其他NTF到avatar时的一个回调方法,告诉avatar转入了这个数据,将此数据添加到avatar的数据中.
这里使用NTF代替其他ERC721 token
_operator: 执行这个操作的address
_from : 原始NTF 拥有者的 address
_childTokenId: NTF id
_data : 附加数据
function transferChild(uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId) external;
function safeTransferChild(uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId) external;
function safeTransferChild(uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId, bytes _data) external
这是三个重载的方法,加上safe是为了确保转入的合约地址有类似于onERC721Received的方法进行回调,确保token不会丢失。如果转入的合约地址没有注册次方法,那么将不会转入成功,从而回退转移操作,保证NTF的安全。
如果转入的是user address,那么直接调用第一个方法即可。
这些方法均会触发TransferChild这个事件
_fromTokenId : avatar id
_to :接受clothes address
_childContract : clothes contract address
_childTokenId : 将要进行转出的clothes id
function transferChildToParent(uint256 _fromTokenId, address _toContract, uint256 _toTokenId, address _childContract, uint256 _childTokenId, bytes _data) external;
如果avatar含有ERC998 ComposableTopDown的token,可以通过这个方法进行转移
function getChild(address _from, uint256 _tokenId, address _childContract, uint256 _childTokenId) external;
用于用户user自己转入clothes到avatar中,注意与onERC721Received进行比较。
_from : clothes拥有者的address
_tokenId :转进给哪一个avatar,即avatar id
_childContract : clothes contract address
_childTokenId : clothes id
interface ERC998ERC721TopDownEnumerable
function totalChildContracts(uint256 _tokenId) external view returns (uint256);
获取avatar下面有多少种类的NFT,目前可以知道我们的项目只有clothes,所以返回1
_tokenId : avatar id
function childContractByIndex(uint256 _tokenId, uint256 _index) external view returns (address childContract);
获取NFT的contract address。目前我们的Bitizen中,仅有clothes,所以结果只有clothes的contract address
_tokenId : avatar id
_index : 从0开始的下标
function totalChildTokens(uint256 _tokenId, address _childContract) external view returns (uint256);
获取NTF的数量,即获取clothes的数量
_tokenId : avatar id
_childContract : NTF contract address,即clothes的合约地址
function childTokenByIndex(uint256 _tokenId, address _childContract, uint256 _index) external view returns (uint256 childTokenId);
根据totalChildTokens的返回值,获取具体的每一个NTF id
_tokenId : avatar id
_childContract : NTF contract address,即clothes的合约地址
_index : 从0 开始的索引,小于totalChildTokens的返回值
interface ERC998ERC20TopDownEnumerable {
function totalERC20Contracts(uint256 _tokenId) external view returns (uint256);
function erc20ContractByIndex(uint256 _tokenId, uint256 _index) external view returns (address);}
interface ERC20AndERC223 {
function transferFrom(address _from, address _to, uint _value) external returns (bool success);
function transfer(address to, uint value) external returns (bool success);
function transfer(address to, uint value, bytes data) external returns (bool success);
function allowance(address _owner, address _spender) external view returns (uint256 remaining);}
ERC20集成到ERC998的interface,可按照ERC721的理解,就不一一讲解了
interface ERC998ERC721BottomUp {
function transferToParent(address _from, address _toContract, uint256 _toTokenId, uint256 _tokenId, bytes _data) external;}
声明ComposableBottonUp的接口,用于transferChildToParent
到此为止,ComposableTopDown的对外开放的接口已经分析完毕了。
ERC998实际运用
Bitizens在这里,你可以找到第一个基于ERC998创建的一款3D游戏,你可以免费创建一个只属于你自己的bitizen.
结尾
这篇文章仅仅分析了ERC998的标准接口,当然其中也涉及到ERC721和ERC20的一些知识,希望能够给将要进入dapp的开发者提供一点点帮助。
文章允许转载,但请注明出处,谢谢
关于我
区块链技术痴迷的程序猿一枚,如果你喜欢我的文章,可以加上微信共同学习,共同进步。