ERC721的分析:理解非同质化以太坊资产……

  • aunyks
  • 发布于 2017-12-27 12:52
  • 阅读 23

文章详细介绍了ERC721标准,解释了非同质化代币(NFT)的概念及其在以太坊区块链上的应用,特别是通过CryptoKitties游戏展示了NFT的独特性和可收藏性。

ERC721的结构

理解非同质化以太坊代币

许多人听说过在以太坊区块链上新推出的游戏CryptoKitties。这个新游戏最近在加密货币社区中引起了许多关注,因为它非常独特的想法和对以太坊网络的影响。CryptoKitties是一款玩家可以购买、出售、交易和繁殖数字猫的游戏。可以将其视作“可繁殖的Beanie Babies”,因为每只猫在某种程度上都是独一无二的。这种独特性使得CryptoKitties极具收藏价值,因为有人可能会对几只小猫的特征产生兴趣,想要拥有其中的多只。

来源: Vice Media

但收藏品并不仅限于数字猫。人类一直以来都有收集物品的历史;这并不新鲜。从实物硬币宝可梦卡,人们喜欢收集。这是一种因对稀缺物品的独特兴趣而形成的爱好。与商品的价值与其稀缺性相关一样,收藏品对收藏者的价值也与其在其他物品中的稀有程度相关。

我们可以利用以太坊代币模拟稀有的收藏品,而这些代币都遵循以太坊社区中称为ERC721的新标准。以太坊注释请求721,或ERC721,是由Dieter Shirley在2017年末提出的一项以太坊改进提案。这是一个建议的标准,允许智能合约作为可交易的代币运作,类似于ERC20。ERC721代币的独特之处在于这些代币是非同质化的。

ERC:非同质化代币标准 ·

同质化 — 指某种性质(例如货币或商品)使得在支付债务或结算账户时,一部分或数量可以被另一个等量的部分或数量替代。来源:Merriam-Webster

同质化本质上是资产的一个特征,或在这里的情况下是标记,决定了相同或类似类型的物品或数量在交换或实用过程中是否可以完全互换。例如,下面的美国五美元钞票可以用于从便利店购买一瓶苏打。

它有价值,可以用于购买相同或更少价值的物品。然而,当一个人试图用下面的棒球卡购买苏打时,店主不会接受它。

来源: Baseball Card Stars

为什么上面的Carlos Santana卡在价值5美元的情况下不会被店主接受?这是因为棒球卡和美元钞票具有不同的特征,这些特征定义了它们对某些人的价值。一个7岁的孩子可能愿意支付7美元购买这张棒球卡,因为他喜欢卡上的颜色。但是,店主甚至不认为这张卡值5美元,仅仅因为它不是由美联储发行的。棒球卡和美元钞票的独特属性是导致它们无法互换的原因,因为它们的价值取决于交换,不能总是互换使用。

就收藏品来说,如果收藏中的两个物品具有不同的特征,它们就不是同质化的。对于实物硬币来说,金币和铜币不是同质化的,因为它们的不同特征使得它们对收藏者有不同的价值。

ERC721代币可以在任何交换中使用,但它们的价值是由于与每个代币相关的独特性和稀缺性。该标准定义了函数 namesymboltotalSupplybalanceOfownerOfapprovetakeOwnershiptransfertokenOfOwnerByIndextokenMetadata。它还定义了两个事件:TransferApproval

请注意:以下是一个ERC721合约示例的简要声明。

erc721-definitions.sol – Medium

contractERC721 {
// 兼容ERC20的函数
function name() constantreturns (stringname);
function symbol() constantreturns (stringsymbol);
function totalSupply() constantreturns (uint256totalSupply);
function balanceOf(address_owner) constantreturns (uintbalance);
// 定义所有权的函数
function ownerOf(uint256_tokenId) constantreturns (addressowner);
function approve(address_to, uint256_tokenId);
function takeOwnership(uint256_tokenId);
function transfer(address_to, uint256_tokenId);
function tokenOfOwnerByIndex(address_owner, uint256_index) constantreturns (uinttokenId);
// 代币元数据
function tokenMetadata(uint256_tokenId) constantreturns (stringinfoUrl);
// 事件
event Transfer(addressindexed_from, addressindexed_to, uint256_tokenId);
event Approval(addressindexed_owner, addressindexed_approved, uint256_tokenId);
}

查看原始 erc721-definitions.sol
GitHub 提供 ❤ 托管

合约内部每个字段的概述如下。

请务必注意:以下代码仅用于教育目的,未经过测试。请勿在生产应用中实施!

类似ERC20的函数

ERC721定义了一些函数,使其在某种程度上与ERC20代币标准兼容。这样做可以使现有钱包更容易显示有关代币的简单信息。这些函数使符合该标准的智能合约能够像比特币或以太坊等常见加密货币一样,通过定义让用户执行发送代币和查看账户余额等操作的函数。

name

