You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a storage slot is set to a non-zero value and then restored to zero within the same transaction (0→X→0 pattern), the following are added to `refund_counter` (a single, un-dimensioned counter):
181
+
When a storage slot is set to a non-zero value and then restored to zero within the same transaction (0 to X to 0 pattern), the state gas and regular gas refunds are handled separately:
182
182
183
-
- State gas: `32 × cost_per_state_byte`(the state creation charge)
- State gas: `32 × cost_per_state_byte`is refunded directly to `state_gas_reservoir` (and `execution_state_gas_used` is decremented). The refund happens immediately at the X to 0 SSTORE, not via `refund_counter`. This ensures the full state gas amount is returned regardless of the 20% refund cap.
184
+
- Regular gas: `GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS`is added to `refund_counter`, subject to the 20% cap.
185
185
186
-
The net cost after refund is `GAS_WARM_ACCESS` (100), consistent with pre-[EIP-8037](./eip-8037.md)`SSTORE` restoration behavior. Refunds use `refund_counter` rather than direct gas accounting decrements, so that reverted frames do not benefit from the refund.
186
+
The net cost after refund is `GAS_WARM_ACCESS`, consistent with pre-[EIP-8037](./eip-8037.md)`SSTORE` restoration behavior.
187
187
188
188
### State gas on frame failure
189
189
190
190
State gas is deducted at the point of the operation (`CREATE`, `CALL` to new account, EOA delegation). If the frame subsequently reverts or halts, the deduction is not undone within that frame — but the parent reclaims the child's consumed state gas via the reservoir restoration described above. At the top level, the same restoration applies: all consumed execution state gas (from the reservoir and any spillover from `gas_left`) is moved back into the `state_gas_reservoir`, and `execution_state_gas_used` is reset to zero. In both cases, state gas is refunded because state changes are reverted and no state was actually grown. This departs from pre-[EIP-8037](./eip-8037.md) behavior where `GAS_NEW_ACCOUNT` was consumed on revert, but is more consistent with the principle that state gas exclusively pays for long-term state growth.
191
191
192
-
#### [EIP-2780](./eip-2780.md) authorizations
192
+
###State gas refund on CREATE failure
193
193
194
-
For [EIP-7702](./eip-7702.md) authorizations, the intrinsic state gas assumes account creation for each authorization: `(112 + 23) × cost_per_state_byte` per authorization. When an authorization targets an existing account (no account creation needed), the `112 × cost_per_state_byte` portion is refunded to `state_gas_reservoir` and subtracted from `intrinsic_state_gas` during authorization processing, before state changes begin. The `intrinsic_state_gas` adjustment is required so that `tx_state_gas = intrinsic_state_gas + execution_state_gas_used` does not double count the refunded gas.
194
+
`CREATE`/`CREATE2` charges `112 × cost_per_state_byte` upfront (pay-before-execute). If the creation fails at the opcode level before a child frame is entered — silent failures such as insufficient balance, nonce overflow, stack depth limit, or address collision — the account creation state gas is refunded to `state_gas_reservoir` (and `execution_state_gas_used` is decremented). No account was created, so no state gas should be paid. This preserves the pay-before-execute model while ensuring state gas is only consumed when state is actually created. Child frame revert and exceptional halt are handled by the general frame failure rule above.
195
+
196
+
### State gas refund on same-tx SELFDESTRUCT
197
+
198
+
When an account is created and self-destructed in the same transaction ([EIP-6780](./eip-6780.md)), the state does not persist. At the end of the transaction, when the actual account and storage removal occurs, all state gas for that account is refunded to `state_gas_reservoir` (and `execution_state_gas_used` is decremented). The refund scope includes:
199
+
200
+
- Account creation: `112 × cost_per_state_byte`
201
+
- Created storage slots: `32 × cost_per_state_byte` per non-zero slot
202
+
- Code deposit: `len(code) × cost_per_state_byte`
203
+
204
+
This refund must be applied before `tx_gas_used_before_refund` is computed so the sender is not charged for state that was destroyed. Storage slots that were restored to zero during execution (0 to X to 0) already have a final value of 0 and are not counted, avoiding a double refund with the SSTORE restoration refund.
205
+
206
+
### CALL with value to the selfdestructed account in the same transaction
207
+
208
+
When an account is created and then selfdestructed in the same transaction ([EIP-6780](./eip-6780.md)), deletion is deferred to the end of the transaction. During the transaction the account is still present in the state with a nonce of 1 from the CREATE, and is therefore neither empty nor nonexistent. A subsequent `CALL` with value to that address does **not** trigger a new account creation and therefore does **not** charge `GAS_NEW_ACCOUNT` state gas.
209
+
210
+
The end of the transaction destruction still removes the account regardless of any value received after the SELFDESTRUCT, so no persisted state results from the CALL. Any value transferred is burned when the account is destroyed. Combined with the same transaction SELFDESTRUCT refund above, the net state gas across the CREATE, SELFDESTRUCT, and CALL with value lifecycle is zero, matching the zero persisted state.
211
+
212
+
#### [EIP-7702](./eip-7702.md) authorizations
213
+
214
+
For [EIP-7702](./eip-7702.md) authorizations, the intrinsic state gas assumes account creation for each authorization: `(112 + 23) × cost_per_state_byte` per authorization. When an authorization targets an existing account (no account creation needed), the `112 × cost_per_state_byte` portion is refunded directly to `state_gas_reservoir` during authorization processing.
215
+
216
+
`intrinsic_state_gas` is immutable after transaction validation and is not modified by this refund. Block accounting uses the original worst-case `intrinsic_state_gas`; the refunded gas is reflected in the final `state_gas_reservoir` rather than in a mutated intrinsic value.
0 commit comments