Skip to content

Commit 9b3961a

Browse files
committed
Snobal tests for bad 7702 state gas accounting
1 parent c288bcd commit 9b3961a

2 files changed

Lines changed: 102 additions & 8 deletions

File tree

tests/amsterdam/eip7778_block_gas_accounting_without_refunds/test_gas_accounting.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,12 @@ def test_multi_transaction_gas_accounting(
309309
310310
This tests that clients correctly use pre-refund gas for block accounting.
311311
"""
312-
# TODO: fix test to work with EIP-8037 two-dimensional gas model
313-
# instead of skipping.
312+
# Skipped on snøbal -- see test_state_gas_snobal_quirks.py.
314313
if refund_type == RefundTypes.AUTHORIZATION_EXISTING_AUTHORITY:
315314
pytest.skip(
316-
"EIP-8037: tx gas_limit includes state gas but block_gas_used "
317-
"uses max(regular, state)"
315+
"snøbal spec quirk: EIP-7702 auth refund not deducted from "
316+
"block_state_gas_used; behavior pinned by "
317+
"test_state_gas_snobal_quirks.py"
318318
)
319319

320320
intrinsic_cost_calc = fork.transaction_intrinsic_cost_calculator()
@@ -454,15 +454,15 @@ def test_varying_calldata_costs(
454454
"since refund is zero when execution reverts"
455455
)
456456

457-
# TODO: fix test to work with EIP-8037 two-dimensional gas model
458-
# instead of skipping.
457+
# Skipped on snøbal -- see test_state_gas_snobal_quirks.py.
459458
if refund_type == RefundTypes.AUTHORIZATION_EXISTING_AUTHORITY:
460459
if calldata_test_type == (
461460
CallDataTestType.DATA_FLOOR_BETWEEN_TX_GAS_BEFORE_AND_AFTER
462461
):
463462
pytest.skip(
464-
"EIP-8037: auth refund bypasses refund counter, "
465-
"so pre/post refund block gas are equal"
463+
"snøbal spec quirk: EIP-7702 auth refund routes to "
464+
"state reservoir, collapsing pre/post-refund range "
465+
"(see test_state_gas_snobal_quirks.py)"
466466
)
467467

468468
match refund_type:
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""
2+
Snøbal devnet-specific tests locking in current spec behavior under
3+
EIP-8037.
4+
5+
These tests document accounting quirks present in the snøbal devnet
6+
spec so client implementations targeting the devnet can be verified
7+
end-to-end. They do **not** describe the intended long-term semantics.
8+
9+
Bug locked in here:
10+
`set_delegation` (vm/eoa_delegation.py) credits
11+
`message.state_gas_reservoir` when the authority pre-exists in state,
12+
but `process_transaction` (fork.py) does not deduct that refund from
13+
`tx_state_gas`. Result: `block_state_gas_used` over-counts state gas
14+
by `STATE_BYTES_PER_NEW_ACCOUNT * COST_PER_STATE_BYTE` per
15+
existing-authority auth tuple.
16+
17+
Delete this file when the spec is fixed (e.g. by adding
18+
`MessageCallOutput.state_refund` and subtracting it from `tx_state_gas`,
19+
mirroring the post-execution selfdestruct refund pattern).
20+
"""
21+
22+
import pytest
23+
from execution_testing import (
24+
Alloc,
25+
AuthorizationTuple,
26+
Block,
27+
BlockchainTestFiller,
28+
Fork,
29+
Header,
30+
Op,
31+
Transaction,
32+
)
33+
34+
from .spec import ref_spec_8037
35+
36+
REFERENCE_SPEC_GIT_PATH = ref_spec_8037.git_path
37+
REFERENCE_SPEC_VERSION = ref_spec_8037.version
38+
39+
40+
@pytest.mark.valid_from("EIP8037")
41+
def test_snobal_block_gas_used_inflated_by_7702_auth_refund(
42+
blockchain_test: BlockchainTestFiller,
43+
pre: Alloc,
44+
fork: Fork,
45+
) -> None:
46+
"""
47+
Lock in: block.header.gas_used reflects the FULL intrinsic state
48+
gas for an EIP-7702 SetCodeTx whose authority pre-exists in state.
49+
50+
Scenario: one SetCodeTx with one authorization tuple pointing at a
51+
do-nothing contract. The authority is funded so it pre-exists,
52+
triggering the auth-refund credit to `state_gas_reservoir` inside
53+
`set_delegation`. The tx body executes only the delegated `STOP`,
54+
so `state_gas_used == 0` and `tx_state_gas == intrinsic_state_gas`
55+
under the current (buggy) accounting.
56+
57+
Snøbal expected: block.gas_used = intrinsic_state_gas
58+
(since intrinsic_state_gas dominates intrinsic_regular)
59+
Post-fix expected: block.gas_used = intrinsic_regular
60+
(after auth_state_refund deduction, regular dominates)
61+
"""
62+
sender = pre.fund_eoa()
63+
authority = pre.fund_eoa()
64+
target = pre.deploy_contract(code=Op.STOP)
65+
66+
auth_state_gas = fork.transaction_intrinsic_state_gas(
67+
authorization_count=1,
68+
)
69+
gas_limit_cap = fork.transaction_gas_limit_cap()
70+
assert gas_limit_cap is not None
71+
72+
tx = Transaction(
73+
to=authority,
74+
gas_limit=gas_limit_cap + auth_state_gas,
75+
sender=sender,
76+
authorization_list=[
77+
AuthorizationTuple(
78+
address=target,
79+
nonce=0,
80+
signer=authority,
81+
),
82+
],
83+
)
84+
85+
blockchain_test(
86+
pre=pre,
87+
blocks=[
88+
Block(
89+
txs=[tx],
90+
header_verify=Header(gas_used=auth_state_gas),
91+
)
92+
],
93+
post={},
94+
)

0 commit comments

Comments
 (0)