Jason chen

Posted on Apr 11, 2022Read on Mirror.xyz

web3的世界一片蛮荒-详解ERC721A

写下这篇文章的原因是今天看到了最主流的协议之一ERC721改进版的ERC721A,该协议可以使得mint多个NFT时的gas费大量降低数倍,这是一个很棒的改进方式,但与此同时我感叹web3的世界一片蛮荒,因为它仅仅将之前需要for循环mint的方式改为了批量mint,这样一个看似极其微小甚至是理应如此的优化却可以解决掉每次mint多花费的数千元,可见web3的基础设施建设差到一片蛮荒,web3基建蕴含着大量的机会等待挖掘。

首先ERC721是什么?是当前月交易额达到35亿美金的NFT最常用的标准协议,它定义了一种以太坊不可分割的、具有唯一性的token交互和流通的接口规范,在该规范下NFT具有以下特性:

目前绝大多数NFT的合约代码都遵循该协议,该协议中对于铸造NFT是调用_safeMint函数来实现,需要传入的参数有2个分别为“接收者地址”和“token id”。

如下图所示,表示给合约调用者msg.sender铸造一个编号为1的token。

那如果我允许用户一次可以mint多个NFT该如何处理?使用for循环遍历要mint的数量_mintAmount,并在第二个参数传入已经产生的NFT数量+1,已经产生的数量使用totalSupply方法来获取。

看到这里其实问题已经显现了,为什么这么麻烦需要遍历还要不断的调用获知已经产生的数量,其实这在web2中也没太大关系不过就是运行效率低一些,但在web3则会导致产生大量的gas费,web3的所有写入操作都需要gas费,意味着每循环一次就要缴纳一次gas费,如果用户要mint多个NFT,这个成本将非常高昂,尤其是新项目开启mint时会产生的gas war,gas费可能飙升数十倍。

要知道NFT月交易额已经达到35亿美金,每天有大量的项目在上线,作为最流行的标准协议,居然一直存在这个问题,每天会有多少web3的用户白白浪费了gas费,又会有多少web2的用户望着高昂的成本被阻挡在外面。

ERC721A提供了一种解决方案,将_safeMint的传入的第二个参数从token id变为mint数量,从而即使一次mint多个NFT交易费用也会和仅mint一个相差无几,具体效果可见下图:

我亲测后确实比使用传统的ERC721降低了10倍的gas费。

那这背后是如何实现进行批量mint的呢?我们先来看一下传统的ERC721中_safeMint的实现逻辑。

先进行来两次校验,分别是地址是否有效和token id是否已经存在,然后使用_beforeTokenTransfer进行转账,从0地址将token id转至对应地址。然后维护两个全局mapping分别为_balances和_owners将地址持有数量+1和将token id指向地址。

下图为ERC72A的_safeMint,其使用的数据结构假设每个用户mint的token id是连续的,所以每次批量mint都只会记录用户第一个mint出来的token id。

如ABC三个地址分别进行了mint,A拥有1、2、3号NFT,B拥有4、5号NFT,C只拥有6号,则相当于记录A1,2,3,B4,5,C6,2、3、5不会存储持有人,因为会认为A至B中间的2和3是A的,B至C中间的5是B的,而传统的ERC721则会将每个id都记录对应的持有人。

下图为ERC721A查询token id持有人的方法,可以看到先传入了一个id,对该id进行递减直到找到某个id持有人,于是就认为该持有人也是传入id的持有人。

确实要承认ERC721A会为广大用户减少大量gas费,避免gaswar,对于web3市场的繁荣是一大利好,从侧面也可以看出这样基础的、常用的功能却经历了如此之久才被更新,可见web3蕴藏的大量荒地等待被开拓,那么你们在参与web3浪潮中都遇到了什么认为不完美的地方呢?欢迎交流探讨,感兴趣可添加微信交流:cj350306878,请备注姓名、公司与来意,谢谢。

其他文章:

Web3