Skip to content

Commit 5be109e

Browse files
committed
Harcode hardcoded addresses static tests
1 parent 13aadf8 commit 5be109e

202 files changed

Lines changed: 7033 additions & 5793 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

scripts/filler_to_python/analyzer.py

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,88 @@ class NoIntResolver(_yaml.SafeLoader): # type: ignore[no-redef]
7171
"stTimeConsuming",
7272
}
7373

74+
# Ported tests (relative to ``tests/ported_static/``) that must keep
75+
# hardcoded addresses. These do not converge under ``exact-no-stack``
76+
# with dynamic addresses because of patterns the analyzer's heuristics
77+
# cannot cover:
78+
#
79+
# - EIP-2929 warm/cold gas accounting that depends on which addresses
80+
# are warm at call time (baseline-specific layout).
81+
# - CREATE2 collision semantics that depend on specific pre-state
82+
# addresses colliding with computed CREATE2 targets.
83+
# - Keccak-derived storage keys (Solidity mappings) baked into the
84+
# pre-state on specific sender / contract addresses.
85+
# - Structural transaction rejections sensitive to exact pre-state
86+
# collisions (empty-but-code, init-colliding-with-non-empty).
87+
# - Edge cases where dynamic allocation randomly picks an address
88+
# with a leading zero byte, changing PUSH size.
89+
# - Tag resolution mismatches (analyzer resolves <contract:0x…hint>
90+
# to a fresh deterministic address, but baseline used the hint).
91+
#
92+
# Treat this list as an allowlist of "we've accepted the divergence
93+
# here; don't try to make it dynamic". See trace-divergences.md for
94+
# the per-file rationale.
95+
FORCE_HARDCODED_TESTS: set[str] = {
96+
# GAS_ONLY (29) — EIP-2929 warm/cold access cost differences
97+
"stCallCodes/test_callcode_dynamic_code.py",
98+
"stCallCodes/test_callcode_dynamic_code2_self_call.py",
99+
"stCallCreateCallCodeTest/test_call1024_pre_calls.py",
100+
"stCallCreateCallCodeTest/test_contract_creation_make_call_that_ask_more_gas_then_transaction_provided.py", # noqa: E501
101+
"stCreate2/test_returndatacopy_following_create.py",
102+
"stCreateTest/test_create_collision_to_empty2.py",
103+
"stCreateTest/test_create_transaction_refund_ef.py",
104+
"stDelegatecallTestHomestead/test_call1024_pre_calls.py",
105+
"stDelegatecallTestHomestead/test_delegatecode_dynamic_code2_self_call.py", # noqa: E501
106+
"stEIP150singleCodeGasPrices/test_eip2929_oog.py",
107+
"stEIP2930/test_manual_create.py",
108+
"stEIP3651_warmcoinbase/test_coinbase_warm_account_call_gas_fail.py",
109+
"stEIP3855_push0/test_push0.py",
110+
"stEIP3855_push0/test_push0_gas2.py",
111+
"stHomesteadSpecific/test_contract_creation_oo_gdont_leave_empty_contract_via_transaction.py", # noqa: E501
112+
"stRandom/test_random_statetest282.py",
113+
"stRandom/test_random_statetest287.py",
114+
"stRandom/test_random_statetest384.py",
115+
"stRandom2/test_random_statetest401.py",
116+
"stRandom2/test_random_statetest508.py",
117+
"stRevertTest/test_cost_revert.py",
118+
"stRevertTest/test_revert_opcode_in_calls_on_non_empty_return_data.py",
119+
"stRevertTest/test_revert_opcode_multiple_sub_calls.py",
120+
"stRevertTest/test_revert_precompiled_touch_paris.py",
121+
"stStackTests/test_underflow_test.py",
122+
"stSystemOperationsTest/test_suicide_caller_addres_too_big_left.py",
123+
"vmBitwiseLogicOperation/test_byte.py",
124+
"vmIOandFlowOperations/test_jump_to_push.py",
125+
"vmIOandFlowOperations/test_jumpi.py",
126+
# EXECUTION_PATH_DIVERGED — remaining 8 (Categories B, C, D, E)
127+
"stCreate2/test_create2_suicide.py",
128+
"stCreate2/test_create2collision_code2.py",
129+
"stCreate2/test_create2collision_selfdestructed2.py",
130+
"stDelegatecallTestHomestead/test_delegatecall_in_initcode_to_existing_contract_oog.py", # noqa: E501
131+
"stLogTests/test_log1_non_empty_mem.py",
132+
"stSystemOperationsTest/test_double_selfdestruct_touch_paris.py",
133+
"stWalletTest/test_multi_owned_change_requirement_to1.py",
134+
"stWalletTest/test_multi_owned_revoke_nothing.py",
135+
# EXECUTION_PATH_DIVERGED + GAS (5)
136+
"stCreate2/test_create2collision_code.py",
137+
"stCreate2/test_create2collision_nonce.py",
138+
"stCreate2/test_create2collision_selfdestructed.py",
139+
"stCreate2/test_create2collision_selfdestructed_revert.py",
140+
"stSStoreTest/test_sstore_gas_left.py",
141+
# OUTPUT_DIFFERS — remaining 2 (Categories F, H)
142+
"stEIP3651_warmcoinbase/test_coinbase_warm_account_call_gas.py",
143+
"stWalletTest/test_multi_owned_is_owner_true.py",
144+
# STRUCTURAL (2) — CREATE collision behaviour
145+
"stCreateTest/test_transaction_collision_to_empty_but_code.py",
146+
"stEIP3607/test_init_colliding_with_non_empty_account.py",
147+
}
148+
149+
150+
def _ported_rel_path(filler_path: Path) -> str:
151+
"""Return the ``<category>/test_<snake>.py`` path for a filler."""
152+
category = filler_path.parent.name if filler_path.parent.name else ""
153+
py_test_name = _filler_name_to_test_name(filler_path.stem)
154+
return f"{category}/{py_test_name}.py"
155+
74156

