ERC721:全生命周期精析,妈妈再也不用担心我不会玩NFT合约啦
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合约啦相关推荐
- 妈妈再也不用担心别人问我是否真正用过redis了
1. Memcache与Redis的区别 1.1. 存储方式不同 1.2. 数据支持类型 1.3. 使用底层模型不同 2. Redis支持的数据类型 3. Redis的回收策略 4. Redis小命令 ...
- 妈妈再也不用担心我的macbook发烫了计划2.0Beta mac发热
mac 发热 解决 妈妈再也不用担心我的macbook发烫了计划2.0Beta 贴吧好多小朋友反应Macabook看视频发热严重,Flash发热当热严重了,没事正很正常,中国这群无良厂商迟迟不改,看看 ...
- 妈妈再也不用担心我词穷了
老听人们说"高端大气上档次"你有木有想过这句话的下一句是什么? 才华横溢的网友们纷纷出手接了下去半句,你来感受一下这些"高端大气上档次"的下半句 . 高端大气上 ...
- Java实现印刷体转手写体—妈妈再也不用担心我被罚抄作业了
Java实现印刷体转手写体-妈妈再也不用担心我被罚抄作业了 文章目录 Java实现印刷体转手写体-妈妈再也不用担心我被罚抄作业了 缘起 开始开发 测试效果 开源地址和总结 郑重声明 因本文中涉及到爬虫 ...
- python绘制横向柱状图 妈妈再也不用担心我不会画图了
python绘制横向柱状图 妈妈再也不用担心我不会画图了 前言 实现代码 成果 前言 事情要从一次画图开始说起 当我开开心心搞到一堆数据,以为能够休息的时候,这时候我突然想起来,是不是绘制成柱状图更直 ...
- 计算机管理怎么给硬盘重新合区,一分钟学会磁盘合区,妈妈再也不用担心!
原标题:一分钟学会磁盘合区,妈妈再也不用担心! 自从上一篇文章<一分钟搞定电脑磁盘分区,再也不求人!>中小编讲到了,日常生活中我们的电脑该如何区分区,留言区就有小伙伴问我,怎么把D盘的容量 ...
- ERC1155: 批发小能手,妈妈再也不用担心网络拥堵造成的gas费飙升啦
ERC1155: 批发小能手,妈妈再也不用担心网络拥堵造成的gas费飙升啦 Hello - 大家好,首先感谢大家对本系列前两篇文章
- 致小白:详解调幅收音机的原理 #妈妈再也不用担心我不懂收音机啦!
标题:致小白:详解调幅收音机的原理 #妈妈再也不用担心我不懂收音机啦! 作者: Pleiades_Antares 出品: BDF元培调查组-北京市内包小组 版权声明:本作系完全原创,他人不得在原作者不 ...
- 妈妈再也不用担心我的公式写不出来了:一款公式输入神器实测
本文推荐一个公式输入神器,只要截图就能识别公式,手写的公式都能识别.经过实测,几乎没有识别不出的公式,并可以输入到word.markdown.latex文件. 一.前言 写论文.博客,技术文档,公式输 ...
最新文章
- 如何在sqlserver数据库表中建立复合主键
- javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
- MySQL数据类型及范围用法一览表
- 下列哪个滤波器是非线性的_数字图像处理复习题(选择题及相应答案)
- 【转】dicom通讯的工作方式及dicom标准简介!!
- python中def root的用法_python scipy optimize.root_scalar用法及代码示例
- 利用建站快速软件包:XAMPP,构建基于winodws平台快速搭建PHP的数据库应用- kimai - 团队时间记录
- ai电磁组属于什么组_星巴克的“气氛组”究竟是一个什么样的神秘组织?
- js获取时间(本周、本季度、本月..)
- Tachyou alluxio初识
- 你可能不知道Flutter到底有多火
- 网易邮箱已经变成无限空间了
- html页面布局实验原理,Html设计实验报告.doc
- The Sandbox 的 OliveX Fitness 之城来啦!
- Oracle-表的创建与管理
- 错误 C4996 ‘scanf‘: This function or variable may be unsafe. Consider using scanf_s instead.
- uniapp使用百度语音识别语音转文字
- 进门985,出来专科生!“醉生梦死”的大学生啊,醒醒吧!
- 红米手机拍照效果测评(对比小米2A)
- 给定三边判断是否是直角三角形
热门文章
- matlab gain使用,matlabgain模块
- 全球与中国小龙虾市场深度研究分析报告
- 美国计算机专业修什么课程,美国计算机研究生需要的先修课程有哪些?
- 火爆全网的ChatGPT上手体验,文尾免费送账号!
- win8.1 android sdk,Android sdk 秒退 win8解决思路
- win10系统 鼠标放在开始或者任务栏就一直转圈圈
- scheme 微博_新浪微博 URL Scheme 收集
- matlab 向量_MatLab简易教程 #4.向量、矩阵操作命令
- 第十二届蓝桥杯嵌入式——赛后总结
- G2:一个由纯 javascript 编写、强大的语义化图表生成工具