Skip to content

feat(test-vm): implement placeholder for bytecode#2103

Open
LouisTsai-Csie wants to merge 1 commit intoethereum:forks/amsterdamfrom
LouisTsai-Csie:feat-implement-placeholder
Open

feat(test-vm): implement placeholder for bytecode#2103
LouisTsai-Csie wants to merge 1 commit intoethereum:forks/amsterdamfrom
LouisTsai-Csie:feat-implement-placeholder

Conversation

@LouisTsai-Csie
Copy link
Collaborator

@LouisTsai-Csie LouisTsai-Csie commented Jan 29, 2026

🗒️ Description

With the gas calculator, we could write the test logic like the following:

code = (
    Op.BLOCKHASH(0)
    + Op.JUMPDEST
    + Op.CALL(address=Op.DUP6, value=1)
    + Op.SWAP1
    + Op.SUB
    + Op.JUMPI(Op.GT(Op.GAS, Op.PUSH(0x0000)), len(setup))
     # Op.PUSH(0x0000) should be based on the gas cost of the code implement
    + Op.RETURN(0, 0)
)

loop_cost = code.gas_cost(fork)

However, this introduces a circular dependency: loop_cost is needed to construct the bytecode, but we can only compute it after the bytecode exists. Without additional support, this forces us to write the code twice, once with a placeholder value and once with the final value.

code = (
    Op.BLOCKHASH(0)
    + Op.JUMPDEST
    + Op.CALL(address=Op.DUP6, value=1)
    + Op.SWAP1
    + Op.SUB
    + Op.JUMPI(Op.GT(Op.GAS, Op.PUSH(0x0000)), len(setup))
     # Op.PUSH(0x0000) should be based on the gas cost of the code implement
    + Op.RETURN(0, 0)
)

loop_cost = code.gas_cost(fork)

final_code = (
    Op.BLOCKHASH(0)
    + Op.JUMPDEST
    + Op.CALL(address=Op.DUP6, value=1)
    + Op.SWAP1
    + Op.SUB
    + Op.JUMPI(Op.GT(Op.GAS, loop_cost), len(setup))
     # Replace Op.PUSH(0x0000) with the final gas cost
    + Op.RETURN(0, 0)
)

A cleaner solution is to introduce a placeholder object. With placeholders, we can write the bytecode once and resolve the value afterward:

loop_cost = Placeholder(width=2)

code = (
    Op.BLOCKHASH(0)
    + Op.JUMPDEST
    + Op.CALL(address=Op.DUP6, value=1)
    + Op.SWAP1
    + Op.SUB
    + Op.JUMPI(Op.GT(Op.GAS, loop_cost), len(setup))
    + Op.RETURN(0, 0)
)

gas_cost = code.gas_cost(fork)
final_code = code.fill(loop_cost, gas_cost)

This avoids duplicated logic, keeps the bytecode definition readable, and makes gas-dependent loops much easier to express correctly.

🔗 Related Issues or PRs

N/A.

✅ Checklist

  • All: Ran fast tox checks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:
    uvx tox -e static
  • All: PR title adheres to the repo standard - it will be used as the squash commit message and should start type(scope):.
  • All: Considered updating the online docs in the ./docs/ directory.
  • All: Set appropriate labels for the changes (only maintainers can apply labels).
  • Tests: Ran mkdocs serve locally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.
  • Tests: For PRs implementing a missed test case, update the post-mortem document to add an entry the list.
  • Ported Tests: All converted JSON/YML tests from ethereum/tests or tests/static have been assigned @ported_from marker.

Cute Animal Picture

meow-wtf-is-going-on

@LouisTsai-Csie LouisTsai-Csie added the A-test-vm Area: execution_testing.vm label Jan 29, 2026
@codecov
Copy link

codecov bot commented Jan 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.07%. Comparing base (2c549ce) to head (fb5d9d2).

Additional details and impacted files
@@               Coverage Diff                @@
##           forks/amsterdam    #2103   +/-   ##
================================================
  Coverage            86.07%   86.07%           
================================================
  Files                  599      599           
  Lines                39472    39472           
  Branches              3780     3780           
================================================
  Hits                 33977    33977           
  Misses                4862     4862           
  Partials               633      633           
Flag Coverage Δ
unittests 86.07% <ø> (ø)

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

☔ View full report in Codecov by Sentry.
📢 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@LouisTsai-Csie LouisTsai-Csie force-pushed the feat-implement-placeholder branch from 292ca09 to fb5d9d2 Compare February 2, 2026 03:54
@LouisTsai-Csie LouisTsai-Csie marked this pull request as ready for review February 2, 2026 04:15
@LouisTsai-Csie LouisTsai-Csie self-assigned this Feb 2, 2026
@LouisTsai-Csie LouisTsai-Csie added the C-feat Category: an improvement or new feature label Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-test-vm Area: execution_testing.vm C-feat Category: an improvement or new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant