ERC721:全生命周期精析,妈妈再也不用担心我不会玩NFT合约啦

由于篇幅有限,本博客将围绕ERC721核心展开介绍,文章内容尽量做到通俗易懂,但其中不可避免地可能涉及一些新手不友好的概念,您可以查阅相关博客做进一步了解,本系列博客也会不断扩充、提升及优化,尽量做到不留死角,人人都能上手Solidity标准开发。

0. ERC 是什么鬼?

ERC 全称 Ethereum Request For Comment (以太坊意见征求稿), 是以太坊上应用级的开发标准和协议(application-level standards and conventions),为以太坊开发人员提供了实施标准,开发人员可以使用这些标准来构建智能合约。

ERC 的雏形是开发人员提交的EIP(Ethereum Improvement Proposals),即新的ERC标准提案,一旦其得到以太坊委员会的批准并最终确定,新的ERC便由此诞生。

1. 初识 ERC 721

ERC 721 是同质资产 NFT 的 API 标准,提供了资产铸造、转移、归属查询、授权第三方转移等资产花费的实用接口。本文将按照 NFT 资产从诞生到历经多种不同方式的流转、最后再到被销毁这一整个生命周期,逐一介绍 ERC721 标准核心接口的含义及开发示例。由于作者经验有限,欢迎广大读者批评指正。

2. NFT 资产跌宕起伏的一生

2.0 ERC721 自画像

ERC721 合约 Github 链接

ERC721 总共包含四个私有映射,分别记录 NFT 的所有者、特定地址拥有的 NFT 数量、可代表 NFT 所有者操作的第三方、以及特定地址是否授权某个第三方作为操作代表。

ERC721 的核心方法是铸造、销毁、和流转。其中流转包括两种方式,安全的流转要求在接收地址是合约的情况下,接收合约实现了处理该 NFT 资产的相关接口,以免 NFT 永久的锁在接收合约中。

ERC721 共有五个查询函数,分别基于前面提到的几个映射,返回NFT 的所有者、NFT是否存在(即是否属于某个非 0 地址)、特定地址拥有的 NFT 数量、可代表 NFT 所有者操作的第三方、以及特定地址是否授权某个第三方作为操作代表。

ERC721 与授权相关的函数共有两个,分别是为特定 NFT 设置第三方操作代表和授予/取消特定地址作为所有者全部 NFT 资产的操作权限。

除此之外, ERC721 中还有几个实用函数,他们分别用于检查 NFT 资产的操作者是否具备操作权限、检查接收合约是否实现处理 NFT 资产的相关接口、以及清除可代表 NFT 所有者操作的第三方。

最后,还要介绍一下 ERC721 中的三个核心事件,他们分别标志着 NFT 资产的转移、特定 NFT 资产第三方操作的授权、 以及特定地址下所有 NFT 资产第三方操作的授权。

2.1 敲开我的蛋壳,给我找一个新家吧~

NFT 通过 _mint 函数铸造,这是一个仅可供内部调用的函数。调用时需要指定 NFT 的新家地址,以及 NFT 的专属 ID 编号(就像身份证号一样哟)。

铸造 NFT 资产的首要条件是不能将这个新铸造的 NFT 资产发往 0 地址,因为只有销毁的 NFT 资产才会被发往 0 地址。

其次是不能重复铸造已经存在的 NFT 资产,如果允许重复铸造,那么某地址拥有的 NFT 资产就会变成多人共有财产,这可不是 NFT 所有者想看到的场面。

以上两个条件都通过后,新生的 NFT 资产就会飞往它的新家,也就是被发到它所有者的地址中,相应地,其所有者拥有的 NFT 数量会增加 1 。

最后,触发一个 Transfer 转账事件,表明一个新生的 NFT 从 0 地址去往新家啦 ~

下图是调用 _mint 函数铸造一个 NFT 的实例,这是一个 public 函数,因为添加了 onlyMinter 修饰符,因此仅 minter 可以调用,该修饰符实现在合约ERC721Mintable中,后续会增加相应的文章对其进行详细介绍。

2.2 检查一下,新生的 NFT 资产送货到家了嘛?

2.2.1 任何人都能通过查 NFT 所有者的方式进行检查

