How Does Berlin's Hard Fork Affect Gas?
原文来源: ECN 以太坊中文社区

The Berlin Hard Fork was launched on the mainnet on April 14, introducing four EIPs. Two of them (EIP-2929 and EIP-2930) have an impact on the gas cost of the transaction. This article will explain how some of the gas costs were calculated before Berlin, how they changed with the addition of EIP-2929, and how to use the access list introduced by EIP-2930.
The main points of quick reference
Berlin hard fork changes the gas cost of some opcodes. If the value of the gas charge in a dApp or a smart contract is hard-coded, they may break down. If this happens and the smart contract is not updatable, the consumer will need to use the access list of the EIP-2930 to use that part of the opcode.
Access lists can be used to reduce gas costs by a small amount, but they can actually increase total gas consumption in some cases.
Geth has added a new RPC method called eth_createAccessList to simplify the creation of access lists.
Each opcode executed by the EVM has an associated gas cost. Most of them have a fixed cost: PUSH1 always consumes 3 units of gas, MUL consumes 5, and so on. Others vary: for example, the cost of an opcode for SHA3 depends on its input size.
We will focus on the opcodes SLOAD and SSTORE, as they are the ones most affected by the Berlin hard fork. We'll discuss opcodes for addresses later, such as all EXT* and CALL*& NBSP; , because their gas costs have also changed.
Before the EIP-2929, the gas consumption of SLOAD was simple: it always consumed 800 gas. So there is nothing to say.
Sstore is probably the most complex opcode in terms of gas consumption because its cost depends on things like the current value of the storage slot, the new value, and whether it has been modified before. we
Analyze only a few cases to gain a basic understanding; If you want to learn more, please read the EIP link at the bottom of this article.
If the value of storage slot changes from 0 to 1 (or any non-0 value), the gas consumption is 20,000.
If the value of storage slot changes from 1 to 2. (or any other non-zero value), the GAS consumption is 5000.
If the value of storage slot goes from 1 (or any non-0 value) to 0, the gas consumption is also 5000, but you get a gas fee refund at the end of the transaction. Gas fee refunds are not discussed in this article, as they are not affected in the Berlin hard fork.
If the value of storage slot is changed in the same transaction before, the gas consumption for all subsequent sstores is 800.
The details aren't interesting, but the important thing is that the store is expensive, and the cost of it depends on several factors.
EIP-2929 has an impact on the GAS consumption of all of the above opcodes. But before we get into any of these changes, we need to talk about an important concept that this EIP introduced: Accessed addresses and accessed storage keys.
If an address or a storage key has been "used" in a previous transaction, they are considered "accessed." For example, when you CALL a different contract, the address of that contract is marked as "Accessed." Similarly, when you SLOAD or SSTORE some slot, trade it
Part of him will also be considered to have visited. It doesn't matter which opcode executes it: if an SLOAD reads a slot, the following SLOAD and SStores are treated as accessed.
As the EIP explains, "When executing a transaction, maintain a Set of accessed_addresses: Set[Address] and accessed_storage_keys: Set [Tuple [Address, Bytes32]] & have spent"
That is, when we say that a storage slot was accessed, we are actually talking about a pair (address, storageKey) that was accessed.
Prior to the Berlin hard fork, SLOAD consumed a fixed 800 gas. Now, it depends on whether the storage slot has been accessed. If it is not accessed, the gas consumption is 2100; If it has been accessed, it is 100. Therefore, if the slot is in the list of accessed storage keys, the gas consumption of SLOAD will be less than 2000.
Let's review the previous SSTORE example in the context of the EIP-2929:
➤ If the value of a storage slot changes from 0 to 1 (or any non-0 value), the gas consumption is:
If the storage key has not been accessed, 22100
If it's been visited, 20,000
➤ If the value of storage slot changes from 1 to 2; (or any other non-zero value), the GAS consumption is:
If the storage key has not been accessed, 5000
If it's been accessed, 2900
➤ If the value of the storage slot goes from 1 (or any non-0 value) to 0, gas consumption is the same as in the previous case, plus returns.
➤ If the value of storage slot is changed in the same transaction previously, the gas consumption for all subsequent sstores will be 100.
As you can see, if the slot SSTORE is modifying is one that has been previously accessed, the first. Sstore consumes less than 2100 gas.
The following table compares the above values:

Note that in the last line it is not necessary to talk about whether the slot has been accessed, because if it has been written before, it will have been accessed.
EIP-2930: Optional access list transaction
The other EIP-2930 we mentioned at the beginning is the EIP-2930. The EIP adds a new type of transaction, which can include an access list in the transaction. This means that you can declare in advance which addresses and slots should be considered accessed before the execution of the transaction begins. For example, an SLOAD of an unaccessed slot consumes 2100 gas, but the same opcode consumes only 100 gas if the slot is added to the transaction access list.
But if addresses that have already been accessed or stored keys consume less gas, does that mean we can reduce gas consumption by adding everything to the transaction access list? Great! No more gas charges! However, this is not always the case, because you still have to pay gas every time you add an address and store the key.
Let's look at an example. If we are sending A transaction to Contract A, the access list might look like this:

