广告

ERC721模板比较

最流行的ERC721模板比较

除了最近的宏观经济事件导致市场略微看跌外,我认为我们可以确信我们仍处于 NFT 牛市的中间。

在这轮牛市中,每周都有数百个项目推出,其中大部分都是类似的智能合约。由于在这个领域几乎所有的东西都是开源的,因此很容易实施被证明有效的解决方案。

然而,这导致项目复制粘贴当前流行的少数NFT智能合约模板,而没有真正理解每个实施中存在的不同的优缺点。

为了在一定程度上消除这种混乱,有必要研究一下最流行的模板,检查每种模板的优缺点,并尝试得出一些关于不同类型项目的最佳合约的结论。

ERC721和ERC721Enumerable

NFT起源于EIP-721不可替代代币标准提议。这个几乎每个人都使用的提案的OG实现是由OpenZeppelin完成的。

ERC721提供的功能很快被证明是不够的,许多项目开始采用ERC721Enumerable扩展。该扩展通过在合约中添加所有代币ID的可枚举性,以及检查帐户拥有的所有代币ID的方法,来增强原始ERC721的功能。

然而,这就是我们开始遇到麻烦的地方。ERC721Enumerable的问题是,它做了很多不必要的事情,导致了gas成本的上升,给社区造成了数百万美元的损失。

ERC721Enumerable可以优化读取函数,但不利于写入函数。

ERC721Enumerable使用了大量的冗余存储,这不仅提高了代币的铸造成本,而且也提高了代币的转账成本。

ERC721Enumerable.sol

这些是状态修改函数,在每次更新或转账发生时执行。

我们可以清楚地看到ERC721Enumerable不是一个理想的选择,不应该再被大多数项目使用。

幸运的是,一些聪明的开发人员已经注意到了这些效率低下的问题,并设计了解决方案。

优化的 ERC721Enumerable

建议大家阅读整篇文章,熟悉解决方案,这个合约的基本前提是,它把优化的重心翻转过来,把写入函数的成本优化为读取函数的成本。这很好,因为如果读取函数在链下被调用 ,那么它们不会花费我们的钱。背后的基本原理ERC721Enumerable可以访问以下三个函数:totalSupply、tokenByIndex和tokenofOwnerByIndex。

我们可以忍受这些函数的低效率和无限循环,因为它们几乎总是在链下被调用。

这个实现首先用一个数组替换ERC721中的_balances和_owners映射。

优化的 ERC721Enumerable by Chance

_mint函数更改为:

偶然优化的 ERC721

ERC721Enumerable中的视图函数更改为:

tokenOfOwnerByIndex的循环是非常低效的,但这也无伤大雅,因为它几乎总是在链下被调用,因此是免费的。

提醒一句

如上所述,上面的版本还删除了_balances数组,从而减少了额外的存储写入操作。因此,balanceOf函数循环遍历整个owners数组,以确定地址的余额。这又是一个非常低效的读取操作,然而,与tokenOfOwnerByIndex相反,我可以想象有几十种情况需要在链上检查地址的余额。

例如,通过MetaMorphies,我们已经在开发NFT质押池,一个治理系统,其中以代币所有权授予投票权,以及一个移动增强现实应用程序。这个复杂系统的各个部分将检查链上的余额,所以它必须是高效的。

即使你不想挂载任何其他合约,如果你的mint函数允许一个地址在铸币之前检查它所拥有的代币数量,就应该小心。对于最初的几位矿工来说,这可能是件好事,但对于第8756位矿工来说,这将是一场灾难。

当涉及到高价值的操作时,盲目地复制粘贴代码是不可取的。一个解决方案在其作者的案例中完美地工作并不意味着它将自动应用到我们项目的特殊需求。

代理和批准

Chance建议的另一个优化是预先批准OpenSea代理注册合约,以转移代币,并允许基础合约所有者在未来可以将任何其他合约挂载到基础合约,并在isApprovedForAll中自动为其返回为true。

这个解决方案在很多方面都存在严重的问题:

  • 如果Open Sea代理注册表被破坏了怎么办

  • 如果已安装的合约受到损害怎么办

  • 如果基础合约的所有者决定采取行动,并从合约中拿走所有代币,该怎么办

  • 如果基础合约所有者的钱包被盗怎么办

实施此模式后,如果发生上述任何一种情况,攻击者就可以从每个所有者那里获取所有的NFT。这只会导致更多的攻击向量和信任假设,而节省20美元的批准交易成本,却有损失数百万美元价值的潜在风险。

优化是一件非常好的事情,但还有更高级的东西,这是区块链和加密领域的基本前提:构建无需信任的系统。