任何人都能输入 NFT 的 ID , 使用 ownerOf 函数查询特定的 NFT 资产当前归属地址。如果该 NFT 未被铸造(即属于 0 地址),您将无法查询它的归属,否则,该函数会返回查询 NFT 资产的所有者地址。

2.2.2 这个内部方法将返回特定 NFT 是否正在流通中

该方法会检查特定 NFT 的所有者地址是不是 0 地址,如果不是,返回 true,表示该 NFT 正在流通中。

2.3 NFT 资产财富窥探器

如果您想快速了解自己或任何地址拥有的 NFT 数量,仅需调用 balanceOf 函数,并传入您想了解的地址即可。

该函数要求传入的地址是非 0 地址,并通过查 _ownedTokensCount 映射的方式,返回特定地址拥有的 NFT 数量。

2.4 让你花我的 NFT,是爱你的表现吗?可能是我懒吧~

2.4.1 我是小气鬼,先授权你花一个

任何人都可以调用 approve 函数允许其他地址花费自己特定的 NFT 资产。该函数首先检查传入 NFT 的所有者,确保不会有无聊的人授权自己花费自己的资产,接着会检查调用该函数进行授权的地址是否是该 NFT 的所有者或有操作权限的第三方,因为没有人希望自己的 NFT 资产被莫名的授权给任何人花费。

以上两个条件通过后,该 NFT 的操作权(花费权)就被正式地赋予传入地址啦~

最后,授权事件 Approval 触发,表明一个 NFT 的第三方操作权限发生变更 ~

2.4.2 TA 真的授权给我花 TA 其中的一个 NFT 了吗?

任何人都可以调用 getApproved 函数检查特定 NFT 允许被哪个地址花费。传入 NFT 资产的 ID ,该函数会返回授权花费的地址,如果返回 0 地址,则代表该 NFT 未授权任何地址花费。

2.4.3 我是土豪,我的就是你的,全让你花

任何人都可以调用 setApproveForAll 函数授权或撤销其他地址花费自己所有的 NFT 资产的权力。该函数首先要求传入地址不与调用地址相同,然后通过映射 _operatorApprovalForAll 保存授权状态,如果要授权特定地址花费调用者所有的 NFT 资产,传入授权地址和 true 即可,反之传入要撤销授权的地址和 false。

最后,批量授权事件 ApprovalForAll 触发,表明特定地址持有的全部 NFT 的第三方操作权限发生变更 ~

2.4.5 TA 真的为我倾尽所有了吗?

任何人都可以调用 isApprovedForAll 函数检查特定地址持有的全部 NFT 对第三方地址的花费授权状态。传入持有地址和第三方地址即可,返回 true 代表授权花费,反之表示未授权花费。

2.5 流通吧!NFT

2.5.1 随意地发起一笔 NFT 转移

2.5.1.1 转移入口

任何人都能通过调用 transferFrom 函数发起一笔 NFT 转移,参数分别是 NFT 的转出地址、转入地址,和 ID 。该函数首先会通过 _isApproveOrOwner 函数检查发起者是否具备转移该 NFT 的资格,如是,则通过内部函数 _transferFrom 实现 NFT 转移。

2.5.1.2 转移条件

该内部函数首先通过前面介绍过的 ownerOf 函数获得特定 NFT 的所有者,然后检查转出该 NFT 的地址是否是该 NFT 的所有者,或有操作该 NFT 权力的第三方(授权方式见2.4.2、2.4.3),如是,返回 true,表示允许转移。

2.5.1.3 转移执行

该函数要求被转移的 NFT 必须从其所有者地址处转出,并且转入一个非 0 地址。

满足以上两个条件,首先调用内部函数 _clearApproval 将有权操作该 NFT 的第三方清除,然后通过修改映射 _ownedTokensCount 的方式将转出地址的 NFT 数量 -1 、转入地址的 NFT 数量 +1 ,接着将该 NFT 的所有者地址设为转入地址,最后触发一个转账事件,表明一个流通中的 NFT 去往新家啦 ~

2.5.1.4 权限清除

由于 NFT 的所有权发生变更,其所属的操作授权方也应该重置。下图函数为一个流通中的 NFT 资产实现操作授权方的重制功能,被授权地址设为 0 地址则表示没有任何地址有权限操作该 NFT 资产。

2.5.2 安全地发起一笔 NFT 转移

2.5.2.1 沉默寡言式安全转移

