最新内容会更新在主站深入浅出区块链社区

原文链接:剖析非同质化代币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
  2. EIPS-721

欢迎来我的知识星球深入浅出区块链讨论区块链,作为星友福利,星友可加入区块链技术付费交流群。

深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。

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

  1. 以太坊ERC20代币合约案例

    一.ERC20代币合约与web3调用 ERC20代币合约在小白看来觉得很高大上,但其实就是一个代币的定义标准,方便其他dapp统一调用各种代币的方法.如图: 二.ERC20合约标准 [官方链接] co ...

  2. 以太坊钱包开发系列4 - 发送Token(代币)

    以太坊去中心化网页钱包开发系列,将从零开始开发出一个可以实际使用的钱包,本系列文章是理论与实战相结合,一共有四篇:创建钱包账号.账号Keystore文件导入导出.展示钱包信息及发起签名交易.发送Tok ...

  3. 发行NEO的NEP-5合约代币

    NEO常见的资产有三种 TOKEN (全局资产) Share (全局资产,股份 ) NEP-5 (合约代币,相当于ETH的ERC20) NEP-5 合约代码 https://github.com/AN ...

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

    原文作者:Xuejie 原文链接:https://xuejie.space/2019_09_06_introduction_to_ckb_script_programming_udt/ Nervos ...

  5. 一步步教你创建自己的数字货币(代币)进行ICO

    本文从技术角度详细介绍如何基于以太坊ERC20创建代币的流程. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以太坊是什么 ...

  6. 用solidity语言开发代币智能合约

    智能合约开发是以太坊编程的核心之一,而代币是区块链应用的关键环节,下面我们来用solidity语言开发一个代币合约的实例,希望对大家有帮助. 以太坊的应用被称为去中心化应用(DApp),DApp的开发 ...

  7. 10分钟 5步 发布以太坊 ERC20 代币

    1.安装 METAMASK Brings Ethereum to your browser 一个可以浏览器上进行操作的以太坊钱包,推荐 Chrome. Chrome 插件安装地址: https://c ...

  8. 以太坊ERC20代币开发

    以太坊ERC20代币开发首先需要对以太坊,代币,ERC20,智能合约等以太坊代币开发中的基本概念有了解.根据我们的示例代码就可以发行自己的以太坊代币. 什么是ERC20 可以把ERC20简单理解成以太 ...

  9. Go-Ethereum 1.7.2 结合 Mist 0.9.2 实现代币智能合约的实例

    目录 目录 1.什么是 Mist 2.Mist 在哪里下载? 3.Mist 有哪些依赖? 4.如何安装 Mist? 4.1.安装 Mist 依赖工具包 4.2.安装 Mist 4.3.启动 Mist, ...

随机推荐

  1. "No Python interpreter configured for the project " in Pycharm for python selenium

    自动化测试问题: pyCharm提示python Interpreter没有设置,点击configure Python Interpreter,进入Settings 在 Project Interpr ...

  2. 下载jQuery EasyUI出现网络问题

    下载jQuery EasyUI出现网络问题 1.具体错误如下 错误 137 (net::ERR_NAME_RESOLUTION_FAILED):未知错误 2.错误原因 由于DNS配置出现问题,导致该网 ...

  3. nest exception is java.sql.SQLException:ORA-01476:除数为0

    1.错误描述 nest exception is java.sql.SQLException:ORA-01476:除数为0 2.错误原因 3.解决办法

  4. 采用Global.asax的Application_BeginRequest事件过滤敏感字符

    1.特殊字符过滤公共类ProcessRequest.cs using System.Web.UI; using System.Web.UI.WebControls; using System.Web. ...

  5. 芝麻HTTP:Python爬虫实战之抓取爱问知识人问题并保存至数据库

    本次为大家带来的是抓取爱问知识人的问题并将问题和答案保存到数据库的方法,涉及的内容包括: Urllib的用法及异常处理 Beautiful Soup的简单应用 MySQLdb的基础用法 正则表达式的简 ...

  6. <训练赛> 垃圾陷阱

    垃圾陷阱 时间限制: 1 Sec  内存限制: 128 MB提交: 78  解决: 38[提交][状态][讨论版] 题目描述 卡门--农夫约翰极其珍视的一条Holsteins奶牛--已经落了到&quo ...

  7. JNDI在server.xml中的配置(全局和局部的)

    总结: 全局就是在数据源server.xml中配置,然后通过和项目名相同的xml来进行映射.对所有的项目都起作用.那个项目需要就在对应的tomcat下配置一个与项目名相同的xml映射文件. 局部的就是 ...

  8. Treeview 丢失焦点后依然高亮 SelectedNode

    参考:StackOverFlow.Control.Validating 事件 注意 TreeView 的 HideSelection 要保持为默认值True. private TreeNode pre ...

  9. Kettle根据时间戳同步数据实现

    1 Kettle总体步骤 由于Kettle自身的特殊性以及在多个步骤中kettle自身处理数据库事务的特殊性,尝试了很多种方案,最终确定暂使用如下方案. 1.使用此方案可以解决kettle本身数据库事 ...

  10. Python机器学习:5.6 使用核PCA进行非线性映射

    许多机器学习算法都有一个假设:输入数据要是线性可分的.感知机算法必须针对完全线性可分数据才能收敛.考虑到噪音,Adalien.逻辑斯蒂回归和SVM并不会要求数据完全线性可分. 但是现实生活中有大量的非 ...