ERC721A

另一个非常聪明,而且最近非常流行的解决方案是由Chiru Labs开发的ERC721A合约。让我们看看在这个智能合约中发生了什么。

ERC721A的基本前提是能够以铸造单个 NFT的成本铸造多个 NFT。让我们看看都做了哪些优化,以及合约是如何工作的。

根据开发团队的描述,第一个优化是去除ERC721Enumerable引入的冗余存储,类似于Chance的做法。

第二,第三优化的是每个批次铸币请求更新一次所有者的余额和代币所有权数据。

for循环被移除,因此ERC721A兑现了它的承诺,以铸造单个 NFT的成本铸造多个 NFT。

但这引发了多个问题:合约如何存储代币ID和所有权数据?如何确定代币的所有权?如何代币转账?

ERC721A存储

ERC721A利用两个结构和两个映射来存储所有权数据。

ERC721A 结构

看这些名字,就可以了解其用途。TokenOwnership使用单个存储槽来存储关于代币所有权的一些信息,AddressData使用单个存储槽来存储关于铸币人地址的信息。

ERC721A所采用的方法乍一看似乎是反直觉的,所以让我们来看看在不同操作期间如何写入和读取存储以达到合约的正确状态。

假设我们是从合约中创建的第一个地址,并且我们铸造了10个代币。在这种情况下,会发生以下情况:

图 1:ERC721A 中的 Mint 操作

在我们的批处理中,第一个ID是0,因此合约为了代币ID和时间戳而使用批处理大小和tokenownership结构来配置AddressData结构。其余代币ID的数据为空。那么我们如何确定所有权呢?这不是问题吗?

要理解为什么不是,让我们看看合约如何确定代币的所有权。

图 2:在 ERC721A 上调用 ownerOf()

让我们假设这个操作遵循上一个铸造10个代币的操作。我们感兴趣的是代币ID为3的所有者,因此我们调用ownerOf(3)。ownerOf(3)]处的槽是空的,所以函数移动到前面的ID。直到找到一个具有所有权地址的代币为止。

但是如果我将代币ID为0的转移到另一个地址会发生什么呢?我的所有代币都带有空数据吗?在这种情况下,如何确定所有权?让我们看看_transfer函数内部发生了什么。

图 3:ERC721A 中的 _transfer()

当代币转账时,代码检查下一个代币是否设置了所有者,如果没有,就将from地址设置为所有者。我们知道,代币ID是在造币时按升序分配的,因此如果一个地址铸造了多个代币,如果所有权数据没有初始化,它也必须拥有下一个代币。

当检查ERC721A合约时,我的第一个想法是它确实为批量铸造保持了低成本,但它在ownershipOf中有一个讨厌的循环,并且每次发生代币转移时它都会调用ownershipOf。这似乎是一种可以反咬用户一口的东西。

ERC721A 中的 _ownershipOf

这确实是一个合理的担忧。为了说明这些成本会增加多少,让我们想象一个不现实的场景,在一个交易中铸造350个代币,然后检查代币ID为330的所有权并进行转账。(getOwner函数是一个简单的函数,它调用ownerOf,然后将一些内容写入存储,以说明任何写入函数调用的成本)。

ERC721A 的gas估算

在2708美元/ETH和70 gwei/gas的价格下,检查所有权和转移ID为 330 的单个代币的成本高于铸造 350 个代币。这是因为_ownershipOf中的循环从330变为0,并且每个SLOAD操作都要消耗gas。

如果我们再次铸造350代币,但转移代币ID 1 而不是 330,则数字看起来会有很大的不同。

ERC721A 的gas估算

我们会阻止任何人从我们的合约中铸造那么多代币。假设我们限制最大的批量大小为10个。如果有人铸造了10个代币,然后试图转移ID为9的代币,数字是这样的:

ERC721A 的gas估算

因此,根据正在转账的代币ID,检查其所有权,gas成本可能会有很大的差异。

对于许多考虑实施该合约的项目来说,这可能会破坏交易。一方面,如果你把批量的大小限制在一个小的数量,这可以节省很多钱且是有效的。我认为大多数集合都有一个有限的批量大小,假设是10个,所以对大多数人来说,这应该不是问题。

如果不限制批处理大小,就会归结为你是否相信你自己的客户在代币转账之前对智能合约进行了深入的思考,以及是否对你的项目进行了篡改,即单个代币转账会让他们付出巨大的代价。

如果你打算将此合约安装到任何类型的复杂生态系统中,还必须考虑_ownershipOf函数的潜在缺陷。正如我在上面所说的,许多合约(比如质押池)会检查代币的余额和所有权,所以如果在链上调用这些函数,我们的目标应该是使它们高效。