安全转移总共有两种实现方式,调用的分别是两个同名函数,区别是是否传入转账说明。下图这个函数仅需传入转出地址、转入地址、和 NFT 的 ID 即可。该函数会传入一个空字符串作为转账说明,自动调用另一个需要传入转账说明的安全转移函数。

2.5.2.2 啰哩啰嗦式安全转移

接上节,安全转移函数最终会走一遍 2.5 中的流程,不同的是会在流程的最后检查一下接收地址是否是一个合约地址,如是,判断其是否实现了处理 NFT 的接口(见下节),如未实现,则交易回滚。这么做的目的是避免 NFT 资产被意外地永久锁定在某个合约当中。除此之外,附带的转账说明只用作触发事件中的参数之一(见下节),是一个可选参数,可有可无。

2.5.2.3 安全转移的安检规则

首先,该函数调用 isContract 函数判断转入地址是否是一个合约,判断方式是看该地址的 size 是否大于0,如是则说明其是一个合约,函数的实现方式详见 2.5.2.3.1,具体的实现原理请参考这个链接。

如果转入地址不是合约,正常转入即可,返回 true;

如是,则该函数会尝试从接收合约取一个返回值(详见 2.5.2.3.3),放在变量 retval 中,该值会跟自己合约中存储的 _ERC_RECEIVED (详见 2.5.2.3.2)做对比,如果相同,则返回 true ,代表转入合约实现了 NFT 资产的处理方法,NFT 资产可以放心地转入而不必担心被意外锁定。

2.5.2.3.1 iscontract 函数实现方式

【实现合约的github链接】

2.5.2.3.2 _ERC_RECEIVED 是什么鬼

2.5.2.3.3 宣告全世界我能接受 NFT

合约源码

下图是一个可接收 NFT 资产的合约示例,合约部署时初始化 _retval 和 _reverts 两个参数,前者的值类似 2.5.2.3.2 ,后者为 false ,表示该合约能够接收 NFT 资产。当 _reverts 为 false 时,onERC721Received 函数返回 _retval 的值,供 _checkOnERC721Received 函数做比较,如果等于 2.5.2.3.2 中的值,转账正常进行,否则会滚该转账交易。

2.6 垃圾回收

不再需要的 NFT ,不能卖废品换钱,只能转让给 0 地址。(突然很想知道拥有这么多“废弃 Token”的 0 地址的财富值到底有多少)。ERC721 实现了两个仅供内部调用的 _burn 函数实现 NFT 回收。

第一个 _burn 函数只需传入 NFT 的 ID ,它会把传入的 NFT 资产的所有者地址一起传给第二个 _burn 函数以执行回收操作。


第二个 _burn 函数需要指定 NFT 资产的所有者地址和资产 ID。函数首先判断传入的 NFT 资产所有者是否正确,接着清除该 NFT 的授权操作方,详见2.5.1.4,然后将该 NFT 资产所有者拥有的 NFT 数量 -1,最后将该 NFT 资产的所有者地址设为 0 地址并触发一个 Transfer 转账事件。

下图是调用 _burn 函数回收一个 NFT 的实例,这是一个 public 函数,但仅可供传入 NFT 资产的所有者或有权第三方调用【合约实现的Github链接】。

至此,NFT 的从铸造、到流转、授权第三方消费及回收等全流程接口实现都已介绍完毕,你学会了嘛~

