在本系列的第一篇文章中 ,我介绍了非真伪令牌(NFT)的概念以及对ERC721(草案)标准的需求 。 在本文中,我们将首先介绍ERC721标准接口,并分解一些要求。 关于ERC165标准还将有一个简短但重要的绕道。

“ Todd Quackenbush在Unsplash上显示的一个工具包的显示内容显示了诸如锤子,斧子,盒子切割器,铁和手电筒之类的工具

接口和ERC165标准

ERC721标准指出:

“每个符合ERC-721的合同都必须实现ERC721和ERC165接口”

如果您从来不需要编写一个Solidity协议,并与其他开发人员编写的合同一起工作,您可能会想知道“什么是接口 ?”。 不管你是否想知道,“什么是ERC621接口?”。 所以让我们回答这两个问题。

接口

一个接口基本上是一个抽象契约,但是你唯一可以定义的是未实现的函数。这是一个用Solidity代码编写的概要,它确保其他开发人员编写的合同能够很好地协同工作,而不必知道彼此的代码库。

例如,如果一个接口将函数balanceOf定义为

 函数balanceOf(地址_owner)外部视图返回(uint256); 

那么你知道任何实现该接口的 契约都会有一个称为balanceOf的函数,它接受一个参数( 地址 )并返回一个值( uint256 )。 你也知道这个函数的可变性是view,这意味着该函数能够读取合同状态,但不能修改它,并且它具有外部修饰符,这对气体消耗有影响,以及该功能应该如何调用。 如果您的契约函数的修饰符或返回值与接口中定义的值不匹配,则会导致编译器给出TypeErrors并且无法编译。

因此,只需使用一个界面 ,就可以告诉其他开发人员有关您的合同所具有的一些功能以及如何使用它们。 简单!

但是这提出了一个问题,没有看看你的合同代码,其他开发者怎么知道你已经使用了给定的接口 ? 这个接口的全部重点是我们不必知道对方的代码库。答案是: ERC165标准 。

ERC165标准

“什么?!? 另一个ERC标准? 这个兔子洞有多深?“