75157
class _AnalyzerAlloc(Alloc):
76158
"""Alloc subclass that supports fund_eoa for analysis."""
@@ -163,8 +245,14 @@ def analyze(
163245
is_fork_dependent = not is_multi_case and len(model.expect) > 1
164246

165247
# 9. Build accounts
248+
force_hardcoded = _ported_rel_path(filler_path) in FORCE_HARDCODED_TESTS
166249
accounts = _build_accounts(
167-
model, tags, addr_to_var, sender_tag_name, imports
250+
model,
251+
tags,
252+
addr_to_var,
253+
sender_tag_name,
254+
imports,
255+
force_hardcoded=force_hardcoded,
168256
)
169257

170258
# Track if sender is not in the pre-state (for fund_eoa handling).
@@ -173,8 +261,8 @@ def analyze(
173261
if sender_tag_name and not any(a.is_sender for a in accounts):
174262
sender_ir.not_in_pre = True
175263

176-
# Always use dynamic sender (pre.fund_eoa) for non-hardcoded tests
177-
sender_ir.use_dynamic = True
264+
# Dynamic sender unless this test is on the hardcoded allowlist.
265+
sender_ir.use_dynamic = not force_hardcoded
178266

179267
# 10. Build environment
180268
environment_ir = _build_environment(model, tags, addr_to_var)
@@ -196,6 +284,13 @@ def analyze(
196284
if not acct.is_eoa:
197285
acct.use_dynamic = False
198286

287+
# 11c. Forced hardcoded (allowlist) also pins every EOA so coinbase
288+
# rebinds and fund_eoa-generated EOAs don't leak into an otherwise
289+
# hardcoded test.
290+
if force_hardcoded:
291+
for acct in accounts:
292+
acct.use_dynamic = False
293+
199294
# 12. Build transaction IR
200295
transaction_ir, access_list_entries = _build_transaction_ir(
201296
model,
@@ -747,6 +842,8 @@ def _build_accounts(
747842
addr_to_var: dict[Address | EOA, str],
748843
sender_tag_name: str | None,
749844
imports: ImportsIR,
845+
*,
846+
force_hardcoded: bool = False,
750847
) -> list[AccountIR]:
751848
"""Build AccountIR list with dependency-ordered contracts."""
752849
# ------------------------------------------------------------------
@@ -998,6 +1095,7 @@ def _build_accounts(
9981095
has_addr_arithmetic
9991096
or short_push_unpinnable
10001097
or has_computed_call_target
1098+
or force_hardcoded
10011099
):
10021100
# Disable dynamic for all contracts and re-generate Op
10031101
# expressions without addr_to_var. Triggers:
@@ -1008,6 +1106,9 @@ def _build_accounts(
10081106
# resolved addresses.
10091107
# * computed call targets (CALL with address=Op.ADD/MLOAD/
10101108
# CALLDATALOAD/...) dispatch by baseline-relative offsets.
1109+
# * the test is on the FORCE_HARDCODED_TESTS allowlist — we've
1110+
# accepted that it can't converge under exact-no-stack with
1111+
# dynamic addresses (see module docstring on that set).
10111112
for acct in raw_accounts:
10121113
if not acct.is_eoa:
10131114
acct.use_dynamic = False

tests/ported_static/stBadOpcode/test_invalid_addr.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ def test_invalid_addr(
575575
+ Op.STOP,
576576
balance=0x10000,
577577
nonce=0,
578+
address=Address(0x1C60A961CFF23C82B2F809E76B815D003898E196), # noqa: E501
578579
)
579580
# Source: lll
580581
# {
@@ -584,6 +585,7 @@ def test_invalid_addr(
584585
code=Op.SELFDESTRUCT(address=Op.CALLDATALOAD(offset=0x0)) + Op.STOP,
585586
balance=4096,
586587
nonce=0,
588+
address=Address(0x9CB657C71386D578195B90DA7DE545482E0A9440), # noqa: E501
587589
)
588590
# Source: lll
589591
# {
@@ -593,6 +595,7 @@ def test_invalid_addr(
593595
code=Op.SELFDESTRUCT(address=Op.CALLDATALOAD(offset=0x0)) + Op.STOP,
594596
balance=4096,
595597
nonce=0,
598+
address=Address(0xE2CFFD6602680D87B7872C3B69F42FA631058CBF), # noqa: E501
596599
)
597600
# Source: lll
598601
# {
@@ -634,7 +637,9 @@ def test_invalid_addr(
634637
+ Op.POP(0x0)
635638
+ Op.JUMP(pc=Op.PUSH2[0x2B])
636639
+ Op.JUMPDEST
637-
+ Op.MSTORE(offset=0x2000, value=addr)
640+
+ Op.MSTORE(
641+
offset=0x2000, value=0x1C60A961CFF23C82B2F809E76B815D003898E196
642+
)
638643
+ Op.JUMPDEST
639644
+ Op.JUMPI(
640645
pc=Op.PUSH2[0x3D],
@@ -972,7 +977,7 @@ def test_invalid_addr(
972977
+ Op.POP(
973978
Op.CALL(
974979
gas=0x10000000,
975-
address=dead1,
980+
address=0x9CB657C71386D578195B90DA7DE545482E0A9440,
976981
value=0x0,
977982
args_offset=0x2000,
978983
args_size=0x20,
@@ -986,7 +991,7 @@ def test_invalid_addr(
986991
+ Op.POP(
987992
Op.CALL(
988993
gas=0x10000000,
989-
address=dead2,
994+
address=0xE2CFFD6602680D87B7872C3B69F42FA631058CBF,
990995
value=0x0,
991996
args_offset=0x2040,
992997
args_size=0x20,
@@ -1026,6 +1031,7 @@ def test_invalid_addr(
10261031
storage={256: 24743},
10271032
balance=0xBA1A9CE0BA1A9CE,
10281033
nonce=0,
1034+
address=Address(0x2D876FD03A90703F170C256363BA225F9494E604), # noqa: E501
10291035
)
10301036

10311037
tx_data = [

0 commit comments

Comments
 (0)