Skip to content

Dev mutation parsing bug: negative numeric params are bitcast into huge u256 values #44

Description

@roninjin10

Summary

hardhat_*/anvil_* state mutation handlers accept JSON integer params through parseU256, but negative integers are bitcast into u256 instead of being rejected. This can turn malformed negative inputs into very large balances/storage/base-fee values.

Why this matters

This is a correctness and safety bug at an RPC boundary: malformed quantity inputs are accepted and interpreted as huge state mutations instead of failing with -32602.

Normative contract

  • docs/specs/json-rpc-contract.md:102 malformed quantities must map to -32602.
  • docs/specs/json-rpc-contract.md:763-767 these mutation methods are part of the contract surface (zevm_setBalance/zevm_setStorageAt with hardhat/anvil aliases).

Evidence

Handlers rely on parseU256:

  • src/rpc/dev_handlers.zig:31-40 (handleHardhatSetBalance)
  • src/rpc/dev_handlers.zig:69-79 (handleHardhatSetStorageAt)
  • src/rpc/dev_handlers.zig:93-101 (handleHardhatSetNextBlockBaseFeePerGas)

parseU256 integer branch performs signed-to-unsigned bitcast:

  • src/rpc/dev_handlers.zig:135-139
fn parseU256(value: std.json.Value) ?u256 {
    const s = switch (value) {
        .string => |str| str,
        .integer => |i| return @intCast(@as(u256, @bitCast(@as(i256, i)))),
        else => return null,
    };

So an input like -1 becomes 0xffff...ffff (u256::MAX) instead of invalid params.

Suggested scope

  • Reject negative numeric inputs in parseU256 (and normalize numeric parsing semantics to QuantityHex expectations).
  • Add regression tests that negative numeric params for balance/storage/base-fee mutation methods return -32602.
  • Audit all dev-control numeric parsers for the same signed/unsigned conversion pattern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions