# ERC721R功能解析

By [xinba](https://paragraph.com/@netmeta) · 2022-04-12

---

几天前我曾在群里与大家探讨目前NFT存在的问题，其中我提到目前购买者在NFT市场处于弱势方，在一级市场被项目方操盘玩弄于股掌之中，二级市场又依赖于项目方真正做事而不是卷款跑路，并推演了一个理想的模型：

![](https://storage.googleapis.com/papyrus_images/86b7ec28eb1ce49f8b8d4f4c0ee14e00b3f136534aa18ceb44da4f328939d77a.png)

当时推演出的模型是一级市场的mint过程要保证绝对公平，二级市场则需要让项目方确保拿到的钱真正的去兑现roadmap而不是卷款割韭菜，所以首先项目方不可以将mint后的钱直接进行提款，毕竟账上躺着价值数百上千万的资产，只需要动动手指头就可以提到个人账户，这种诱惑很难有人抗拒，其次项目方的提款需要用在正道上，即去实现roadmap里的承诺，要知道用户花钱买的不是项目方的jpg，而是这张jpg后的权益与故事，用户在买的那一瞬间是透支了项目方未来的时间。

我认为NFT市场应该是一个良币驱逐劣币的市场，若实现以上的模型，如果项目方不用，则用户会认为项目方心虚从而不买，继而倒逼项目方使用更健康的模型，最终形成正循环净化整个市场。

今天看群里有人提到新出来的一个ERC721R协议，有点上文中聊到的意思，故我们来分析分析它实现了什么，又是怎么实现的。

![](https://storage.googleapis.com/papyrus_images/156f7da719cc64caed0e0e7e9280746bce685810ae8d87f98c2100ffe1282c95.png)

我们可以看到媒体报道说它允许铸造者进行退款，即以前你在淘宝买到假货只能认栽，现在你可以7天无理由退款。

我们打开ERC721R的官网[https://erc721r.org/，可以看到其slogen是为NFT创造者带来巨大的责任感，所以它是制约了项目方的权利从而要求项目方认真做事，否则用户会把到了你兜里的钱取回来。](https://erc721r.org/%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E5%85%B6slogen%E6%98%AF%E4%B8%BANFT%E5%88%9B%E9%80%A0%E8%80%85%E5%B8%A6%E6%9D%A5%E5%B7%A8%E5%A4%A7%E7%9A%84%E8%B4%A3%E4%BB%BB%E6%84%9F%EF%BC%8C%E6%89%80%E4%BB%A5%E5%AE%83%E6%98%AF%E5%88%B6%E7%BA%A6%E4%BA%86%E9%A1%B9%E7%9B%AE%E6%96%B9%E7%9A%84%E6%9D%83%E5%88%A9%E4%BB%8E%E8%80%8C%E8%A6%81%E6%B1%82%E9%A1%B9%E7%9B%AE%E6%96%B9%E8%AE%A4%E7%9C%9F%E5%81%9A%E4%BA%8B%EF%BC%8C%E5%90%A6%E5%88%99%E7%94%A8%E6%88%B7%E4%BC%9A%E6%8A%8A%E5%88%B0%E4%BA%86%E4%BD%A0%E5%85%9C%E9%87%8C%E7%9A%84%E9%92%B1%E5%8F%96%E5%9B%9E%E6%9D%A5%E3%80%82)

可以看到他们列出的4点优势也是重点在强调项目方跑路的问题，30天内项目方没有做事可以退款。

![](https://storage.googleapis.com/papyrus_images/2f6dfce253d715f394a0e8add30c6be8217faf403889a9199da2276fb2659425.png)

在QA中提到项目方在退款期间是无法将mint资金提出来的，其次他也为项目方进行了解释，即说哎呀你们如果是个正经项目方肯定也不会需要mint完就立马将钱提出来，所以放几天也没关系，言下之意就是你不用我的协议那就是心里有鬼，良币驱逐劣币。

![](https://storage.googleapis.com/papyrus_images/91df420ddf1ff9cc91e19bfd1b1fd1fcc80a1fd1c002b688f5cb63aee153e839.png)

理念都挺好的，接下来我们看看他们的代码具体是怎么实现上述过程的，我们进入他们的github主页[https://github.com/exo-digital-labs/ERC721R](https://github.com/exo-digital-labs/ERC721R)

可以看到更详细的描述，说是在原有的721和1155协议上新增了退款功能。

![](https://storage.googleapis.com/papyrus_images/190b86906b42ab16764684b895aa0c27e088a06e67840049bfb7f61f4621ba23.png)

对于工作原理的描述，用户交的钱先到了智能合约（721、1155也本身就是这样的），然后有个锁定期，这个期间项目方不能提款，但是用户可以退款。

![](https://storage.googleapis.com/papyrus_images/d5fc681efc81bb047cd8ecf48fde4660254adb290511b320de9bcb65f80d841f.png)

这是它的示例代码，我来带大家一起拆解一下。

![](https://storage.googleapis.com/papyrus_images/c20cda27987e219c683dc638bcd71233b6cc2899d01c49bd69675a2f7c31b920.png)

首先定义了锁定期refundPeriod并默认45天，当然项目方也可以自己改。

然后定义了构造函数，默认提款账号为合约部署者，

![](https://storage.googleapis.com/papyrus_images/50e61f7aba1dc71e42ae1611916e2efc43ba29bb11a0cd02635200bbcffb2059.png)

并调用了一个时间计算的函数，即获取当前合约部署的时间再加上锁定期就是最终项目方可以提款的日期。

![](https://storage.googleapis.com/papyrus_images/8acef8d8db11a6e711b3d3f4319a1c4c69726204af0059d41161b31100bda13a.png)

这个函数是用来校验是否处于锁定期的，在下文用户退款的操作中会用到。

然后我们看一下核心的退款操作，用户输入自己要退款的对应token id，因为是数组格式可以退多个NFT，然后合约首先用刚才说到的校验函数来判定是否处于锁定期，若处于的话用户就可以从里面退款，然后用for循环遍历用户输入的token id，并逐个校验是否真的属于当前用户，若属于的话则调用transfer函数将用户的NFT还给项目方。然后再计算出应该退还给用户多少钱，即用户退的NFT数量乘以mint价格，然后再调用第三方合约的sendValue把钱打给用户。

![](https://storage.googleapis.com/papyrus_images/1a99479d5f7e15dcd4c73a591c22de0031993fe26a1096222f30c83d132cc789.png)

这是正常的项目方提款函数，这里加了个校验是否达到了锁定时间，如果没达到就不能执行函数，

![](https://storage.googleapis.com/papyrus_images/b7d090a3c9e140d91889098376d36bebdd6c48218c5b4fb8b7c45129ae668e70.png)

总结一下，721R对于721、1155等协议的主要改动在于2点：

*   提款函数多加了一层时间校验，没有到时间不能提款，从而限制项目方
    
*   新增了一个给用户退款的函数。
    

全程代码量不超过30行，其次也没有像721A在底层进行封装，只在最上层的mint合约代码中进行了修改，所以先定性：它不属于协议，或它达不到协议的层次。

其次因为都是在上层合约里改，所以治标不治本，且不说项目方会不会在里面把一些限制去掉，当然去了后代码一开源也会被大家识破，不过到了这里你们是否有发现一个漏洞？

还记得上文中提到的退款时，给用户退的钱是NFT数量乘以mint价格，但是mint价格是参数呀，只要是参数就可以改的，如果我mint时的价格是1eth，mint完项目方把价格改成0eth，那我退了个寂寞...而且这个过程在用户退款前是不会被发现的。

所以我们来跑一下代码试试看这样做可不可行。

我将价格设置为1eth，然后mint了5个。

![](https://storage.googleapis.com/papyrus_images/61f19a6580d9ac63fb2789e01bff8c3475ddd93f24344fcc3f9251ffe130c3c0.png)

此时我的余额为94.99（测试网初始100）

![](https://storage.googleapis.com/papyrus_images/502dc188011838c9d2a646e272c49fd46dce8b06fbd74d556d5b7af709605a9b.png)

然后我将id为1的NFT进行退款。    

![](https://storage.googleapis.com/papyrus_images/5efdbb98fa07cfd80634f7bf49e7c82fe9451e3b7e44f4f1dfe5fee669628671.png)

执行完成后我的余额多了1eth。

![](https://storage.googleapis.com/papyrus_images/4e04f70a4276f42b800b5e70ff9f48aa42ec1d88d7459b1656b9a17eb6bdf170.png)

那么此时假设我作为一个毫无良知道德败坏只想着割韭菜的项目方我肯定要想办法搞点破坏是吧，我把价格改成0，我让你们退。

然后我再退id为2的NFT试试看。

![](https://storage.googleapis.com/papyrus_images/2791ba114c0fbfc3cd034010d02d01e55e58b3f63e824fb6b40bfbf1d3ac6398.png)

NFT是退回去了，但是余额没有变化.....

![](https://storage.googleapis.com/papyrus_images/f15018661ad446493f15ae53d2027ca0196bcc4226d66f663923e391680dcc07.png)

所以如果要解决这一点也非常依赖于项目方的自觉性，不要改价格，或者直接把价格写成常量压根不能改，大家也不要一听到有项目方使用了ERC721R就冲，还是要认真看一看代码，到底有没有给你们埋坑。

综上所述，ERC721R是当今NFT市场的一股清流，他指出了这个市场的弊端，真正站到了用户的角度去考虑，并提出了一种切实可行的解决方案，不过这套方案并不是那么的完美，依然有大量需要完善补充的地方，但这并不妨碍他成为这个市场敢于说真话的吹哨人（这么说会不会太过誉了）。

web3的世界现在还一片蛮荒，有大量的土地等待我们开垦，ERC721R开了一个好头，后面需要我们做的事情还很多。

---

*Originally published on [xinba](https://paragraph.com/@netmeta/erc721r)*
