织梦CMS - 轻松建站从此开始!

我的网站

当前位置: 主页 > 竞争币

搞懂 “柏林” 之后的合约Gas开销(2)

时间:2021-04-18 16:35来源:未知 作者:admin 点击:
注意:存储项的键是“内在于”某些地址中的,一如该EIP所解释的: 执行事务时,保持一个集合:accessed_addresses:Set[Address]以及accessed_storage_keys:Set[Tuple[A

注意:存储项的键是“内在于”某些地址中的,一如该EIP所解释的:

执行事务时,保持一个集合:accessed_addresses:Set[Address]以及accessed_storage_keys:Set[Tuple[Address,Bytes32]]

也就是说,当我们说某个存储槽已被访问过了,我们的实际意思是:(address,storageKey)已被访问过了。

搞清楚了这个概念,我们来谈谈新的Gas消耗量计算模式。

“柏林”以后的SLOAD

升级前,SLOAD的Gas消耗量是固定的800。但升级后,Gas消耗量要看这个存储槽是否已经被访问过。还没访问过的,消耗量就是2100 gas;访问过的,就是100 gas。所以,如果某个存储项槽已经在“已访问过的存储项键`的集合里了,就可以省掉2000 gas。

“柏林”以后的SSTORE

我们逐个逐个对比下,在EIP-2929实施后,上面的几个例子会发生什么样的变化:

如果存储项的值从0改为1(或者任意非零的值),Gas消耗量是20000

如果该存储项键还未访问过,消耗22100 gas

若已访问过,消耗20000 gas

如果存储项的值从1改为2(或者任意非零的值),Gas消耗量是5000

如果该存储项键还未访问过,消耗5000 gas

若已访问过,消耗2900 gas

如果存储项的值从1(或任意非零的值)改为0,消耗量保持不变,gas返还机制也不变

在一笔事务中,如果存储项已不是第一次修改,则后续每一次SSTORE都消耗100 gas

由此可见,如果某个槽此前已访问过,则对它的第一次SSTORE操作会节约2100 gas(相比于从未访问过)。

汇总一下

EIP-2930:可选“访问清单”的事务类型

另一个“柏林”升级包含的EIP是2930。该EIP加入了一种新的类型的事务,可以在事务的负载中包含一个“访问清单”,意思是,你可以在事务执行前就声明哪些地址和存储槽应被认为是“访问过的”。举个例子,对一个未访问过的槽执行SLOAD需要耗费2100 gas,但如果该存储槽被包含在了事务的“访问清单”中,则操作的消耗量机会降为100 gas。

但如果只要地址和槽被当成“已访问过的”就可以降低操作的Gas消耗量;而访问清单可以把地址和槽标记为“已访问过的”;那岂不是说我们可以把这些东西都放在访问清单中,来获得Gas消耗量的减免?真棒,天赐Gas!

额,并不完全如此,因为你每添加一个地址或存储项键,都要支付额外的Gas。

举个例子。假如我们要向合约A发送了一条事务。

这是不是说,每次使用访问清单我们都能节省gas呢?很遗憾,也不是,因为在访问清单中填入地址也需要支付gas。(也就是我们示例中的"<address of A>")

访问过的地址

迄今为止,我们只讨论了SLOAD和SSTORE操作码,但“柏林”升级还改变了别的操作码。举个例子,CALL操作码原来的Gas消耗量为固定的700,但2929实施后,如果所调用的地址不在访问清单中,消耗量将提高到2600;如果在,则降低为100。而且,就像访问过的存储键一样,到底哪个操作码访问过那个地址并不重要(比如,如果用户最先调用的是EXTCODESIZE,这一个操作的消耗量是2600,但后续的调用,只要是对同一个地址的,无论是EXTCODESIZE、CALL还是STATICCALL,都只消耗100 gas。 (责任编辑:admin)

织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
推荐内容