Skip to content

Commit 426e747

Browse files
committed
fix(test): more updates related to rigid costs across tests; make flexible
1 parent f3dcf7a commit 426e747

20 files changed

Lines changed: 386 additions & 83 deletions

File tree

packages/testing/src/execution_testing/cli/pytest_commands/plugins/shared/transaction_fixtures.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,7 @@ def type_4_default_transaction(
104104
target2 = pre.deploy_contract(Op.SSTORE(0, 1))
105105

106106
# Recipient may be a nonexistent account (e.g., EIP-7708 transfer
107-
# log tests), so cover one NEW_ACCOUNT state charge. NEW_ACCOUNT
108-
# is the legacy 25_000 pre-EIP-8037 and scales with cpsb on
109-
# Amsterdam, keeping this budget CPSB-agnostic.
107+
# log tests), so cover one NEW_ACCOUNT state charge.
110108
return Transaction(
111109
ty=4,
112110
sender=sender,

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,12 @@ def set_delegation(message: Message) -> Uint:
205205
if authority_nonce != auth.nonce:
206206
continue
207207

208-
# For existing accounts, no account creation needed.
209-
# Refund the account creation state gas to the reservoir.
210-
# intrinsic_state_gas is immutable after validation.
208+
# For existing accounts no account creation happens, so the
209+
# NEW_ACCOUNT portion of the auth's intrinsic state cost is
210+
# refunded. The reservoir credit lowers `tx_gas_used` for the
211+
# sender; debiting `intrinsic_state_gas` lowers
212+
# `block_state_gas_used` so the block accounting matches the
213+
# state work that actually occurred.
211214
if account_exists(tx_state, authority):
212215
refund = STATE_BYTES_PER_NEW_ACCOUNT * COST_PER_STATE_BYTE
213216
message.state_gas_reservoir += refund

tests/amsterdam/eip7708_eth_transfer_logs/test_fork_transition.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,10 @@ def test_burn_log_at_fork_transition(
119119
beneficiary: Account(balance=contract_balance * 3),
120120
}
121121

122-
# Same-tx CREATE+SELFDESTRUCT requires NEW_ACCOUNT state gas, which
123-
# scales with cpsb on Amsterdam. NEW_ACCOUNT is the legacy 25_000
124-
# pre-EIP-8037, so the bump is harmless on the pre-transition block.
125-
# `fork` is a TransitionFork here; resolve to the post-transition
126-
# fork (timestamp 15_001) where the larger NEW_ACCOUNT applies.
122+
# Same-tx CREATE+SELFDESTRUCT charges NEW_ACCOUNT state gas; the
123+
# pre-transition block has plenty of headroom. `fork` is a
124+
# TransitionFork here, so resolve to the post-transition fork
125+
# (timestamp 15_001) where the larger NEW_ACCOUNT applies.
127126
post_fork = fork.fork_at(timestamp=15_001)
128127
gas_limit = 200_000 + post_fork.gas_costs().NEW_ACCOUNT
129128
blocks = [

tests/berlin/eip2930_access_list/test_acl.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,16 @@ def test_account_storage_warm_cold_state(
9090

9191
intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator()
9292

93+
# CodeGasMeasure SSTOREs the measured cost; budget for one
94+
# first-time SSTORE whose state gas scales with cpsb on Amsterdam.
9395
tx_gas_limit = (
9496
intrinsic_gas_calculator(
9597
calldata=tx_data,
9698
contract_creation=contract_creation,
9799
access_list=access_lists,
98100
)
99101
+ 100_000
102+
+ fork.sstore_state_gas()
100103
)
101104

102105
tx = Transaction(

tests/cancun/eip5656_mcopy/test_mcopy.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
Alloc,
1212
Bytecode,
1313
Environment,
14+
Fork,
1415
Hash,
1516
Op,
1617
StateTestFiller,
@@ -115,13 +116,20 @@ def code_address(pre: Alloc, code_bytecode: Bytecode) -> Address:
115116

116117
@pytest.fixture
117118
def tx( # noqa: D103
118-
pre: Alloc, code_address: Address, dest: int, src: int, length: int
119+
pre: Alloc,
120+
fork: Fork,
121+
code_address: Address,
122+
dest: int,
123+
src: int,
124+
length: int,
119125
) -> Transaction:
126+
# The test SSTOREs each memory word it reads, so budget for ~10
127+
# first-time SSTOREs whose state gas scales with cpsb on Amsterdam.
120128
return Transaction(
121129
sender=pre.fund_eoa(),
122130
to=code_address,
123131
data=Hash(dest) + Hash(src) + Hash(length),
124-
gas_limit=1_000_000,
132+
gas_limit=1_000_000 + 10 * fork.sstore_state_gas(),
125133
)
126134

127135

@@ -231,6 +239,7 @@ def test_valid_mcopy_operations(
231239
def test_mcopy_repeated(
232240
state_test: StateTestFiller,
233241
pre: Alloc,
242+
fork: Fork,
234243
dest: int,
235244
src: int,
236245
length: int,
@@ -294,7 +303,7 @@ def test_mcopy_repeated(
294303
sender=pre.fund_eoa(),
295304
to=contract,
296305
data=Hash(dest) + Hash(src) + Hash(length),
297-
gas_limit=1_000_000,
306+
gas_limit=1_000_000 + 2 * fork.sstore_state_gas(),
298307
),
299308
)
300309

tests/cancun/eip6780_selfdestruct/test_selfdestruct.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,7 @@ def test_create_multiple_contracts_destroy_one_then_destroy_other_next_tx(
16321632
blockchain_test: BlockchainTestFiller,
16331633
eip_enabled: bool,
16341634
pre: Alloc,
1635+
fork: Fork,
16351636
sender: EOA,
16361637
selfdestruct_contract_initial_balance: int,
16371638
) -> None:
@@ -1734,16 +1735,21 @@ def test_create_multiple_contracts_destroy_one_then_destroy_other_next_tx(
17341735
+ Op.STOP
17351736
)
17361737

1738+
# tx1 does 2 CREATE2 (NEW_ACCOUNT each) plus several first-time
1739+
# SSTOREs across entry/init code; tx2 does one SSTORE call.
1740+
# Bump scales with cpsb on Amsterdam.
1741+
new_account = fork.gas_costs().NEW_ACCOUNT
1742+
sstore_state = fork.sstore_state_gas()
17371743
txs = [
17381744
Transaction(
17391745
sender=sender,
17401746
to=entry_code_address,
1741-
gas_limit=1_000_000,
1747+
gas_limit=1_000_000 + 2 * new_account + 6 * sstore_state,
17421748
),
17431749
Transaction(
17441750
sender=sender,
17451751
to=tx2_caller,
1746-
gas_limit=500_000,
1752+
gas_limit=500_000 + sstore_state,
17471753
),
17481754
]
17491755

tests/constantinople/eip1014_create2/test_create2_revert.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
Account,
88
Alloc,
99
Environment,
10+
Fork,
1011
Initcode,
1112
Op,
1213
StateTestFiller,
@@ -87,6 +88,7 @@ def test_create2_revert_preserves_balance(
8788
def test_create2_succeeds_after_reverted_create2(
8889
state_test: StateTestFiller,
8990
pre: Alloc,
91+
fork: Fork,
9092
) -> None:
9193
"""
9294
Test that CREATE2 succeeds after a previous CREATE2 at the same address
@@ -99,6 +101,9 @@ def test_create2_succeeds_after_reverted_create2(
99101
storage = Storage()
100102
salt = 1
101103

104+
new_account = fork.gas_costs().NEW_ACCOUNT
105+
sstore_state = fork.sstore_state_gas()
106+
102107
runtime_code = Op.SSTORE(0, 1) + Op.STOP
103108
initcode = Initcode(deploy_code=runtime_code)
104109

@@ -129,7 +134,7 @@ def test_create2_succeeds_after_reverted_create2(
129134
Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE)
130135
+ Op.POP(
131136
Op.CALL(
132-
gas=200_000,
137+
gas=200_000 + new_account + sstore_state,
133138
address=creator,
134139
args_size=Op.CALLDATASIZE,
135140
)
@@ -144,7 +149,7 @@ def test_create2_succeeds_after_reverted_create2(
144149
+ Op.SSTORE(
145150
storage.store_next(0, "reverter_call_result"),
146151
Op.CALL(
147-
gas=300_000,
152+
gas=300_000 + new_account + sstore_state,
148153
address=reverter,
149154
args_size=Op.CALLDATASIZE,
150155
),
@@ -153,7 +158,7 @@ def test_create2_succeeds_after_reverted_create2(
153158
+ Op.SSTORE(
154159
storage.store_next(1, "creator_call_result"),
155160
Op.CALL(
156-
gas=300_000,
161+
gas=300_000 + new_account + sstore_state,
157162
address=creator,
158163
args_size=Op.CALLDATASIZE,
159164
),
@@ -177,7 +182,7 @@ def test_create2_succeeds_after_reverted_create2(
177182
tx=Transaction(
178183
sender=sender,
179184
to=outer,
180-
gas_limit=2_000_000,
185+
gas_limit=2_000_000 + 2 * (new_account + sstore_state),
181186
data=initcode,
182187
),
183188
)

tests/constantinople/eip1052_extcodehash/test_extcodehash.py

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -563,9 +563,12 @@ def test_extcodehash_dynamic_account_overwrite(
563563
target_storage[target_storage_slot] = 1
564564

565565
sender = pre.fund_eoa()
566-
gas_limit = 400_000
567-
if fork.is_eip_enabled(8037):
568-
gas_limit = 1_000_000
566+
# Test does ~10 first-time SSTOREs plus a CREATE2 (NEW_ACCOUNT)
567+
# in the caller. Both terms are 0 pre-EIP-8037 and scale with cpsb
568+
# on Amsterdam, keeping this CPSB-agnostic.
569+
gas_limit = (
570+
400_000 + fork.gas_costs().NEW_ACCOUNT + 10 * fork.sstore_state_gas()
571+
)
569572

570573
tx = Transaction(
571574
sender=sender,
@@ -1352,19 +1355,22 @@ def test_extcodehash_call_to_selfdestruct(
13521355

13531356
call_succeeds = call_opcode != Op.STATICCALL
13541357

1358+
# SELFDESTRUCT to a nonexistent beneficiary creates a new account
1359+
# whose state gas scales with cpsb on Amsterdam. Forward enough so
1360+
# the inner CALL still completes when NEW_ACCOUNT grows.
1361+
new_account = fork.gas_costs().NEW_ACCOUNT
1362+
sstore_state = fork.sstore_state_gas()
13551363
code = Op.SSTORE(
13561364
storage.store_next(int(call_succeeds)),
1357-
call_opcode(address=target, gas=165_000),
1365+
call_opcode(address=target, gas=165_000 + new_account),
13581366
) + Op.SSTORE(
13591367
storage.store_next(target_code.keccak256()),
13601368
Op.EXTCODEHASH(target),
13611369
)
13621370

13631371
code_address = pre.deploy_contract(code, storage=storage.canary())
13641372

1365-
gas_limit = 400_000
1366-
if fork.is_eip_enabled(8037):
1367-
gas_limit = 1_000_000
1373+
gas_limit = 400_000 + new_account + 2 * sstore_state
13681374
tx = Transaction(
13691375
sender=pre.fund_eoa(),
13701376
to=code_address,
@@ -1578,9 +1584,11 @@ def inner_extcode_checks() -> Bytecode:
15781584
)
15791585
outer = pre.deploy_contract(outer_code, storage=outer_storage.canary())
15801586

1581-
gas_limit = 400_000
1582-
if fork.is_eip_enabled(8037):
1583-
gas_limit = 1_000_000
1587+
# Test does ~10 first-time SSTOREs (across inner and outer) plus a
1588+
# CREATE2 (NEW_ACCOUNT). Both terms scale with cpsb on Amsterdam.
1589+
gas_limit = (
1590+
400_000 + fork.gas_costs().NEW_ACCOUNT + 10 * fork.sstore_state_gas()
1591+
)
15841592
tx = Transaction(
15851593
sender=pre.fund_eoa(),
15861594
to=outer,
@@ -1639,9 +1647,14 @@ def test_extcodehash_subcall_selfdestruct(
16391647
selfdestruct_code = Op.SELFDESTRUCT(beneficiary)
16401648
target_c = pre.deploy_contract(selfdestruct_code)
16411649

1650+
# SELFDESTRUCT to a nonexistent beneficiary creates a new account
1651+
# whose state gas scales with cpsb on Amsterdam.
1652+
new_account = fork.gas_costs().NEW_ACCOUNT
1653+
sstore_state = fork.sstore_state_gas()
1654+
16421655
# A: executes C's code in A's context via CALLCODE/DELEGATECALL
16431656
a_code = call_opcode(
1644-
gas=350_000,
1657+
gas=350_000 + new_account,
16451658
address=target_c,
16461659
ret_size=32,
16471660
)
@@ -1682,12 +1695,12 @@ def extcode_checks(target: Address | Bytecode) -> Bytecode:
16821695
code += extcode_checks(a_target)
16831696
code += Op.SSTORE(
16841697
storage.store_next(1),
1685-
Op.CALL(gas=350_000, address=a_target),
1698+
Op.CALL(gas=350_000 + new_account, address=a_target),
16861699
)
16871700
code += extcode_checks(a_target)
16881701
code += Op.SSTORE(
16891702
storage.store_next(1),
1690-
Op.CALL(gas=350_000, address=a_target),
1703+
Op.CALL(gas=350_000 + new_account, address=a_target),
16911704
)
16921705

16931706
code_address = pre.deploy_contract(code, storage=storage.canary())
@@ -1696,9 +1709,8 @@ def extcode_checks(target: Address | Bytecode) -> Bytecode:
16961709
a = compute_create_address(address=code_address, nonce=1)
16971710
storage[created_slot] = a
16981711

1699-
gas_limit = 500_000
1700-
if fork.is_eip_enabled(8037):
1701-
gas_limit = 1_000_000
1712+
# Test does up to ~7 first-time SSTOREs plus a CREATE for dynamic A.
1713+
gas_limit = 500_000 + new_account + 7 * sstore_state
17021714
tx = Transaction(
17031715
sender=pre.fund_eoa(),
17041716
to=code_address,
@@ -1757,6 +1769,12 @@ def test_extcodehash_subcall_create2_oog(
17571769
deploy_code_bytes = bytes(deploy_code)
17581770
initcode = Initcode(deploy_code=deploy_code)
17591771

1772+
# CREATE2 charges NEW_ACCOUNT state gas; the deploy_code's SSTORE
1773+
# also charges first-time SSTORE state gas. Both scale with cpsb
1774+
# on Amsterdam.
1775+
new_account = fork.gas_costs().NEW_ACCOUNT
1776+
sstore_state = fork.sstore_state_gas()
1777+
17601778
# Factory: CREATE2, optionally consume all gas to trigger OOG.
17611779
factory_code = Om.MSTORE(initcode, 0) + Op.MSTORE(
17621780
0, Op.CREATE2(value=0, offset=0, size=len(initcode), salt=0)
@@ -1777,7 +1795,7 @@ def test_extcodehash_subcall_create2_oog(
17771795
storage.store_next(int(not oog), "call_result"),
17781796
call_opcode(
17791797
address=factory,
1780-
gas=200_000,
1798+
gas=200_000 + new_account + sstore_state,
17811799
ret_offset=0,
17821800
ret_size=32,
17831801
),
@@ -1813,9 +1831,8 @@ def test_extcodehash_subcall_create2_oog(
18131831
else:
18141832
post[created] = Account(nonce=1, code=deploy_code)
18151833

1816-
gas_limit = 500_000
1817-
if fork.is_eip_enabled(8037):
1818-
gas_limit = 1_000_000
1834+
# Caller does ~5 first-time SSTOREs plus the inner CALL+CREATE2.
1835+
gas_limit = 500_000 + new_account + 5 * sstore_state
18191836
tx = Transaction(
18201837
sender=pre.fund_eoa(),
18211838
to=code_address,

tests/frontier/create/test_create_one_byte.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ def test_create_one_byte(
4848
sender = pre.fund_eoa()
4949
expect_post = Storage()
5050

51-
call_gas = 50_000
52-
if fork.is_eip_enabled(8037):
53-
call_gas = 200_000
51+
new_account = fork.gas_costs().NEW_ACCOUNT
52+
sstore_state = fork.sstore_state_gas()
53+
# Each call forwards gas to the create_contract that does CREATE;
54+
# forward base + NEW_ACCOUNT (cpsb-agnostic).
55+
call_gas = 50_000 + new_account
5456

5557
# make a subcontract that deploys code, because deploy 0xef eats ALL gas
5658
create_contract = pre.deploy_contract(
@@ -100,9 +102,11 @@ def test_create_one_byte(
100102
expect_post[256] = 1
101103

102104
# Osaka (EIP-7825) caps transaction gas limit at 16,777,216.
103-
# Amsterdam (EIP-8037) adds state gas for CREATEs and SSTOREs.
105+
# Amsterdam (EIP-8037) adds state gas via the reservoir on top of
106+
# the cap. NEW_ACCOUNT and sstore_state_gas are 0 pre-EIP-8037 and
107+
# scale with cpsb on Amsterdam, keeping this CPSB-agnostic.
104108
if fork.is_eip_enabled(8037):
105-
gas_limit = 60_000_000
109+
gas_limit = 16_000_000 + 256 * new_account + 257 * sstore_state
106110
elif fork >= Osaka:
107111
gas_limit = 16_000_000
108112
else:
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
"""Pytest (plugin) definitions local to Identity precompile tests."""
22

33
import pytest
4+
from execution_testing import Fork
45

56

67
@pytest.fixture
7-
def tx_gas_limit() -> int:
8+
def tx_gas_limit(fork: Fork) -> int:
89
"""Return the gas limit for transactions."""
9-
return 365_224
10+
# The `nonzerovalue` variants transfer 1 wei to the identity
11+
# precompile, creating its account and charging NEW_ACCOUNT
12+
# state gas under EIP-8037 (0 otherwise).
13+
return 365_224 + fork.gas_costs().NEW_ACCOUNT

0 commit comments

Comments
 (0)