If we send a transaction with this access list attached, the first opcode using slot0x0 is SLOAD, which consumes 100 gas instead of 2100 gas. This is a reduction of 2,000 gas. But each time the storage key is added to the access list of the transaction, 1900 gas is consumed. So we're only saving 100 gas. (If the first opcode to access the slot was SSTORE instead of SLOAD, we would have saved 2100 gas, which is a total of 200 gas if we considered the cost of storing the key.)
Does this mean that we can save gas just by using the transaction access list? No, because we also need to pay to add an address to the access list (i.e. in our example "< <; address of A>" Gas).
So far, we've only talked about opcodes SLOAD&NBSP; And SSTORE, but these are not the only opcodes that have changed after the Berlin upgrade. For example, the fixed consumption before the opcode CALL is 700. However, after EIP-2929, if the address is not in the access list, its consumption becomes 2600, if it is, it is 100. Also, like accessed storage keys, no matter what opcode was accessed before (for example, if EXTCODESIZE is called the first time, that opcode will consume 2600 gas, whereas any subsequent EXTCODESIZE that uses the same address, Both Call and StaticAll cost only 100 Gas).
How does this affect transactions with access lists? For example, if we send A transaction to contract A and that contract calls another contract B, we can add A list like this:

We would have to pay 2400 gas to add this access list to the transaction, but then the first opcode using the B address would only cost 100 gas instead of 2600. So, we saved 100 gas by doing this. If B uses its storage in some way, and we know which keys we use, we can add them to the access list as well, saving 100 to 200 gas per key (depending on whether your first opcode is SLOAD or SSTORE&NBSP;). .
But why are we talking about another contract? What about the contract we're calling? Why not do this with the contract?

We could do this, but it wouldn't be cost-effective, because EIP-2929 explicitly states that the address of the contract being called (that is, tx.to) will be added to the accessed_addresses list by default. Due to the
So we don't need to pay the extra 2400 gas.
Let's review the previous example:

Unless we need to add a few more storage keys, this is actually wasteful. If we preset SLOAD Always use the storage keys first, then we need at least 24 storage keys to break even.
As you can imagine, doing analysis and manually creating an access list isn't all that fun. Fortunately, there's a better way.
eth_createAccessList RPC method
Geth (as of version 1.10.2) adds a new eth_createAccessListPC method that you can use to generate access lists. Its use is associated with eth_estimateGas Similar, but instead of a gas estimate, it returns something like the following:

That is, it gives you the list of addresses and storage keys used for the transaction, plus the gas consumed if the access list is added. (like & have spent ETH_ESTIMATECATEGAS, which is an estimate, the list may change when the transaction is actually mined. However, this does not mean that the gas consumption is lower than that of sending the same transaction without access to the list!
I think we'll find the right way to use it over time, but my guess is that the pseudocode is as follows:

It's worth noting that the primary purpose of accessing the list is not to use GAS. As explained by EIP:
"Mifies the risk of contract breakage introduced by EIP-2929, because transactions can specify and prepay for accounts and storage slots that are accessed by the trading plan; finally, in actual execution, the opcodes SLOAD and EXT* consume only 100 gas: This low gas consumption not only prevents breakages caused by the EIP, but also "unwinds" any contracts that are limited by the EIP-1884."
This means that if a contract makes an assumption about the cost of performing a transaction, an increase in the cost of gas could shut it down. For example, one contract calls another contract, like this. SomeOtherContract. SomeFunction {34500} gas: (), because it assumes that the someFunction will consume 34500 gas accurately, so that it will be a problem. But if you add a reasonable list of accesses, the contract will work again.
If you want to test it yourself, copy the code base with multiple instances that can be executed with HardHat and Geth. Check the instructions at README.
EIP-2929 and EIP-2930 are the two Berlin hard fork EIPs related to this article.
The EIP-2930 relies on another part of the Berlin hard fork: EIP-2718, also known as Type Transaction.
The EIP-2929 references a lot of the EIP-2200, so if you want to dig deeper into gas costs, you can start there.
If you want to see a more complex example of comparing GAS usage changes, see here.
The original link
Welcome to join the official BlockBeats community:
Telegram Subscription Group: https://t.me/theblockbeats
Telegram Discussion Group: https://t.me/BlockBeats_App
Official Twitter Account: https://twitter.com/BlockBeatsAsia