Conversation
On the CREATE success path, generic_create credited the NEW_ACCOUNT state-gas refund (target-already-alive case) after incorporate_child_on_success, which folds the child's spill into the parent. The refund's LIFO gas_left/reservoir split was therefore computed against the combined parent+child spill, unlike the error path (whose incorporate_child_on_error does not fold the child's spill). Credit before incorporating the child so the refund reverses only the parent's own NEW_ACCOUNT spill, matching the error path. The split is tx-unobservable: the total refund is preserved, and over-cap frames carry gas_left near TX_MAX_GAS_LIMIT so the routing never gates a downstream charge. Verified by filling the eip8037 suite: 1567 fixtures byte-for-byte identical before and after. Claude-Session: https://claude.ai/code/session_01Nw3qUNd4aNzVypuzNhbQyg
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## forks/amsterdam #3099 +/- ##
================================================
Coverage 93.24% 93.24%
================================================
Files 624 624
Lines 36986 36986
Branches 3383 3383
================================================
Hits 34489 34489
Misses 1704 1704
Partials 793 793
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| 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). |
There was a problem hiding this comment.
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:
- The old code credits the child's spill back into
gas_leftwhile refundingStateGasCosts.NEW_ACCOUNT - The new code credits everything in
StateGasCosts.NEW_ACCOUNTto the reservoir.
Since the GAS opcode excludes the reservoir, this is observable behaviour. Probably needs a test case.
|
Also, should we do the refund first in |
The NEW_ACCOUNT refund on a successful CREATE onto an alive target is credited LIFO against the incorporated child spill, landing in the parent's gas_left where the GAS opcode (which excludes the reservoir) observes it. Complements test_create_onto_alive_refunds_to_gas_left, which covers the parent-spill case that is insensitive to the credit vs incorporation order. The factory stores the gas measured across the CREATE, pinning the refund routing: reordering the credit before child incorporation (PR ethereum#3099) shifts the stored value by exactly NEW_ACCOUNT (183,600).
|
Added test, let's review that one first: #3163. |
The NEW_ACCOUNT refund on a successful CREATE onto an alive target is credited LIFO against the incorporated child spill, landing in the parent's gas_left where the GAS opcode (which excludes the reservoir) observes it. Complements test_create_onto_alive_refunds_to_gas_left, which covers the parent-spill case that is insensitive to the credit vs incorporation order. The factory stores the gas measured across the CREATE, pinning the refund routing: reordering the credit before child incorporation (PR ethereum#3099) shifts the stored value by exactly NEW_ACCOUNT (183,600). Parametrized over CREATE and CREATE2.
The NEW_ACCOUNT refund on a successful CREATE onto an alive target is credited LIFO against the incorporated child spill, landing in the parent's gas_left where the GAS opcode (which excludes the reservoir) observes it. Complements test_create_onto_alive_refunds_to_gas_left, which covers the parent-spill case that is insensitive to the credit vs incorporation order. The factory stores the gas measured across the CREATE, pinning the refund routing: reordering the credit before child incorporation (PR #3099) shifts the stored value by exactly NEW_ACCOUNT (183,600). Parametrized over CREATE and CREATE2.
|
Accidental close? |
|
No. Not equivalent as proven by the test added in #3163. |
🗒️ Description
On the CREATE success path, generic_create credited the NEW_ACCOUNT state-gas refund (target-already-alive case) after incorporate_child_on_success, which folds the child's spill into the parent. The refund's LIFO gas_left/reservoir split was therefore computed against the combined parent+child spill, unlike the error path (whose incorporate_child_on_error does not fold the child's spill).
Credit before incorporating the child so the refund reverses only the parent's own NEW_ACCOUNT spill, matching the error path. The split is tx-unobservable: the total refund is preserved, and over-cap frames carry gas_left near TX_MAX_GAS_LIMIT so the routing never gates a downstream charge. Verified by filling the eip8037 suite: 1567 fixtures byte-for-byte identical before and after.
🔗 Related Issues or PRs
N/A.
✅ Checklist
just static<type>(<area>):, where<type>and<area>come from an approrpriateC-<type>, respectivelyA-<area>, label. The title should match the a target squash commit message../tests/ported_static/: