Skip to content

Commit 1628020

Browse files
committed
feat(spec-specs): SSTORE 0 to x to 0 refunds state gas to reservoir
1 parent e723e7d commit 1628020

3 files changed

Lines changed: 25 additions & 7 deletions

File tree

src/ethereum/forks/amsterdam/vm/__init__.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ class Evm:
173173
accessed_storage_keys: Set[Tuple[Address, Bytes32]]
174174
regular_gas_used: Uint = Uint(0)
175175
state_gas_used: Uint = Uint(0)
176+
state_gas_refund: Uint = Uint(0)
176177

177178

178179
def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None:
@@ -196,6 +197,7 @@ def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None:
196197
evm.accessed_storage_keys.update(child_evm.accessed_storage_keys)
197198
evm.regular_gas_used += child_evm.regular_gas_used
198199
evm.state_gas_used += child_evm.state_gas_used
200+
evm.state_gas_refund += child_evm.state_gas_refund
199201

200202

201203
def incorporate_child_on_error(
@@ -210,6 +212,12 @@ def incorporate_child_on_error(
210212
that spilled into `gas_left`, is restored to the parent's reservoir and
211213
the child's `state_gas_used` is not accumulated.
212214
215+
Inline state-gas refunds (SSTORE 0 to x to 0) accumulated in the child or
216+
its successful descendants are dropped: `state_gas_refund` is subtracted
217+
from the amount returned to the parent's reservoir and is not propagated.
218+
This matches `refund_counter`'s error-path behavior and keeps the refund
219+
frame-scoped.
220+
213221
Parameters
214222
----------
215223
evm :
@@ -219,5 +227,9 @@ def incorporate_child_on_error(
219227
220228
"""
221229
evm.gas_left += child_evm.gas_left
222-
evm.state_gas_left += child_evm.state_gas_used + child_evm.state_gas_left
230+
evm.state_gas_left += (
231+
child_evm.state_gas_used
232+
+ child_evm.state_gas_left
233+
- child_evm.state_gas_refund
234+
)
223235
evm.regular_gas_used += child_evm.regular_gas_used

src/ethereum/forks/amsterdam/vm/instructions/storage.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,16 @@ def sstore(evm: Evm) -> None:
127127
if original_value == new_value:
128128
# Storage slot being restored to its original value
129129
if original_value == 0:
130-
# Slot was originally empty and was SET earlier.
131-
# Refund state gas and the write cost (the write
132-
# is cancelled — clients batch trie writes to slot
133-
# boundaries, so no IO actually happens).
130+
# Slot set then cleared: refund state gas to the
131+
# reservoir and regular cost via refund_counter. The
132+
# state-gas credit is tracked in state_gas_refund so it
133+
# can be unwound on revert or exceptional halt of this
134+
# frame or any ancestor that inherits it.
135+
evm.state_gas_left += state_gas_storage_set
136+
evm.state_gas_used -= state_gas_storage_set
137+
evm.state_gas_refund += state_gas_storage_set
134138
evm.refund_counter += int(
135-
state_gas_storage_set
136-
+ GAS_STORAGE_UPDATE
139+
GAS_STORAGE_UPDATE
137140
- GAS_COLD_STORAGE_ACCESS
138141
- GAS_WARM_ACCESS
139142
)

src/ethereum/forks/amsterdam/vm/instructions/system.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ def generic_create(
124124
# No account created — refund state gas to reservoir.
125125
evm.state_gas_left += create_account_state_gas
126126
evm.state_gas_used -= create_account_state_gas
127+
evm.state_gas_refund += create_account_state_gas
127128
push(evm.stack, U256(0))
128129
return
129130

@@ -138,6 +139,7 @@ def generic_create(
138139
# Address collision — no account created, refund state gas.
139140
evm.state_gas_left += create_account_state_gas
140141
evm.state_gas_used -= create_account_state_gas
142+
evm.state_gas_refund += create_account_state_gas
141143
push(evm.stack, U256(0))
142144
return
143145

@@ -170,6 +172,7 @@ def generic_create(
170172
# No account created, refund parent's CREATE state gas.
171173
evm.state_gas_left += create_account_state_gas
172174
evm.state_gas_used -= create_account_state_gas
175+
evm.state_gas_refund += create_account_state_gas
173176
evm.return_data = child_evm.output
174177
push(evm.stack, U256(0))
175178
else:

0 commit comments

Comments
 (0)