Skip to content

feat(typewriter-evm): pick Monad or Ethereum EVM from the chain ID - #122

Closed
kyscott18 wants to merge 2 commits into
mainfrom
feat/ethereum-chain-spec
Closed

kyscott18 wants to merge 2 commits into
mainfrom
feat/ethereum-chain-spec

Conversation

@kyscott18

@kyscott18 kyscott18 commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Spec is a Monad hardfork or an Ethereum one (Merge..Osaka). When it isn't pinned, the chain ID picks it: 143/10143 use monad-revm's schedule; 1, Sepolia, and Hoodi use Ethereum's activation timestamps (checked against alloy-hardforks). The harness picks monad-revm or mainnet revm through a small Backend trait, and the network stays fixed after init.
  • Simulated gas_limit is now max(gas spent before refund + reserve, EIP-7623 floor). Monad has no refunds, so tx_gas_used was enough there. On Ethereum it under-provisions any tx that clears a slot (new reserve_covers_refunds test).
  • The sim draws chain.network. Anvil keeps its chain ID (31337), which has no hardfork schedule, so the sim pins the hardfork to match: --network monad runs MonadTen, and --hardfork osaka --enable-tx-gas-limit with 12s blocks runs Osaka. Choosing the hardfork from the chain ID is covered by the Rust and TS unit tests.

Validation

  • Rust tests: 9/9. typewriter-evm TS tests: 34/34. typewriter unit tests: 97/97. Typecheck, clippy, and biome are clean.
  • Reorg-free seeds, run one at a time:
    • Ethereum: 10/12 pass. 0x4d and 0x4 fail with intrinsic gas too high -- tx.gas_limit > resolved tx gas limit cap.
    • Monad: 6/6 pass (0x11 0x41 0x23 0x74 0xcd 0x16f).

Ethereum blockers this exposes (not fixed here)

  1. Osaka per-tx gas cap (2^24 ≈ 16.8M). A backlog settles in one tx; seed 0x87 simulated 486 mutations at 32.7M gas. This is the existing TODO(kyle) cap a submission. Monad has no such cap.
  2. EXPIRATION_MARGIN = 5s. It is shorter than one 12s slot, so 1–15% of mutations per seed are dropped from reverted settlements. With expirations off, 0x4d and 0x87 drop 0.
  3. eth_sendRawTransactionSync vs the 5s REQUEST_TIMEOUT. With 12s blocks, every sync send times out before inclusion. The sim's transport doesn't resend a known tx, so it passes; on a real node this depends on how the node answers a resent known tx.

🤖 Generated with Claude Code

kyscott18 and others added 2 commits November 2, 2026 21:49
The harness ran only monad-revm, with a Monad-only hardfork schedule. A
spec is now a Monad hardfork or an Ethereum one (Merge..Osaka); unpinned,
the chain ID picks it: 143/10143 follow monad-revm's schedule, 1, Sepolia
and Hoodi follow Ethereum's, and the network's EVM (monad-revm or mainnet
revm) is fixed at init.

Simulated gas limits now cover gas spent before refunds and the EIP-7623
calldata floor, which Monad (no refunds) never needed.

The simulation draws `chain.network`: Anvil runs `--network monad
--chain-id 143` or `--chain-id 1 --hardfork osaka --enable-tx-gas-limit`
with 12s blocks, genesis after both activations, and no pinned hardfork.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyscott18 kyscott18 closed this Nov 2, 2026
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.

1 participant