Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/ethereum/forks/amsterdam/vm/instructions/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,12 @@ def generic_create(
evm.return_data = child_evm.output
push(evm.stack, U256(0))
else:
incorporate_child_on_success(evm, child_evm)
if target_alive:
# Target already existed: no new account, refund the state gas.
# Credit before incorporating the child so the refund reverses
# the parent's own spill only (as the error path does).

@gurukamath gurukamath Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the parent's StateGasCosts.NEW_ACCOUNT charge is covered by the state_gas_reservoir but the child's initcode spills state charges into gas_left and then successfully deploys onto an already-alive address, the two orderings route the refund differently:

  1. The old code credits the child's spill back into gas_left while refunding StateGasCosts.NEW_ACCOUNT
  2. The new code credits everything in StateGasCosts.NEW_ACCOUNT to the reservoir.

Since the GAS opcode excludes the reservoir, this is observable behaviour. Probably needs a test case.

credit_state_gas_refund(evm, StateGasCosts.NEW_ACCOUNT)
incorporate_child_on_success(evm, child_evm)
evm.return_data = b""
push(evm.stack, U256.from_be_bytes(child_evm.message.current_target))

Expand Down
Loading