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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions