这里值得注意的是,存储密钥是“内置于“一些地址的。就如这份EIP所解释: 在执行交易时,维持一组accessed_addresses:Set[Address]和accessed_storage_keys:Set[Tuple[Address,Bytes32]] 也就是说,当我们说一个存储slot被访问了,我们实际上说的一对(address,storageKey)被访问了。 接下来谈谈新的gas消耗。 柏林后的SLOAD 在柏林硬分叉之前,SLOAD固定消耗800 gas。现在,它取决于该存储slot是否被访问过。如果它没有被访问过,gas消耗是2100;如果被访问过了,则是100。因此,如果该slot是在访问过的存储密钥列表里的,SLOAD的gas消耗会少于2000。 柏林后的SSTORE 让我们在EIP-2929语境下重温前面的SSTORE例子: 如果存储slot的值从0变成1(或任何非0的值),gas消耗量是: 如果存储密钥没有被访问过,22100 如果被访问过了,20000 如果存储slot的值从1变成2(或任何其他非0的值),gas消耗量是: 如果存储密钥没有被访问过,5000 如果被访问过了,2900 如果存储slot的值从1(或任何非0的值)变成0,gas消耗与上一种情况一样,再加上返还。 如果存储slot的值在之前相同的交易中被修改了,往后所有SSTORE的gas消耗量都是100。 如你所见,如果SSTORE正在修改的slot是之前被访问过的,第一个SSTORE消耗少于2100 gas。 总结 请注意,在最后一行没有必要谈论slot是否已经被访问过,因为如果它之前就被写入,那它就被访问过了。 EIP-2930:可选访问列表交易 我们一开始提及的其他EIP就是EIP-2930。这份EIP增加了一种新的交易类型,它可以在交易里加入一个访问列表。这意味着你可以在交易执行开始前,事先声明哪些地址和slot应被视为访问过的。例如,一个未被访问过的slot的一个SLOAD需要消耗2100 gas,但如果该slot被加入到交易访问列表里,同一个操作码只需消耗100 gas。 但如果已经被访问过的地址或存储密钥会消耗更少gas,这是否意味着我们可以把所有东西都添加到交易访问列表来降低gas消耗了?棒!不用给gas费了!然而,不尽然是这样,因为你每次添加地址和存储密钥的时候还是需要支付gas费的。 我们来看一个例子。假如我们正在向合约A发送一笔交易,如果我们发送一笔附有这个访问列表的交易,使用slot 0x0的第一个操作码是SLOAD,它消耗的是100而不是2100 gas。这减少了2000 gas。但每次把存储密钥添加到交易的访问列表中都需要消耗1900 gas。因此我们只省了100 gas。(如果访问该slot的第一个操作码是SSTORE而不是SLOAD,我们可以省2100 gas,也就是说如果我们考虑的是存储密钥的消耗的话,我们总共节省200 gas。) 这是否代表只要我们使用交易访问列表就能节省gas?不是的,因为我们还需要支付添加地址到访问列表(即我们的例子中的"<address of A>")的gas。 (责任编辑:admin) |