ERC721代码详解

  • A+
所属分类:区块链

目录

name - 名称

Symbol - 符号

totalSupply - 总发行量

balanceOf - 余额

ownerOf - 持币人

approve - 授权

takeOwnership - 获取

transfer - 转账

tokenOfOwnerByIndex - 通证检索

tokenMetaData - 通证元数据

Transfer 事件- 转账

Approval 事件- 批准

ERC-721是非同质化代币(Non-Fungible Token,缩写为NFT)的标准接口。ERC-721在2017年底首先被CryptoKitties游戏所使用,CryptoKitties的火爆让人们意识到了ERC-721的重要价值。ERC-721是非同质化代币,也就意味着每个Token都是不一样的,都有自己的唯一性和独特价值,当然这也就意味着它们是不可分割的,也同时具有了可追踪性。ERC-721代表了对资产的所有权,为物品或记录的代币化提供了可能,开劈了一个巨大的市场,比如现实世界的房屋(房屋是不可移动,占据特定空间的资产,具有唯一性)和独一无二的艺术品;虚拟世界中的收藏物品,如以太坊上的各种收藏游戏中各种独一无二的收藏品;金融交易中的借贷交易记录。

这是一个简明的ERC721智能合约声明:

contract ERC721 {

   //元数据,可选,建议有

   function name() external view returns (string _name);

   function symbol() external view returns (string _symbol);

   function tokenURI(uint256 _tokenId) external view returns (string);

 

   //枚举查询选项,可选,建议有

   function totalSupply() external view returns (uint256);

   function tokenByIndex(uint256 _index) external view returns (uint256);

   function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);

 

 

   //基本函数-查询

   function balanceOf(address _owner) constant returns (uint balance);

   function ownerOf(uint256 _tokenId) constant returns (address owner);

   //基本函数-操作

   function approve(address _to, uint256 _tokenId);(setApprovalForAll/getApproved/isApprovedForAll/)

   function transfer(address _to, uint256 _tokenId);(safeTransferFrom/transferFrom)

   //基本函数-获取元数据

   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);

}

   event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

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;

 

  function totalSupply() constant returns (uint256supply){

    return totalSupply;

  }

}

balanceOf - 余额

该函数用于查询某一地址里的通证余额。例如:

contract MyNFT {

  mapping(address => uint) privatebalances;

  

  function balanceOf(address _owner) constant returns(uint balance){ 

    return balances[_owner];

  }

}

下面这些函数定义了合约如何处理通证的所有权及如何转移所有权。其中最重要的两个函数 是获取(takeOwnership)和转账(transfer),用来实现用户之间的通证流转,就像银行的提款 和汇款功能。

ownerOf - 持币人

该函数返回通证持有人的地址。因为每一个ERC721通证都是不可替代的,因此可以在区块链上 唯一的地址找到,我们可以用通证的ID来确定其持有人。

contract MyNFT {

  mapping(uint256 => address) privatetokenOwners;

  mapping(uint256 => bool) private tokenExists;

 

  function ownerOf(uint256 _tokenId) constant returns (address owner) {

    require(tokenExists[_tokenId]);

    return tokenOwners[_tokenId];

  }

}

approve - 授权

该函数用来授权给另一主体代表持有人进行通证转移操作。例如,假设Alice有一个ERC721通证,她可以 调用approve函数来授权给她的朋友Bob,然后Bob就可以代表Alice行使通证持有人的权利。

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函数来从另一个用户的账户 中提取ERC721通证。

因此,在一个用户被(其他人)授权拥有一定数量的通证的情况下,可以通过该功能将这部分 通证从另一个用户的账户中提取出来。

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[oldOwner] += 1;

    Transfer(oldOwner, newOwner,_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)函数可以通过这种方式追溯某一特定的通证。

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)链接,这些 引用,被称作元数据。元数据是可选的。

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);

}

 

ERC721的相关应用:

CryptoKitties. https://www.cryptokitties.co

0xcert ERC-721 Token. https://github.com/0xcert/ethereum-erc721

Su Squares. https://tenthousandsu.com

Decentraland. https://decentraland.org

CryptoPunks. https://www.larvalabs.com/cryptopunks

DMarket. https://www.dmarket.io

Enjin Coin. https://enjincoin.io

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: