Skip to content

Add eth_call state overrides (closes #12)#54

Merged
koko1123 merged 3 commits intomainfrom
feat/state-overrides
May 1, 2026
Merged

Add eth_call state overrides (closes #12)#54
koko1123 merged 3 commits intomainfrom
feat/state-overrides

Conversation

@koko1123
Copy link
Copy Markdown
Contributor

@koko1123 koko1123 commented May 1, 2026

Summary

Adds Provider.callWithOverrides so simulators can answer "what if?" questions (modified balances, nonces, code, or storage) without forking a node. Maps to the geth-style third parameter of eth_call:

eth_call(transaction, blockTag, stateOverrideObject)

Supported by Anvil, Geth, Reth, Alchemy, Infura, and QuickNode.

New module: src/state_overrides.zig

pub const StateOverrides = struct {
    pub fn setBalance(addr, value) !void
    pub fn setNonce(addr, value) !void
    pub fn setCode(addr, bytecode) !void           // deep-copies the bytes
    pub fn setStorageAt(addr, slot, value) !void   // overlay onto existing state (`stateDiff`)
    pub fn setFullStorage(addr, slot, value) !void // replace state entirely (`state`)
    pub fn serializeJson(allocator) ![]u8
};

setStorageAt feeds the JSON-RPC stateDiff field; setFullStorage feeds state. Multiple addresses, multiple slots, and arbitrary combinations of fields per address are supported.

Provider changes

  • callWithOverrides(to, data, *const StateOverrides) ![]u8
  • formatCallParamsWithOverrides() helper that produces the three-arg eth_call body shape.

Test plan

  • make ci passes (1300+ unit tests)
  • zig build integration-test against Anvil: 21/21 pass, including 3 new tests:
    • code + balance override: deploys an ADDRESS BALANCE return-bytecode shim via setCode, sets a custom balance via setBalance, calls the contract, and verifies the returned 32-byte word is the overridden balance
    • stateDiff: deploys a SLOAD return-bytecode shim, sets storage slot 5 to a sentinel, verifies the returned word
    • empty overrides path matches plain eth_call
  • coderabbit review --prompt-only --type committed --base origin/main: no findings (after addressing two iterations of feedback: defensive errdefer on the setCode copy, and a redundant @constCast in deinit)
  • No std.debug.print in library code, no emojis

Out of scope

  • Composing with batch eth_call (Deprecated allocator initialization + tests fix LLVM crash by AI  #10) -- the batch API takes raw params strings; users can pre-build via formatCallParamsWithOverrides if needed. A typed batch + overrides convenience can be added later.
  • An Override struct-construction API (the issue mentions setStorageAt(pool, slot, value) style which is what we implemented; we did not add a fluent builder)

Closes #12.

koko1123 added 3 commits May 1, 2026 15:46
Adds Provider.callWithOverrides so simulators can answer "what if?"
questions (modified balances, nonces, code, or storage) without forking
a node. Maps to the geth-style third parameter of eth_call:

  eth_call(transaction, blockTag, stateOverrideObject)

Supported by Anvil, Geth, Reth, Alchemy, Infura, and QuickNode.

New module: src/state_overrides.zig

  pub const StateOverrides = struct {
      pub fn setBalance(addr, value) !void
      pub fn setNonce(addr, value) !void
      pub fn setCode(addr, bytecode) !void           // deep-copies the bytes
      pub fn setStorageAt(addr, slot, value) !void   // overlay onto existing state
      pub fn setFullStorage(addr, slot, value) !void // replace state entirely
      pub fn serializeJson(allocator) ![]u8
  };

setStorageAt feeds the JSON-RPC `stateDiff` field; setFullStorage feeds
`state`. Multiple addresses, multiple slots, and arbitrary combinations
of fields per address are supported.

Provider:
- callWithOverrides(to, data, *const StateOverrides) ![]u8
- formatCallParamsWithOverrides() helper that produces the three-arg
  eth_call body shape.

Tests:
- 9 unit tests in state_overrides.zig (empty -> {}, balance / nonce /
  code combined, stateDiff merging, full-state replacement, setCode
  overwrite without leak, multiple addresses, hex encoding edge cases).
- 2 unit tests in provider.zig for formatCallParamsWithOverrides
  (with and without overrides; verifies wire shape).
- 3 integration tests against Anvil:
    - code + balance override (deploy ADDRESS BALANCE return-bytecode,
      verify the overridden balance is observed)
    - stateDiff (deploy SLOAD return-bytecode, verify slot value)
    - empty overrides path matches plain eth_call

All 1300+ unit tests pass; 21/21 integration tests pass against Anvil.

Closes #12.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
eth-zig Ready Ready Preview, Comment May 1, 2026 7:53pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

Warning

Rate limit exceeded

@koko1123 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 45 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c95b544-e2ae-4be7-ae9c-91bfa0c7a55b

📥 Commits

Reviewing files that changed from the base of the PR and between 6cf28b5 and e23f47b.

📒 Files selected for processing (5)
  • README.md
  • src/provider.zig
  • src/root.zig
  • src/state_overrides.zig
  • tests/integration_tests.zig
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/state-overrides

Review rate limit: 0/5 reviews remaining, refill in 3 minutes and 45 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@koko1123 koko1123 merged commit 922aa1c into main May 1, 2026
14 checks passed
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.

eth_call with state overrides

1 participant