ERC721藏品合约标准解析及代码实现
(2019-09-04 11:48:45)
标签:
erc721 |
分类: 区块链 |
我们可以用以太坊智能合约来模拟稀有的收藏品,每一个通证都遵循以太坊ERC-721标准,
它是DieterShirley在2017年末提出的以太坊改进建议书。ERC721可以使智能合约像类似于
ERC20代币一样进行交易, 区别在于,ERC721通证是独一无二的,每一个都有唯一的ID,具有不可取代性。
它是DieterShirley在2017年末提出的以太坊改进建议书。ERC721可以使智能合约像类似于
ERC20代币一样进行交易, 区别在于,ERC721通证是独一无二的,每一个都有唯一的ID,具有不可取代性。
ERC721约定了一些接口函数,使它在一定程度上符合ERC20代币标准。这么做是为了让现有的
钱包更容易显示代币的基本信息。这些函数可以让符合ERC721标准的智能合约像比特币或者
以太币这样普通的数字加密币一样,通过智能合约编程的方式定义一些功能让用户实现向他人
发送代币或检查账户余额等操作。
钱包更容易显示代币的基本信息。这些函数可以让符合ERC721标准的智能合约像比特币或者
以太币这样普通的数字加密币一样,通过智能合约编程的方式定义一些功能让用户实现向他人
发送代币或检查账户余额等操作。
这是一个简明的ERC721智能合约声明:
contract ERC721 {
//与ERC20兼容的接口
function name() constant
returns (string name);
function symbol() constant
returns (string symbol);
function totalSupply()
constant returns (uint256 totalSupply);
function balanceOf(address
_owner) constant returns (uint balance);
//所有权相关的接口
function ownerOf(uint256
_tokenId) constant returns (address owner);
function approve(address _to,
uint256 _tokenId);
function takeOwnership(uint256
_tokenId);
function transfer(address _to,
uint256 _tokenId);
function
tokenOfOwnerByIndex(address _owner, uint256 _index) constant
returns (uint tokenId);
//通证元数据接口
function tokenMetadata(uint256
_tokenId) constant returns (string infoUrl);
//事件
event Transfer(address indexed
_from, address indexed _to, uint256 _tokenId);
event Approval(address indexed
_owner, address indexed _approved, uint256 _tokenId);
}
}
name - 名称
该函数应当返回通证的名称。 例如:
contract MyNFT {
function name() constant returns(string
name){
return "My
Non-FungibleToken";
}
}
}
Symbol - 符号
该函数应当返回通证的符号,它有助于提高与ERC20的兼容性。例如:
contract MyNFT {
function symbol() constant returns(string
symbol){
return
"MNFT";
}
}
}
totalSupply - 总发行量
该函数应当返回区块链上供应的通证总数量,该数量不一定是固定不变的。
例如:
例如:
contract MyNFT {
//想发行多少取决于你 ;)
uint256 private totalSupply = 1000000000;
}
balanceOf - 余额
该函数用于查询某一地址里的通证余额。例如:
contract MyNFT {
mapping(address => uint)
privatebalances;
}
下面这些函数定义了合约如何处理通证的所有权及如何转移所有权。其中最重要的两个函数
是获取(takeOwnership)和转账(transfer),用来实现用户之间的通证流转,就像银行的提款
和汇款功能。
是获取(takeOwnership)和转账(transfer),用来实现用户之间的通证流转,就像银行的提款
和汇款功能。
ownerOf - 持币人
该函数返回通证持有人的地址。因为每一个ERC721通证都是不可替代的,因此可以在区块链上
唯一的地址找到,我们可以用通证的ID来确定其持有人。
唯一的地址找到,我们可以用通证的ID来确定其持有人。
contract MyNFT {
mapping(uint256 => address)
privatetokenOwners;
mapping(uint256 => bool) private
tokenExists;
}
approve - 授权
该函数用来授权给另一主体代表持有人进行通证转移操作。例如,假设Alice有一个ERC721通证,她可以
调用approve函数来授权给她的朋友Bob,然后Bob就可以代表Alice行使通证持有人的权利。
调用approve函数来授权给她的朋友Bob,然后Bob就可以代表Alice行使通证持有人的权利。
contract MyNFT {
mapping(address => mapping (address=>
uint256)) allowed;
}
takeOwnership - 获取
该函数类似于取款功能,一个外部主体通过调用takeOwnership函数来从另一个用户的账户
中提取ERC721通证。因此,在一个用户被(其他人)授权拥有一定数量的通证的情况下,可以通过该功能将这部分
中提取ERC721通证。因此,在一个用户被(其他人)授权拥有一定数量的通证的情况下,可以通过该功能将这部分
通证从另一个用户的账户中提取出来。
contract MyNFT {
function takeOwnership(uint256_tokenId){
require(tokenExists[_tokenId]);
}
transfer - 转账
另一种转移通证的方法时使用transfer函数。转账(transfer)功能可以让用户将通证发给另一个用户,
类似于操作比特币这样的加密数字货币。然而,只有在汇出账户之前授权过汇入账户持有其通证的
情况下,才可以进行转账。
类似于操作比特币这样的加密数字货币。然而,只有在汇出账户之前授权过汇入账户持有其通证的
情况下,才可以进行转账。
contract MyNFT {
mapping(address => mapping(uint256 =>
uint256)) private ownerTokens;
function removeFromTokenList(address owner,
uint256 _tokenId) private {
for(uint256
i = 0;ownerTokens[owner][i] != _tokenId;i++){
ownerTokens[owner][i] = 0;
}
}
function transfer(address _to, uint256
_tokenId){
address
currentOwner = msg.sender;
address
newOwner = _to;
require(tokenExists[_tokenId]);
require(currentOwner == ownerOf(_tokenId));
require(currentOwner != newOwner);
require(newOwner != address(0));
removeFromTokenList(_tokenId);
balances[oldOwner] -= 1;
tokenOwners[_tokenId] = newOwner;
balances[newOwner] += 1;
Transfer(oldOwner, newOwner, _tokenId);
}
}
}
tokenOfOwnerByIndex - 通证检索
这个函数是可选的,但推荐你实现它。
每一个ERC721通证的持有者可以同时持有不止一个通证,因为每个通证都有唯一的ID,但是,要跟踪某个用户持有的通证可能就会比较困难。为此,合约需要记录每个用户持有的每个通证。通过这种方式,用户可以
通过索引清单检索其拥有的通证。通证检索(tokenOfOwnerByIndex)函数可以通过这种方式追溯某一特定的通证。
通过索引清单检索其拥有的通证。通证检索(tokenOfOwnerByIndex)函数可以通过这种方式追溯某一特定的通证。
contract MyNFT {
mapping(address => mapping(uint256 =>
uint256)) private ownerTokens;
function tokenOfOwnerByIndex(address _owner,
uint256 _index) constant returns (uint tokenId){
return
ownerTokens[_owner][_index];
}
}
}
tokenMetaData - 通证元数据
就像我们之前所说的,使物品具有不可替代性的是它们独一无二的特质。美元和网球卡不可替代,
因为它们的特征不同。但是,在区块链上将这些区分每个通证的特征储存下来成本很高,也不推荐这么做。
为了解决这个问题,我们可以储存每个通证的引用(references),例如IPFS哈希或HTTP(S)链接,这些
引用,被称作元数据。元数据是可选的。
因为它们的特征不同。但是,在区块链上将这些区分每个通证的特征储存下来成本很高,也不推荐这么做。
为了解决这个问题,我们可以储存每个通证的引用(references),例如IPFS哈希或HTTP(S)链接,这些
引用,被称作元数据。元数据是可选的。
tokenMetaData函数应当返回通证的元数据,或者通证数据的链接。
contract MyNFT {
mapping(uint256 => string) tokenLinks;
function tokenMetadata(uint256 _tokenId)
constant returns (string infoUrl) {
return
tokenLinks[_tokenId];
}
}
}
当调用合约方法的时候,事件将会被触发,并且一旦被触发就会向监听系统传播。外部应用可以监听区块链
中的事件,一旦接收到区块链中的事件被触发,监听系统就可以通过事件中包含的信息执行逻辑程序。
中的事件,一旦接收到区块链中的事件被触发,监听系统就可以通过事件中包含的信息执行逻辑程序。
ERC721标准定义了下面两个事件。
Transfer - 转账
当一个通证的所有权从一个用户转移到另一个时,将触发该事件,事件的信息包括汇出账户、汇入账户和通证ID。
contract MyNFT {
event Transfer(address indexed _from,address
indexed _to, uint256 _tokenId);
}
Approval - 批准
当一个用户允许另一个用户持有其通证的时候(例如启用“授权”功能的时候),该事件就会被触发,事件的信息中包含这些通证现在的持有账户、被授权账户以及通证ID。
contract MyNFT {
event Approval(address indexed _owner, address
indexed _approved, uint256 _tokenId);
}
}
完整的源代码在https://gist.github.com/aunyks/b25cffd4f4250a3fbf26e3a626441e33。
————————————————
版权声明:本文为CSDN博主「新缸中之脑」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shebao3333/article/details/80233967
————————————————
版权声明:本文为CSDN博主「新缸中之脑」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shebao3333/article/details/80233967
前一篇:ERC20和ERC721

加载中…