剖析非同质化代币ERC721-全面解析ERC721标准

什么是ERC-721?现在我们看到的各种加密猫猫狗狗都是基于ERC-721创造出来的,每只都是一个独一无二的ERC-721代币,不过ERC-721在区块链世界远不止猫猫狗狗,它更大的想象空间在于将物理世界的资产映射到区块链上。本文就来剖析下什么是ERC721.

ERC721是什么

创建代币一篇,我们讲到过ERC20代币,
和ERC20一样,ERC721同样是一个代币标准,ERC721官方简要解释是Non-Fungible Tokens,简写为NFTs,多翻译为非同质代币。

ERC721 是由Dieter Shirley 在2017年9月提出。Dieter Shirley 正是谜恋猫CryptoKitties背后的公司Axiom Zen的技术总监。因此谜恋猫也是第一个实现了ERC721 标准的去中心化应用。ERC721号提议已经被以太坊作为标准接受,但该标准仍处于草稿阶段。本文介绍的ERC721标准基于最新(2018/03/23官方提议。

那怎么理解非同质代币呢?

非同质代表独一无二,谜恋猫为例,每只猫都被赋予拥有基因,是独一无二的(一只猫就是一个NFTs),猫之间是不能置换的。这种独特性使得某些稀有猫具有收藏价值,也因此受到追捧。

ERC20代币是可置换的,且可细分为N份(1 = 10 * 0.1), 而ERC721的Token最小的单位为1,无法再分割。

如果同一个集合的两个物品具有不同的特征,这两个物品是非同质的,而同质是某个部分或数量可以被另一个同等部分或数量所代替。

非同质性其实广泛存在于我们的生活中,如图书馆的每一本,宠物商店的每一只宠物,歌手所演唱的歌曲,花店里不同的花等等,因此ERC721合约必定有广泛的应用场景。通过这样一个标准,也可建立跨功能的NFTs管理和销售平台(就像有支持ERC20的交易所和钱包一样),使生态更加强大。

ERC721标准

ERC721最为一个合约标准,提供了在实现ERC721代币时必须要遵守的协议,要求每个ERC721标准合约需要实现ERC721及ERC165接口,接口定义如下:

pragma solidity ^0.4.20;

interface ERC721 /* is ERC165 */ {

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

    function balanceOf(address _owner) external view returns (uint256);
    function ownerOf(uint256 _tokenId) external view returns (address);

    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

    function approve(address _approved, uint256 _tokenId) external payable;
    function setApprovalForAll(address _operator, bool _approved) external;
    function getApproved(uint256 _tokenId) external view returns (address);
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

接口说明:

  • balanceOf(): 返回由_owner 持有的NFTs的数量。
  • ownerOf(): 返回tokenId代币持有者的地址。
  • approve(): 授予地址_to具有_tokenId的控制权,方法成功后需触发Approval 事件。
  • setApprovalForAll(): 授予地址_operator具有所有NFTs的控制权,成功后需触发ApprovalForAll事件。
  • getApproved()、isApprovedForAll(): 用来查询授权。
  • safeTransferFrom(): 转移NFT所有权,一次成功的转移操作必须发起 Transer 事件。函数的实现需要做一下几种检查:
    1. 调用者msg.sender应该是当前tokenId的所有者或被授权的地址
    2. _from 必须是 _tokenId的所有者
    3. _tokenId 应该是当前合约正在监测的NFTs 中的任何一个
    4. _to 地址不应该为 0
    5. 如果_to 是一个合约应该调用其onERC721Received方法, 并且检查其返回值,如果返回值不为bytes4(keccak256("onERC721Received(address,uint256,bytes)"))抛出异常。
      一个可接收NFT的合约必须实现ERC721TokenReceiver接口:
      interface ERC721TokenReceiver {
      /// @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
      function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
      }
  • transferFrom(): 用来转移NFTs, 方法成功后需触发Transfer事件。调用者自己确认_to地址能正常接收NFT,否则将丢失此NFT。此函数实现时需要检查上面条件的前4条。

ERC165 标准

ERC721标准同时要求必须符合ERC165标准 ,其接口如下:

interface ERC165 {
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

ERC165同样是一个合约标准,这个标准要求合约提供其实现了哪些接口,这样再与合约进行交互的时候可以先调用此接口进行查询。
interfaceID为函数选择器,计算方式有两种,如:bytes4(keccak256(‘supportsInterface(bytes4)‘));ERC165.supportsInterface.selector,多个函数的接口ID为函数选择器的异或值。
关于ERC165,这里不深入介绍,有兴趣的同学可以阅读官方提案

可选实现接口:ERC721Metadata

ERC721Metadata 接口用于提供合约的元数据:name , symbol 及 URI(NFT所对应的资源)。
其接口定义如下:

interface ERC721Metadata /* is ERC721 */ {
    function name() external pure returns (string _name);
    function symbol() external pure returns (string _symbol);
    function tokenURI(uint256 _tokenId) external view returns (string);
}

接口说明:

  • name(): 返回合约名字,尽管是可选,但强烈建议实现,即便是返回空字符串。
  • symbol(): 返回合约代币符号,尽管是可选,但强烈建议实现,即便是返回空字符串。
  • tokenURI(): 返回_tokenId所对应的外部资源文件的URI(通常是IPFS或HTTP(S)路径)。外部资源文件需要包含名字、描述、图片,其格式的要求如下:
    {
    "title": "Asset Metadata",
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "description": "Identifies the asset to which this NFT represents",
        },
        "description": {
            "type": "string",
            "description": "Describes the asset to which this NFT represents",
        },
        "image": {
            "type": "string",
            "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.",
        }
    }
    }

    tokenURI通常是被web3调用,以便在应用层做相应的查询和展示。

可选实现接口:ERC721Enumerable

ERC721Enumerable的主要目的是提高合约中NTF的可访问性,其接口定义如下:

interface ERC721Enumerable /* is ERC721 */ {
    function totalSupply() external view returns (uint256);
    function tokenByIndex(uint256 _index) external view returns (uint256);
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}

接口说明:

  • totalSupply(): 返回NFT总量
  • tokenByIndex(): 通过索引返回对应的tokenId。
  • tokenOfOwnerByIndex(): 所有者可以一次拥有多个的NFT, 此函数返回_owner拥有的NFT列表中对应索引的tokenId。

补充说明

NTF IDs

NTF ID,即tokenId,在合约中用唯一的uint265进行标识,每个NFT的ID在智能合约的生命周期内不允许改变。推荐的实现方式有:

  1. 从0开始,每新加一个NFT,NTF ID加1
  2. 使用sha3后uuid 转换为 NTF ID

与ERC-20的兼容性

ERC721标准尽可能遵循 ERC-20 的语义,但由于同质代币与非同质代币之间的根本差异,并不能完全兼容ERC-20。

交易、挖矿、销毁

在实现transter相关接口时除了满足上面的的条件外,我们可以根据需要添加自己的逻辑,如加入黑名单等。
同时挖矿、销毁尽管不是标准的一部分,我们可以根据需要实现。

参考实现

参考实现为订阅用户专有福利,请订阅我的小专栏:区块链技术查看。

## 参考文献
1. [EIPS-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md)
2. [EIPS-721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md)
3. [深入浅出区块链](https://learnblockchain.cn/) - 系统学习区块链,打造最好的区块链技术博客。

原文地址:http://blog.51cto.com/13457438/2117111

时间: 2024-08-30 16:52:58

剖析非同质化代币ERC721-全面解析ERC721标准的相关文章

以太坊代币合约详析

以太坊代币 在以太坊系统中,存在作为基础货币的 Ether(以太),以及同样可以作为货币使用的 Token(代币). 以太坊与其他加密货币的主要不同在于,以太坊不是单纯的货币,而是一个环境/平台.在这个平台上,任何人都可以利用区块链的技术,通过智能合约来构建自己的项目和DAPPS(去中心化应用). 如果把以太坊理解成互联网,DAPPS则是在上面运行的网页.DAPPS是去中心化的,意味着它不属于某个人,而是属于一群人.DAPPS发布的方式通常是采用被称为 ICO 的众筹方式.简单来说,你需要用你的

基于以太坊实现代币发布

https://blog.csdn.net/Y_xiaohe1234/article/details/76848150 一.什么是代币?代币是利用以太坊的智能合约编写的数字货币.程序员可以通过编写智能合约代码,创建一种新的数字货币.你可以实现的功能: 基本功能:-创建数字货币,设置货币的名称.货币总量.货币图标等基本参数.-创建货币交易功能.实现货币在不同用户之间的转移. 上面的是基本功能,已经可以实现基本的代表交换,下面是高级功能,可以实现更加复杂的应用.高级功能:-创建货币的管理者.虽然区块

【在 Nervos CKB 上做开发】Nervos CKB 脚本编程简介[3]:自定义代币

原文作者:Xuejie 原文链接:https://xuejie.space/2019_09_06_introduction_to_ckb_script_programming_udt/ Nervos CKB 脚本编程简介[3]:自定义代币 CKB 的 Cell 模型和 VM 支持许多新的用例.然而,这并不意味着我们需要抛弃现有的一切.如今区块链中的一个常见用途是 Token 发行者发布具有特殊目的/意义的新 Token.在以太坊中,我们称之为 ERC20 Token,下面让我们看看我们如何在 C

程序员的自我救赎---12.2.1: 虚拟币交易平台(区块链) 上【发行区块链代币】

<前言> (一) Winner2.0 框架基础分析 (二)PLSQL报表系统 (三)SSO单点登录 (四) 短信中心与消息中心 (五)钱包系统 (六)GPU支付中心 (七)权限系统 (八)监控系统 (九)会员中心 (十) APP版本控制系统 (十一)Winner前端框架与RPC接口规范讲解 (十二)上层应用案例 (十三)总结 <虚拟币交易平台(区块链)> --上 [发行区块链代币] 关于对于区块链 或者 比特币还没有一个基础概念的就自行百度吧,什么"去中心化",

数字代币ICO

随着比特币.莱特币.以太币的逐步兴起,越来越多的数字代币开始衍生,虚拟货币扑朔迷离,一不小心就被人割了韭菜..... 从荷兰IPO的故事说起 400多年前,西方有一群精英海盗开了一家公司.为了顺利拓展东方的海上业务,他们必须弄来很多的钱去买粮食和弹药.海盗想:要不先跟父老相亲借?如果能抢到很多东西,那么回巢就还他们钱,另外再给一些钱(分红)都不是问题. 于是,投钱的西方人就成了史上最早期的股东,海盗公司会给每个股东发个凭证,这就是股票最早的样子.如果要用钱,人们就拿着凭证去公司换钱. 再后来还出

solidity开发以太坊代币智能合约

智能合约开发是以太坊编程的核心之一,而代币是区块链应用的关键环节,下面我们来用solidity语言开发一个代币合约的实例,希望对大家有帮助. 以太坊的应用被称为去中心化应用(DApp),DApp的开发主要包括两大部分: 智能合约的开发 用户界面的开发 在本文中,我们将介绍智能合约的开发语言solidity. 让我们先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. contract SimpleStorage { uint storedData; functi

创建自己的加密货币MNC——以太坊代币(二)

创建一个基于以太坊平台的分红币MNC,根据持有的代币数量,进行分红的算法.github地址: https://github.com/lxr1907/MNC 1.使用以太坊根据比例换购token MNC 2.定期根据使用用户资金购买的矿机挖ETH,打入该合约,触发分红方法根据token持有比例分红 3.衰减,由于矿机有折旧衰减损坏的概率,token会随着持有时间而衰减. 代码如下 pragma solidity ^0.4.19; contract owned { address public ow

小虎链:代币和积分有什么区别?

有人问代币和积分有什么区别?小虎认为代币和积分的本质区别是:一个是基于区块链而产生的,而积分并不是基于区块链的!代币的价值要远远大于积分! 像理发店的积分和你玩游戏的时候获的积分是同样的概念.这些积分都是用来积累到一定程度就能兑换相应的东西或者奖励的.而且这些积分是可以无限增加的. 而代币就是数字货币了,是基于区块链技术的,发行总量有限.而且是去中心化的,采用分布式记账的! 而从表面上看,两者都是一种虚拟奖励,但是因为其背后的支撑逻辑不同: 第一:形成逻辑不同,代币是基于去中心化的区块链技术形成

科普贴 | 以太坊代币钱包MyEtherWallet使用教程,一步步教你玩转MEW

MyEtherWallet 是一个以太坊的网页钱包,使用非常简单,打开网页就可以使用,源代码开源,不会在服务器上存储用户的钱包信息如私钥和密码.支持 Ledger Wallet.TREZOR 等硬件钱包,功能极为丰富.是一把我们经常会用到的瑞士军刀! Myetherwallet 支持符合 ERC20 标准的代币(即以太坊系代币). 官网:https://www.myetherwallet.com/ ,一定要认准网址. 创建钱包1. 打开官网,将页面切换为中文,设置一个钱包密码(不少于9位,一定要