Skip to content

feat(tests): probe EIP-161 emptiness after same-tx precompile touches - #3477

Open
spencer-tb wants to merge 3 commits into
ethereum:forks/amsterdamfrom
spencer-tb:tests/eip161-emptiness-probes
Open

feat(tests): probe EIP-161 emptiness after same-tx precompile touches#3477
spencer-tb wants to merge 3 commits into
ethereum:forks/amsterdamfrom
spencer-tb:tests/eip161-emptiness-probes

Conversation

@spencer-tb

@spencer-tb spencer-tb commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Description

Stacked on #3480.

Add a touch-then-probe family for EIP-161 emptiness, covering erigontech/erigon#23670: a client that reads its own touch bookkeeping as proof of account existence skips new-account charges and diverges. A zero-value CALL to an absent precompile runs its code without creating the account, and nothing in the suite exercised that sequence before.

  • New tests/spurious_dragon/eip161_state_trie_clearing/:
    • test_extcodehash_after_precompile_touch (ConstantinopleFix+, all precompiles): EXTCODEHASH, EXTCODESIZE and BALANCE probes around a same-transaction touch, for absent and funded precompiles.
    • test_call_new_account_charge_after_precompile_touch and test_selfdestruct_beneficiary_charge_after_precompile_touch (SpuriousDragon+): measure the exact charge after a touch. The measured call forwards zero gas, so the callee runs only on the value stipend and always halts, keeping precompile costs out of the measurement. From Amsterdam the new-account charge is state gas and invisible to the GAS delta, so the expectation uses execution_cost and the state charge stays pinned through the sender balance in the state root.
  • test_bal_insufficient_balance_call_to_touched_precompile (EIP-7928): RIPEMD-160 must appear in the BAL with empty changes when reached only by a value call that fails its balance check, the shape the fuzzer found.

Related Issues or PRs

#3480
erigontech/erigon#23670
erigontech/erigon#23672

Checklist

  • Ran fast static checks to avoid CI fails, see Code Standards & Verifying Changes: just static
  • PR title has the form <type>(<area>): <title>, where <type> and <area> come from an appropriate C-<type>, respectively A-<area>, label. The title should match the target squash commit message.

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.05%. Comparing base (8faf36a) to head (7bd986d).
⚠️ Report is 5 commits behind head on forks/amsterdam.

Additional details and impacted files
@@                 Coverage Diff                 @@
##           forks/amsterdam    #3477      +/-   ##
===================================================
+ Coverage            93.90%   94.05%   +0.14%     
===================================================
  Files                  624      624              
  Lines                36905    36905              
  Branches              3326     3326              
===================================================
+ Hits                 34655    34710      +55     
+ Misses                1569     1525      -44     
+ Partials               681      670      -11     
Flag Coverage Δ
unittests 94.05% <ø> (+0.14%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@spencer-tb
spencer-tb force-pushed the tests/eip161-emptiness-probes branch from 119c361 to c9c388c Compare September 2, 2026 12:59
@spencer-tb
spencer-tb marked this pull request as ready for review September 2, 2026 12:59

@fselmo fselmo left a comment

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.

Sorry had one thing locally that I pushed as it was an exploration and revealed a possible blip I think. Basically, the fixture carried no trace of the charge and a client that skips it after a touch would pass this test. I pushed a second value call that actually creates the precompile, so the charge is paid and stays paid, and the sender balance in the state root proves it.. with the precompile pre-funded as a control, the sender pays exactly NEW_ACCOUNT less.

Left some comments as well, nothing big. Looks good otherwise!

Please review my commit and lmk!



ref_spec_161 = ReferenceSpec(
"EIPS/eip-161.md", "96523ef4d76ca440f73f0403ddb5c9cb3b24dcae"

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.

This looks wrong?

Suggested change
"EIPS/eip-161.md", "96523ef4d76ca440f73f0403ddb5c9cb3b24dcae"
"EIPS/eip-161.md", "b746c239881f24996f0205855e44f9b2d3b92b6a"

return Op.POP(Op.CALL(gas=100_000, address=precompile))
# The value exceeds the caller's balance, so the transfer fails
# after the target access is charged.
return Op.POP(Op.CALL(gas=100_000, address=precompile, value=2**100))

@fselmo fselmo Sep 2, 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.

nit: personal preference but also bc it could be a footgun... I'd prefer these to be if / elif for all cases and to raise on the else. Can be convinced otherwise though 😅

),
)

blockchain_test(

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.

nit: this can also be a state_test since just one tx 👀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants