以太坊今日将完成柏林硬分叉升级,这些知识点你需要了解
在北京时间4月15日下午18:00左右(具体是以太坊网络区块高度达到#12244000时), 以太坊 的柏林(Berlin)硬分叉升级将会发生,这次升级将纳入4个新的EIP改进提案,而其中两个(EIP-2929和EIP-2930)将会影响交易的gas成本计算。
本文解释了在这次硬分叉升级前后的gas成本计算,这将如何随EIP-2929而发生改变,以及如何使用EIP-2930引入的访问列表功能,原文作者是Nomic Labs软件开发者Franco Victorio。
注:文章篇幅较长,以下是其中的一些要点:
-
柏林硬分叉改变了一些opcode操作码的gas成本。如果你在dapp或智能合约中有一个硬编码的gas值,它们可能会停止工作。如果发生这种情况,并且智能合约是不可升级的,则用户将需要使用访问列表(EIP-2930)来启用它。
-
访问列表可用于稍稍降低gas成本,但在某些情况下,它们实际上会增加gas消耗总量。
-
geth包含了一个新的RPC方法(eth\u createAccessList)来简化访问列表的创建。
1 柏林硬分叉前的gas成本
EVM执行的每个opcode操作码都有一个相关的gas成本。对于大多数操作码而言,这个成本是固定的:PUSH1总是消耗3个单位的gas,MUL则消耗5个单位的gas,等等。而对于其他操作码来说,它是可变的:例如,SHA3操作码的成本取决于其输入的大小。
我们将重点讨论SLOAD和SSTORE操作码,因为它们是受柏林硬分叉影响最大的操作码。我们稍后将讨论那些以地址为目标的操作码,就像所有的 EXT*和CALL*操作码,因为它们的gas成本也会发生变化。
柏林硬分叉之前的SLOAD
如果没有EIP-2929,SLOAD的成本很简单:它总是会消耗800 gas。
柏林硬分叉之前的SSTORE
就gas而言,SSTORE可能是最复杂的操作码,因为它的成本取决于存储slot的当前值、新值以及它是否以前被修改过。我们将只分析一些场景以获得基本的理解。如果你想了解更多,请阅读本文末尾链接的eip。
-
如果slot的的值从0更改为1(或任何非零值),则成本为20000;
-
如果slot的的值从1更改为2(或任何其他非零值),则成本为5000;
-
如果slot的的值从1(或任何非零值)更改为0,则成本也为5000,但在交易结束时你将获得gas退款。这篇文章中,我们不会详细讨论退款,因为它们不受柏林硬分叉的影响;
-
如果以前在同一事务中修改了该值,则所有后续sstore的成本为800;
这里的细节有些枯燥,重要的一点是,SSTORE是非常昂贵的,其成本取决于几个因素。
2 实施EIP-2929之后的gas成本
EIP-2929改变了所有这些值,但在此之前,我们需要先谈谈这个EIP引入的一个重要概念:已访问地址和已访问存储密钥。
如果地址或存储密钥以前在交易期间被“使用”,则该地址或存储密钥就被视为已访问。例如,当你调用另一个合约时,该合约的地址会被标记为已访问。类似地,当你SLOAD或SSTORE某些slot时,它将被视为在交易的其余部分已被访问。不管是哪个操作码做的:如果一个SLOAD读取了一个slot,那么它将被认为对接下来的SLOAD以及SSTORE都是已访问的。
这里需要注意的一点是,存储密钥位于某个地址的“内部”。正如EIP所解释的:
“执行事务时,维护一组accessed_addresses: Set[Address] 和 accessed_storage_keys: Set[Tuple[Address, Bytes32]]”
也就是说,当我们说一个存储slot被访问时,我们实际上是说一对(address, storageKey)被访问了。
话虽如此,我们还是来谈谈新的gas成本吧。
柏林硬分叉之后的SLOAD
在柏林硬分叉之前,SLOAD的固定成本是800 gas,现在,这取决于是否已访问了存储slot。如果未访问,则成本为2100 gas,如果已访问,则成本为100 gas。因此,如果slot在已访问的存储密钥列表中,则一次SLOAD的成本会降低2000 gas。
柏林硬分叉之后的SSTORE
让我们在部署EIP-2929的环境下回顾一下之前的SSTORE示例:
-
如果slot的值从0更改为1(或任何非零值),则成本为:22100(如果未访问存储密钥),20000(如果已访问存储密钥);
-
如果slot的值从1更改为2(或任何其他非零值),则成本为:5000(如果未访问存储密钥),2900(如果已访问存储密钥);
-
如果slot的值从1(或任何非零值)更改为0,则成本与上一项相同,然后加上退款;
-
如果以前在同一交易中修改了该值,则所有后续SSTORE的成本为100;
如你所见,如果要修改的slot以前被访问过,那么第一次SSTORE的成本将降低2100 gas。
下面的表总结了目前为止所有改变的值:
请注意,在最后一行中,谈论是否访问了slot是没有意义的,因为如果它以前被写入过,则表明其也被访问过。
3 EIP-2930
我们在文章开头提到的另一个EIP就是EIP-2930,这个改进提案添加了一种新类型的事务,该事务可以在事务负载中包括访问列表。这意味着你可以在事务开始执行之前预先声明哪些地址和slot应被视为是已访问的。例如,一个未访问slot的SLOAD成本为2100,但是如果该slot包含在事务的访问列表中,则相同的操作码成本就为100。
但是,如果当地址或存储密钥已被访问时,gas成本变更低了,这是否意味着我们可以将所有内容添加到事务的访问列表中并降低gas成本呢?不完全是这样,因为你还需要为添加的每个地址和每个存储密钥支付gas。
让我们看一个例子,假设我们正在向合约A发送一笔交易,访问列表可能如下所示:
如果我们用这个访问列表发送了一笔交易,并且第一个使用0x0 slot的操作码是SLOAD,则它将花费100 gas(而不是2100 gas),这就降低了2000 gas的消耗量。但事务访问列表中包含的每个存储密钥的成本为1900 gas,所以我们只省了100 gas。(如果访问该slot的第一个操作码是SSTORE,那么我们将节省2100 gas,这意味着如果考虑到存储密钥的成本,我们总共将节省200 gas。)
这是否意味着我们在使用带有访问列表的交易时总是能节省gas消耗?并非如此,因为我们还要为访问列表中的地址支付gas成本(在我们的示例中是"
")
已访问地址
以上,我们只讨论了SLOAD和SSTORE操作码,但这些并不是柏林硬分叉之后唯一改变的操作码。例如,原先调用操作码的固定成本为700 gas。但是在实施EIP-2929之后,如果地址不在访问列表中,则开销就是2600 gas,但如果是在已访问列表中,则开销就是100 gas。而且,与已访问存储密钥一样,之前访问该地址的操作码并不重要(例如,如果先调用EXTCODESIZE,则该操作码将花费2600 gas,使用相同地址的任何后续EXTCODESIZE、CALL、STATICCALL将花费100 gas)。
这是如何受到访问列表交易的影响的?例如,如果我们将一笔交易发送至合约A,而该合约调用另一个合约B,那么我们可以包含如下访问列表:
我们必须支付2400 gas的费用才能将这个访问列表包含在交易中,但是第一个使用B地址的操作码将花费100 gas(而不是2600gas)。所以我们这样做就节省了100 gas,如果B以某种方式使用它的存储,并且我们知道它将使用哪些密钥,那么我们还可以将它们包括在访问列表中,并为每个密钥节省100/200的gas(取决于第一个操作码是SLOAD还是SSTORE)。
但我们为什么要谈另一个合约呢?我们调用的合约怎么了?我们为什么不这样做?
我们可以这样做,但这是不值得的,因为EIP-2929指定了被调用的合约地址(即tx.to)总是包含在accessed_addresses列表中,因此这只会白白浪费2400 gas。
让我们再次分析上一节的示例:
这实际上是浪费,除非我们包含多个存储密钥。如果我们假设一个SLOAD总是首先使用一个存储密钥,那么我们至少需要24个存储密钥才能实现收支平衡。
显然,分析并创建这样的一个访问列表是没有意义的。幸运的是,我们有更好的方法。
4 eth_createAccessList RPC方法
Geth(从1.10.2版本开始)包含了一个新的eth\u createAccessList RPC方法,其可以用来生成访问列表。它的用法类似于eth_estimateGas,但它不是用于估算gas,而是返回如下内容:
也就是说,它为你提供了该交易将使用的地址和存储密钥的列表,以及如果包含访问列表,则会消耗的gas。(而且,与eth_estimateGas一样,这是一种估计值,在实际进行交易时,列表可能会更改。)
我想,随着时间的推移,我们会发现执行此操作的正确方法是什么,而我的伪代码猜测是:
5 激活合约
必须要指出的是,访问列表的主要目的不是使用gas,正如EIP所解释的:
“ EIP-2929 所引入的是减轻合约破坏风险,因为交易可预先指定和支付交易计划访问的帐户和存储slot。因此,在实际执行中,SLOAD和EXT*操作码只需要100 gas,这已经足够低了,它不仅可防止因该EIP而导致的破坏,还可以“激活”由于EIP 1884而卡住的任何合约。”
这意味着,如果一个合约对执行某些操作的成本做出假设,那么gas成本的增加可能会导致它无法工作。例如,一个合约调用另一个合约(例如someOtherContract.someFunction{gas: 34500}())因为它假设某个函数正好使用34500 gas,那么它就会中断,但如果在事务中包含适当的访问列表,那么合约将再次工作。
如果你想自己测试这些EIP,你可以复制这个repo,它有几个可使用Hardhat和geth执行的示例。有关说明,请查看README文件。
来源:巴比特资讯(ID:bitcoin8btc)
==
和11万人同时接收最新行情资讯
搜“鸵鸟区块链”下载
和2万人一起加入鸵鸟社群
添加微信ID:tuoniao02
Bitcoin Price Consolidates Below Resistance, Are Dips Still Supported?
Bitcoin Price Consolidates Below Resistance, Are Dips Still Supported?
XRP, Solana, Cardano, Shiba Inu Making Up for Lost Time as Big Whale Transaction Spikes Pop Up
XRP, Solana, Cardano, Shiba Inu Making Up for Lost Time as Big Whale Transaction Spikes Pop Up
Justin Sun suspected to have purchased $160m in Ethereum
Justin Sun suspected to have purchased $160m in Ethereum