此函数用于告知外部合约和应用该代币的名称。函数的一个示例实现如下。

contract MyNFT {
  function name() constant returns (string name){
    return "My Non-Fungible Token";
  }}

symbol

此函数也帮助提供与ERC20代币标准的兼容性。它为外部程序提供代币的简称或符号。

contract MyNFT {
  function symbol() constant returns (string symbol){
    return "MNFT";  }}

totalSupply

此函数返回区块链上可用的代币总数。供应不必是固定的。

contract MyNFT {
  // 这可以是一个任意数字  uint256 private totalSupply = 1000000000;  function totalSupply() constant returns (uint256 supply){
    return totalSupply;  }}

balanceOf

此函数用于查找给定地址所拥有的代币数量。

contract MyNFT {
  mapping(address => uint) private balances;  function balanceOf(address _owner) constant returns (uint balance)
  {
    return balances[_owner];  }}

所有权函数

这些函数定义该合约将如何处理代币的所有权以及如何转移所有权。最显著的函数是 takeOwnershiptransfer,它们分别像取款和发送功能,并且对于让用户之间转移代币至关重要。

ownerOf

此函数返回一个代币的拥有者的地址。由于每个ERC721代币是非同质化的,因此独特的,它通过唯一的ID在区块链上进行引用。我们可以使用代币的ID来确定代币的拥有者。

contract MyNFT {
  mapping(uint256 => address) private tokenOwners;
  mapping(uint256 => bool) private tokenExists;  function ownerOf(uint256 _tokenId)
  constant returns (address owner) {
    require(tokenExists[_tokenId]);    return tokenOwners[_tokenId];  }}

approve

此函数批准或授权另一个实体代表所有者转移代币。例如,如果Alice拥有1个MyNFT,她可以为她的朋友Bob调用approve函数。经过成功调用后,Bob可以在稍后的时间代表Alice对代币进行所有权或操作的请求。有关转移所有权的更多信息可以在takeOwnershiptransfer函数中看到。

contract MyNFT {
  mapping(address => mapping (address => uint256)) allowed;  function approve(address _to, uint256 _tokenId){
    require(msg.sender == ownerOf(_tokenId));
    require(msg.sender != _to);    allowed[msg.sender][_to] = _tokenId;
    Approval(msg.sender, _to, _tokenId);  }}

takeOwnership

此函数类似于一个取款功能,因为外部方可以调用它,以便从另一个用户的账户中提取代币。因此,当用户已被批准 持有一定数量的代币并希望从另一个用户的余额中提取这些代币时,可以使用takeOwnership

contract MyNFT {
  function takeOwnership(uint256 _tokenId){
    require(tokenExists[_tokenId]);    address oldOwner = ownerOf(_tokenId);
    address newOwner = msg.sender;    require(newOwner != oldOwner);    require(allowed[oldOwner][newOwner] == _tokenId);
    balances[oldOwner] -= 1;
    tokenOwners[_tokenId] = newOwner;    balances[newOwner] += 1;
    Transfer(oldOwner, newOwner, _tokenId);  }}

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(可选 — 推荐)

每个非同质化代币的拥有者可以同时拥有多个代币。然而,由于每个代币由其唯一ID引用,用户所拥有的单个代币可能很难跟踪。为此,合约保持记录每个用户拥有的代币ID。因此,用户所拥有的每个代币都可以通过其在用户所拥有的代币列表(数组)中的索引进行检索。tokenOfOwnerByIndex允许我们以这种方式检索一个代币。

contract MyNFT {
  mapping(address => mapping(uint256 => uint256)) private ownerTokens;  function tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId){    return ownerTokens[_owner][_index];  }}

元数据函数

正如我们之前所说,制造非同质化物品非同质化的,是它们独特的属性集合。美元和棒球卡不是同质化的,因为它们具有不同的特征。但是,在区块链上存储定义每个代币特征的数据是非常昂贵且不推荐的。为了对抗这个问题,我们可以在区块链上存储引用,比如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

此事件在用户批准另一用户接管代币所有权时触发(即每次执行approve时)。它详细说明了当前拥有代币的账户,将来被允许拥有该代币的账户,以及获得所有权转移的代币(按ID)。

contract MyNFT {
  event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);}

我实现的ERC721标准的源代码可以在这里找到。

与ERC20类似,新提出的ERC721标准为新的智能合约开辟了作为非同质化物品的通道。在像CryptoKittiesDecentralandCryptoPunks等应用中可以看到,非同质化代币已被证明是需求极高的产品。甚至维基解密拥有几只高价值的CryptoKitties!但最终,该标准将进一步扩展加密货币经济,并推动该领域更进一步发展。

非常感谢你的阅读!请务必关注我们的Twitter

*在本篇写作时,ERC721尚未成为正式标准,仍在修订中。

  • 原文链接: medium.com/crypto-curren...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
aunyks
aunyks
江湖只有他的大名,没有他的介绍。