售前客服二维码
文章均源于网络收集编辑侵删
提示:仅接受技术开发咨询!
摘要:本文阐述了硬叉升级前后的燃气成本计算,它将如何随着EIP-2929而改变,以及如何使用EIP-2930引入的访问列表功能。北京时间4月15日下午18:00左右(具体是当以太网的网块高度达到#12244000时),将进行以太网的柏林硬叉升级,此次升级将包括4个新的EIP改进方案,其中2个(EIP-2929和EIP-2930)将影响交易的燃气成本计算。
摘要:本文阐述了硬叉升级前后的燃气成本计算,它将如何随着EIP-2929而改变,以及如何使用EIP-2930引入的访问列表功能。原作者是节拍实验室软件开发人员弗朗哥维多里奥。
注:文章较长,以下是一些要点:
柏林硬叉改变了一些操作码操作码的气体成本。如果你在dapp或智能合同中有一个硬编码的气体值,它们可能会停止工作。如果出现这种情况,并且智能合同不可升级,用户将需要使用访问列表(EIP-2930)来启用它。
访问列表可以用来稍微降低燃气成本,但在某些情况下,它们实际上增加了燃气的总消耗量。
Geth包含一个新的RPC方法(eth\u createAccessList)来简化访问列表的创建。
我们将重点介绍SLOAD和SSTORE操作码,因为它们是受柏林硬分叉影响最大的操作码。我们稍后将讨论以地址为目标的操作码,就像所有EXT*和CALL*操作码一样,因为它们的气体成本也会改变。
如果插槽的值从0更改为1(或任何非零值),则成本为20000;
如果槽的值从1变为2(或任何其他非零值),则成本为5000;
如果槽的值从1(或任何非零值)变为0,则成本为5000,但在交易结束时,您将获得气体退款。本文不详细讨论退款,因为不受柏林硬分叉的影响;
如果该值先前在同一交易中被修改,则所有后续交易的成本为800;
这里的细节有点枯燥,但重要的一点是SSTORE很贵,成本取决于几个因素。
如果该地址或存储密钥先前在事务期间被“使用”,则该地址或存储密钥被认为已经被访问。例如,当您调用另一个合同时,该合同的地址将被标记为已访问。类似地,当您SLOAD或SSTORE某个槽时,它将被视为在事务的剩余部分被访问过。不管哪个操作码完成了:如果一个SLOAD读取一个槽,它将被认为是被访问到下一个SLOAD和SSTORE。
这里需要注意的一点是,存储密钥位于地址“内部”。正如EIP解释的那样:
“在执行事务时,维护一组access _ address 3360 set[address]和access _ storage _ key 3360 set[tuple[address,bytes32]]”,也就是说,当我们说一个存储槽被访问时,我们实际上是指一对(address,storageKey)被访问。
说了这么多,我们来说说新的燃气成本。
如果插槽的值从0更改为1(或任何非零值),则成本为22100(如果存储密钥未被访问)和20000(如果存储密钥被访问);
如果插槽的值从1更改为2(或任何其他非零值),则成本为5000(如果存储密钥未被访问)和2900(如果存储密钥被访问);
如果槽值由1(或任意非零值)变为0,则费用与前一项相同,然后追加退款;
如果该值先前在同一交易中被修改,则所有后续SSTORE的成本将为100;
如你所见,如果之前访问过要修改的槽,那么第一个SSTORE的成本会降低2100气。
下表总结了迄今为止所有已更改的值:
请注意,在最后一行中,谈论插槽是否被访问是没有意义的,因为如果它以前被写入过,就意味着它也被访问过。
但是,如果地址或存储密钥被访问时,燃气成本变低,这是否意味着我们可以将所有内容添加到交易的访问列表中,从而降低燃气成本?不完全是,因为你必须为你添加的每个地址和每个存储密钥支付汽油费。
举个例子吧。假设我们向合同A发送一个事务,访问列表可能如下所示:
如果我们用这个访问列表发送一个事务,使用0x0槽的第一个操作码是SLOAD,那么花费100 gas而不是2100 gas,减少了2000 gas的消耗。但是交易访问列表中包含的每个存储密钥的成本是1900 gas,所以我们只节省了100 gas。(如果访问槽的第一个操作码是SSTORE,那么我们将节省2100 gas,也就是说如果考虑存储密钥的成本,我们总共将节省200 gas。)
这是否意味着我们在使用带有访问列表的事务时,总能节省油耗?事实并非如此,因为我们必须为访问列表中的地址支付煤气费(在我们的示例中是“A”的地址)
访问列表事务对此有何影响?例如,如果我们向合同A发送一个事务,而该合同调用另一个合同B,那么我们可以包括以下访问列表:
我们必须支付2400 gas才能将这个访问列表包含在事务中,但是使用B地址的第一个操作码将花费100 gas,而不是2600gas。所以这样做可以省100个气。如果B以某种方式使用它的存储,并且我们知道它将使用哪些密钥,我们也可以将它们包含在访问列表中,并为每个密钥保存100/200 gas(取决于第一个操作码是SLOAD还是SSTORE)。
但我们为什么要谈另一份合同?我们打电话的合同怎么了?我们为什么不这样做?
我们可以这样做,但不值得,因为EIP-2929规定被叫合同地址(即tx.to)始终包含在accessed _ addresses列表中,所以只会浪费2400气。
让我们再次分析上一节中的示例:
除非我们包含多个存储密钥,否则这实际上是一种浪费。如果我们假设一个SLOAD总是首先使用一个存储密钥,那么我们至少需要24个存储密钥来实现收支平衡。
显然,分析和创建这样的访问列表是没有意义的。幸好我们有更好的办法。
也就是说,它为您提供了一个将在交易中使用的地址和存储密钥列表,以及如果包含访问列表将消耗的气体。(而且,和eth_estimateGas一样,这是一个估计值,在实际交易过程中列表可能会发生变化。)
我想,随着时间的推移,我们会找到执行这个操作的正确方法,我的伪代码猜测是:
“引入EIP-2929是为了降低合同被破坏的风险,因为交易可以预先指定并支付交易计划访问的账户和存储槽。所以在实际实现中,SLOAD和EXT*操作码只需要100个gas,已经够低了。它不仅能防止EIP造成的损害,还能“激活”任何因1884年EIP事件而停滞不前的合同这意味着,如果合同承担了执行某些操作的成本,天然气成本的增加可能会导致合同失败。例如,一个合同调用另一个合同(例如,某个其他合同。有些函数{gas: 34500}())因为它假设一个函数恰好使用34500 gas,那么它将被中断,但是如果在事务中包含了一个适当的访问列表,那么契约将再次工作。
如果你想自己测试这些EIP,你可以复制这个报告,它有几个例子可以用Hardhat和geth执行。有关说明,请查看自述文件。
相关信息:
1.EIP-2929和EIP-2930
2.EIP-2930依赖于柏林硬分叉的另一个组成部分:EIP-2718;
3.EIP-2929引用了大量的EIP-2200,所以如果你想知道更多的天然气成本,你应该从EIP-2200开始。
4.比较气体使用变化的更复杂的例子;
文章均源于网络收集编辑侵删
提示:仅接受技术开发咨询!