别担心,这是我们将要讨论的唯一一个,而且非常简单 - 它只有一个功能! ERC165标准只是一种检查您的合同指纹是否与任何给定接口的指纹相匹配的方法。 我们来看看整个ERC165标准接口:

 界面ERC165 {  /// @notice查询合同是否实现了一个接口  /// @param interfaceID接口标识符,如  ///在ERC-165中指定  /// @dev接口标识在中指定  /// ERC-165。 该功能使用不到30,000个气体。  /// @如果合约实现了`interfaceID`,@return`true`  ///和`interfaceID`不是0xffffffff,否则为`false` 函数supportsInterface(bytes4 interfaceID)外部视图返回(bool);  } 

因此,您的合同必须有一个函数supportsInterface ,它接受一个表示interfaceID ( bytes4 )的参数,如果该接口受支持,则返回true ( bool),其中interfaceID在ERC165标准中定义为“异或在界面中的所有功能选择器“。

或者用简单的英语,你可以给这个功能任何接口的指纹( interfaceID ),并且它会告诉你它是否与你的任何契约的手指相匹配。

至于获取函数选择器,有两种简单的方法来完成它。 作为一个例子,我将使用前面的balanceOf函数。 为了节省你滚动,它被定义为:

 函数balanceOf(地址_owner)外部视图返回(uint256){  // ...  }; 

我们最终的ERC721合同已经实现了这个功能,这就是我添加花括号的原因,但是当涉及到函数选择器时,它并不重要 - 你会明白为什么。 获取上述函数的函数选择器的两种方法是:

  this.balanceOf.selector 

或手动使用

  bytes4(keccak256( “balanceOf(地址)”)) 

两者都会返回0x70a08231 ,虽然第一个看起来比较干净,但我们偶尔需要第二个,如果接口使用重载函数。 您会注意到函数选择器不关心参数名称,修饰符,可变性,返回值或函数的内容。 只是函数名称和参数类型。 这就是为什么我说这个功能是否被实现并不重要。

但是我们需要interfaceID中的“接口中所有函数选择器的XOR” 。 让我们假设一个接口由三个函数组成: function1() , function2()function3() 。

interfaceID只是:

  interfaceID = this.function1.selector ^ this.function2.selector ^ this.function3.selector; 

很简单! 现在请记住,我们开始进行ERC165讨论的原因是因为我们的ERC721协议需要实现ERC165接口,所以让我们来编写我们的ERC165实现(ERC721协议将继承它)来包装它。

当谈到Solidity时,我们想要减少使用的气体。 做不必要的计算会使用户花费金钱,并浪费网络资源。 ERC165标准实际上要求supportsInterface功能“ 使用少于30,000个气体”。 因此,每次有人调用supportsInterface ,不要重新计算interfaceID,而是让我们支持的接口ID保存在映射中 。

开始我们的合同 , CheckERC165 ,像这样:

 合同CheckERC165是ERC165 { 映射(bytes4 => bool)internal supportedInterfaces; 

这样, supportsInterface函数只需要从映射中返回一个值,下面是整个函数的实现:

 函数supportsInterface(bytes4 interfaceID)外部视图返回(bool){ 返回supportedInterfaces [interfaceID];  } 

大! 我们的合同现在实现了ERC165接口中的所有功能(只有一个)。 让我们将ERC165 interfaceID添加到supportedInterfaces并将此事物带到一个完整的圆圈。

最近发布了Solidity Version 0.4.22,为我们的constructor函数提供了更简单的constructor函数名称。 所以让我们来构造一个构造函数,并在其中添加ERC165接口的interfaceID。

 构造函数()public {  supportedInterfaces [this.supportsInterface.selector] = true;  } 

现在,如果有人使用ERC165标准接口 ( 0x01ffc9a7 )的interfaceID调用supportsInterface ,它将返回true 。

这就是ERC165! 完整的合同可在我的GitHub上找到 。 我们稍后将使用ERC721实现,在处理一般接口时,它也是一个很方便的实现。

ERC721接口

现在我们已经了解了接口,让我们回到ERC721。 您会注意到ERC721标准实际上包含四个不同的接口。 一般ERC721合同的一个主要部分,一个用于可以接收ERC721令牌的合同,另外两个用于增加额外功能的可选扩展。 我们现在将忽略扩展,并快速查看主界面和接收器。

应付职能和可变性

立即对我而言突出的是ERC721接口中的四个功能具有应付修饰符。 即两个safeTransferFrom函数, transferFromapprove 。 每次转移令牌或授予令牌控制权时,ERC721合同总是应付款并没有意义。

你可以想象这种情况可能是这种情况 - 如果你为NFT建立市场,那么毫无疑问你会处理付款 - 但是令牌所有者必须支付的情况只是为了将令牌的控制权交给某人否则很难想象。 事实上, 应付修饰词的原因并不是很性感,这一切都归结为可变性。

从ERC721标准的注意事项部分:

“易变性保证是弱到强: payable ,隐含不付款, viewpure 。”

因此,通过将这些功能标记为可payable ,这仅仅是作者的一种说法,即对所需的可变性没有限制。 在这个特定的例子中, payable只是一种明确表示没有限制的方式。 您的实施可能会更严格,但不会更弱。

有两种方法可以解决这个问题,你可以:

  1. 保持这些功能为可支付的,只需返回任何随事务发送的Ether(或保留它,如果这是您的设计),或者
  2. 删除应付修饰符,但您必须在ERC721 接口副本中执行相同的操作 ,以避免引发TypeError。

从前面记得,函数选择器不受修饰符的影响,所以这不会干扰interfaceID。标记为external功能也是如此,您应该随时根据需要将其更改为public 。

ERC721TokenReceiver

在结束之前,我想快速介绍ERC721TokenReceiver接口。 这不是我们令牌合同需要继承的东西。 顾名思义,它是可以接收ERC721令牌的合同接口。

由于我不会在本系列中介绍制作钱包合约,因此可以快速制作一些虚拟钱包,稍后我们将使用这些虚拟钱包进行测试。 一个有效的接收者和一个无效的接收者。

就我们的目的而言,唯一重要的信息是有效的ERC721TokenReceiver将实现该功能

 函数onERC721Received(地址_from,uint256 _tokenId,字节数据)外部返回(bytes4); 

并返回

 bytes4(keccak256(“onERC721Received(address,uint256,bytes)”)) 

一个无效的将不执行该函数,或者从字面上返回任何其他内容。 所以让我们定义我们的两个接收器如下:

 合同ValidReceiver是ERC721TokenReceiver { 函数onERC721Received(地址_from,uint256 _tokenId,字节数据)外部返回(bytes4){ 返回bytes4(keccak256(" onERC721Received(address,uint256,bytes) ")); } bytes4(keccak256(" onERC721Received(address,uint256,bytes) ")); }  } 

 合同InvalidReceiver是ERC721TokenReceiver { 函数onERC721Received(地址_from,uint256 _tokenId,字节数据)外部返回(bytes4){ 返回bytes4(keccak256(" some invalid return data ")); } bytes4(keccak256(" some invalid return data ")); }  } 

我们不会在很久之后才会使用这些测试,所以请保存它们并放在口袋里。 我只是想在我们对接口进行概述的同时对其进行介绍。

包起来

所以毕竟,你应该熟悉接口,并且有一个ERC165实现,你可以使用它来指示你的合约实现了哪些接口。 我们还介绍了ERC721标准中的可变性保证,并且很快写了一些虚拟钱包合约以供日后测试。

在下一篇文章中,我们将使用到目前为止所介绍的所有内容,并开始编写实际的ERC721令牌合同。

https://medium.com/coinmonks/jumping-into-solidity-the-erc721-standard-part-2-383438734de5

【译】Jumping into Solidity — The ERC721 Standard (Part 2)相关推荐

  1. 【译】Jumping into Solidity — The ERC721 Standard (Part 3)

    到目前为止,在本系列中,我介绍了非易失性和ERC721的基础知识 ,然后介绍了标准接口及其中的一些要求 . 在本文中,我们将对我们的ERC721合同做出一些设计决定,并开始编写它. 贝拉儿NG在Uns ...

  2. 【译】Jumping into Solidity — The ERC721 Standard (Part 4)

    在我上一篇文章中,我们开始编写ERC721合同. 在前三篇文章( 第1部分, 第2部分 , 第3部分 )中有很多序言和解释,所以我会假设你在家中玩耍并直接跳回到代码中. 照片由RémiJacquain ...

  3. 【译】Jumping into Solidity —The ERC721 Standard (Part 1)

    本文不是Solidity的介绍,所以我会假设你知道什么是区块链,以太坊是什么,以及Solidity的基础知识. *(如果你是初学者,请参阅脚注). 在接下来的几篇文章中,我将探索ERC721标准,它是 ...

  4. [译] 标准化的包布局(Standard Package Layout)

    原文地址:Standard Package Layout 原文作者:Ben Johnson 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:steinlib ...

  5. 十一课堂|通过小游戏学习Ethereum DApps编程(4)

    2019独角兽企业重金招聘Python工程师标准>>> 在上篇完结的时候,我们制造出了这个独一无二可爱至极的角色: 这里我们继续总结一些关于solidity语言的知识点.并且开始了解 ...

  6. 非你莫属 java全球排名_TIOBE:2018年5月全球编程语言排行榜

    原标题:TIOBE:2018年5月全球编程语言排行榜 TIOBE 刚刚发布了 5 月编程语言排行榜.Scala 经过长时间的沉淀,本月终于进入了 TIOBE 榜单的前 20 名.Scala 是一种 J ...

  7. TIOBE 6 月编程语言排行榜:Java 放缓,C 复兴了!

    一月一更的 TIOBE 编程语言社区最新发布了 2018 年 6 月排行榜. 和 5 月榜单相比,前十名没有任何变化,依然是 Java.C.C++.Python.C#.Visual Basic .NE ...

  8. TIOBE 5 月编程语言排行榜:暴涨的 C,逆袭的 Scala

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! TIOBE 刚刚发布了 5 月编程语言排行榜. 对比 4 月榜单,这个月的排名并没有太大变化 ...

  9. 计算机考研四大名著,2018考研英语翻译每日一句:四大名著

    考研英语翻译部分在试题中分值占10%,建议同学们还是要重视起来,为自己争取更多的分数.新东方在线考研为大家搜集整理有关社会生活.科普知识.文化教育等方面的相关句子,以此拓展大家的视野.一起来学习吧! ...

最新文章

  1. 显卡玩家の反击!矿难一个月,618集体大战黄牛“降价也不买”
  2. 我在神策做研发 | 成长中的成都研发中心
  3. python如何连接自己电脑服务器_Python远程连接windows服务器并上传数据
  4. 关于通过DDMS向Android系统的模拟器的sdcard中导入mp3文件的问题
  5. C++安全方向openssl(三):3.2 md5算法原理详解以及代码实现
  6. php提交失败阻止提交数据,php – 在刷新浏览器时阻止重新提交提交
  7. 1. OpenMAX系列 —— ACodec和OMX的联系
  8. python求两个字符串之间最小子串
  9. 串口软件与uPs测试,智能化UPS的软件设计及串口通信实现
  10. Java之常见异常 整理集合
  11. php经纬度测距,PHP根据经纬度坐标计算距离
  12. maxscale mysql 主从_MySQL高可用——MaxScale
  13. 算法-3个水桶8升水
  14. android数据格式化,手机格式化了?教你找回安卓手机误删数据
  15. keras求两向量间的余弦值
  16. 【PMP】项目生命周期和开发生命周期
  17. luogu1091合唱队形
  18. PS纳米纤维膜 聚苯乙烯 纤维直径500-2000nm
  19. springboot启动报错Bean with name ‘xxxxService‘ has been injected into other beans
  20. cuDNN: efficient Primitives for Deep Learning 论文阅读笔记

热门文章

  1. 基于Angularjs+jasmine+karma的测试驱动开发(TDD)实例
  2. 如何用极致业务基础平台做一个通用企业ERP系列之二一览表培训
  3. Ajax调试servlet连接失败
  4. TOPAS 命令详解
  5. 2016年春季计算机应用基础,东北师范2016年春季《计算机应用基础》期末考核
  6. 科大星云诗社动态20210125
  7. 科大星云诗社动态20210911
  8. 云炬随笔20180613
  9. 能源15A1,A2燃烧学期末试题2018-01-02
  10. 人工智能学习实战之路