成本比较

最后,让我们进行几次测试,以直观了解每种解决方案的潜在gas成本。下面我们从每个实现中创建1、3、5和10个代币,各5次。Custom721A是我们的ERC721A实现,CustomEnumerable是优化后的ERC721Enumerable, OZEnumerable是Open Zeppelin版本。

铸造一些代币的结果

这些观察结果与我们上面讨论的一致。Open Zeppelin 版本在任何地方都非常昂贵且效率低下。如果你只铸造一个代币,Custom721A和CustomEnumerable的成本大致相同,如果你铸造多个代币,则Custom721A的成本几乎保持不变,并随着CustomEnumerable的循环大小而增加。

现在让我们从上面的假设场景中尝试一下:我们铸造350个代币,然后随机挑选20个代币ID,然后检查所有权并进行转账(ERC721A的已知弱点)。

铸造和代币转账的结果

这与我们之前讨论的是一致的。检查所有权的成本约为ERC721A的5倍,而代币转账的成本约为4倍。

我们还可以清楚地看到,批量铸造正是ERC721A真正的亮点所在。铸造350个代币只需要147美元,而对于CustomEnumerable来说,同样的操作需要11倍以上的成本。但是,在一批铸造350个代币是非常不现实的。

结论:用一个ERC721来统治所有?

那么,你是不是正站在十字路口,使用哪个?我可以很自信地说,这要视情况而定。

本文最重要的一点应该是,当涉及到智能合约时,你必须了解导入到代码库中的所有内容的来龙去脉。请不要盲目地复制-粘贴代码,即使它来自一个非常可靠的来源,因为他们的解决方案可能不适合你正在进行的项目的特定需求。

24小时热点

Payment Gateways , Litecoin (LTC)

Payment Gateways ...

136082

CCFOX

区块链技术主要应用于哪些方面

区块链技术,自比特币首次引入以来,已经从单一的加密货币应用扩 ...

12219

波场区块链浏览器

令牌

计算机术语中“令牌”一词有两个意思: 对用户进行授权的小工 ...

98800

文博数藏

NBC币(Niobium Coin)钱包?

NBC币(Niobium Coin)是一种基于区块链技术的数 ...

1867

区块链网快讯

一文教会怎么注册usdt钱包

想要注册USDT钱包可以选择知名的加密货币,钱包提供商,比如 ...

18521

波场区块链浏览器

区块链平台的搭建步骤详解

随着区块链技术的普及,越来越多的企业和个人对搭建自己的区块链 ...

5317

波场区块链浏览器

TRC20的钱包有哪些?TRC20代币协议详解!

TRC20钱包属于数字货币钱包当中的一种,可以为用户提供比较 ...

37136

波场区块链浏览器

BLZ-Bluzelle-小蓝细胞

货币简介 Bl ...

25462

寻迹藏品

比特币兑换人民币汇率

比特币作为一种全球性的加密货币,其对各种法币的兑换率是投资者 ...

2440

波场区块链浏览器

权益授权证明

DPoS 是一种类似董事会的授权共识机制,该机制让每一个持币 ...

22981

欧易官网苹果APP
广告

热点专题

区块链网是什么

中国区块链价值评价中心 中国区块链价值评价中心于2 ...

5261968

知信链

元界(Metaverse)

元界(Metaverse)是一个去中心化的公有区块链项目,元 ...

958285

WEEX数字货币

BTC123

BTC123(www.btc123.com)成立于2011年 ...

738581

Kusama 测试网

DAC币——达芬奇Davinci Coin

达芬奇项目的平台是通过叫作"Dchain"的自身区块链把可以 ...

690705

Mechanism Capital

Bitfinex(香港B网)

Bitfinex交易平台目前仍处于试运营阶段,该平台由iFi ...

665155

Hi元宇宙

MCO币

MCO,前为Monaco,朝着让每个钱包都载有加密货币的愿景 ...

653940

第九空间

熊猫矿机(PandaMiner)

熊猫矿机(PandaMiner),企业文化背景为:其一,熊猫 ...

634078

金融界区块链频道

陈景润证明哥德巴赫猜想1+2的论文

大偶数表为一个素数及一个不超过二个素数的乘积之和 。 本 ...

605129

鲸探

中币网zb——中币交易所

ZB.com是一个全球化的数字货币交易所,目前已获得泰国和迪 ...

595701

中币交易所

五大区块链骗局揭露

从古至今,骗子这个行当一直都是经久不衰,上至皇宫贵族,下至农 ...

521264

DeRace