ERC721:全生命周期精析,妈妈再也不用担心我不会玩NFT合约啦相关推荐

  1. 妈妈再也不用担心别人问我是否真正用过redis了

    1. Memcache与Redis的区别 1.1. 存储方式不同 1.2. 数据支持类型 1.3. 使用底层模型不同 2. Redis支持的数据类型 3. Redis的回收策略 4. Redis小命令 ...

  2. 妈妈再也不用担心我的macbook发烫了计划2.0Beta mac发热

    mac 发热 解决 妈妈再也不用担心我的macbook发烫了计划2.0Beta 贴吧好多小朋友反应Macabook看视频发热严重,Flash发热当热严重了,没事正很正常,中国这群无良厂商迟迟不改,看看 ...

  3. 妈妈再也不用担心我词穷了

    老听人们说"高端大气上档次"你有木有想过这句话的下一句是什么? 才华横溢的网友们纷纷出手接了下去半句,你来感受一下这些"高端大气上档次"的下半句 . 高端大气上 ...

  4. Java实现印刷体转手写体—妈妈再也不用担心我被罚抄作业了

    Java实现印刷体转手写体-妈妈再也不用担心我被罚抄作业了 文章目录 Java实现印刷体转手写体-妈妈再也不用担心我被罚抄作业了 缘起 开始开发 测试效果 开源地址和总结 郑重声明 因本文中涉及到爬虫 ...

  5. python绘制横向柱状图 妈妈再也不用担心我不会画图了

    python绘制横向柱状图 妈妈再也不用担心我不会画图了 前言 实现代码 成果 前言 事情要从一次画图开始说起 当我开开心心搞到一堆数据,以为能够休息的时候,这时候我突然想起来,是不是绘制成柱状图更直 ...

  6. 计算机管理怎么给硬盘重新合区,一分钟学会磁盘合区,妈妈再也不用担心!

    原标题:一分钟学会磁盘合区,妈妈再也不用担心! 自从上一篇文章<一分钟搞定电脑磁盘分区,再也不求人!>中小编讲到了,日常生活中我们的电脑该如何区分区,留言区就有小伙伴问我,怎么把D盘的容量 ...

  7. ERC1155: 批发小能手,妈妈再也不用担心网络拥堵造成的gas费飙升啦

    ERC1155: 批发小能手,妈妈再也不用担心网络拥堵造成的gas费飙升啦 Hello - 大家好,首先感谢大家对本系列前两篇文章

  8. 致小白:详解调幅收音机的原理 #妈妈再也不用担心我不懂收音机啦!

    标题:致小白:详解调幅收音机的原理 #妈妈再也不用担心我不懂收音机啦! 作者: Pleiades_Antares 出品: BDF元培调查组-北京市内包小组 版权声明:本作系完全原创,他人不得在原作者不 ...

  9. 妈妈再也不用担心我的公式写不出来了:一款公式输入神器实测

    本文推荐一个公式输入神器,只要截图就能识别公式,手写的公式都能识别.经过实测,几乎没有识别不出的公式,并可以输入到word.markdown.latex文件. 一.前言 写论文.博客,技术文档,公式输 ...

最新文章

  1. 如何在sqlserver数据库表中建立复合主键
  2. javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
  3. MySQL数据类型及范围用法一览表
  4. 下列哪个滤波器是非线性的_数字图像处理复习题(选择题及相应答案)
  5. 【转】dicom通讯的工作方式及dicom标准简介!!
  6. python中def root的用法_python scipy optimize.root_scalar用法及代码示例
  7. 利用建站快速软件包:XAMPP,构建基于winodws平台快速搭建PHP的数据库应用- kimai - 团队时间记录
  8. ai电磁组属于什么组_星巴克的“气氛组”究竟是一个什么样的神秘组织?
  9. js获取时间(本周、本季度、本月..)
  10. Tachyou alluxio初识
  11. 你可能不知道Flutter到底有多火
  12. 网易邮箱已经变成无限空间了
  13. html页面布局实验原理,Html设计实验报告.doc
  14. The Sandbox 的 OliveX Fitness 之城来啦!
  15. Oracle-表的创建与管理
  16. 错误 C4996 ‘scanf‘: This function or variable may be unsafe. Consider using scanf_s instead.
  17. uniapp使用百度语音识别语音转文字
  18. 进门985,出来专科生!“醉生梦死”的大学生啊,醒醒吧!
  19. 红米手机拍照效果测评(对比小米2A)
  20. 给定三边判断是否是直角三角形

热门文章

  1. matlab gain使用,matlabgain模块
  2. 全球与中国小龙虾市场深度研究分析报告
  3. 美国计算机专业修什么课程,美国计算机研究生需要的先修课程有哪些?
  4. 火爆全网的ChatGPT上手体验,文尾免费送账号!
  5. win8.1 android sdk,Android sdk 秒退 win8解决思路
  6. win10系统 鼠标放在开始或者任务栏就一直转圈圈
  7. scheme 微博_新浪微博 URL Scheme 收集
  8. matlab 向量_MatLab简易教程 #4.向量、矩阵操作命令
  9. 第十二届蓝桥杯嵌入式——赛后总结
  10. G2:一个由纯 javascript 编写、强大的语义化图表生成工具