Skip to content

ethereum.decode() behavioral change in 0.42.0: ethabi whitespace parsing bug no longer masks subgraph errors #6461

Closed

Description

@madumas

Summary

The migration from ethabi to alloy in graph-node 0.42.0 (PR #6063) fixes a long-standing parsing bug in ethabi that silently decoded incorrect types when whitespace was present in ethereum.decode() type strings. This causes subgraphs with pre-existing bugs to fail on 0.42.0 where they previously appeared to work.

Specifically, ethabi::param_type::Reader::read(" address") (with a leading space) returned Uint(8) instead of Address. Alloy correctly parses " address" as Address. Subgraphs that relied on this wrong type to call .toBigInt() on address values now abort.

Affected subgraphs

An ERC-4337 account abstraction indexer (WASM QmX1PEqGky924qHWEi62wVoCQkjUHkkHMZXtrAGiBptyY1) deployed on 6 chains:

Deployment Network Fails at block
QmTfNJcEqPAhVSDNqDvVQFaDoKpcZXhndPt8Yqmhqax15H Gnosis 27,054,017
QmRMTqyq4MF8hQbZm2rh4kyt288RDihrt6L5LyRfJA6uB8 Fantom 59,007,732
QmeBrPAc2KZrfopxCiKHZV5QH2qHkwdjbmFLsuP4x4wQRq BSC not yet hit
QmRxWZUuUj2YUAdAormTjaFrmuXFz5wxLoP7UCvKcNhFUE Optimism not yet hit
QmWFAFmcKXaksfC1TpDDr8dJHt6gjJcEWKLowEyKnKoxoT Mainnet not yet hit
QmPqHW8mpD8nU3t1LNkTd8wEdEExpe5tbfKyXxGWwXQ6v5 Base not yet hit

All 6 are healthy on graph-node < 0.42. A scan of 1,119 unique WASM files across our indexer confirmed this is the only WASM with this specific pattern.

Error:

Mapping aborted at ~lib/@graphprotocol/graph-ts/chain/ethereum.ts, line 83, column 7,
with message: Ethereum value is not an int or uint.
in handler `handleUserOperationEventV5`

Root cause

The subgraph calls ethereum.decode() with a type string containing a space before address:

ethereum.decode(
  "((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[], address)",
  //                                                                                     ^ space
  data
)

Then accesses the beneficiary as tuple[1].toBigInt().

ethabi (< 0.42.0): Reader::read does not recognize " address" (with leading space) and falls back to Uint(8). tuple[1] has kind Uint → .toBigInt() succeeds.

alloy (>= 0.42.0): Correctly parses " address" as Address. tuple[1] has kind Address → .toBigInt() aborts.

ethabi::param_type::Reader::read(" address")  // => Ok(Uint(8))  — wrong
" address".parse::<DynSolType>()              // => Ok(Address)  — correct

The subgraph has a latent bug (address → BigInt → address round-trip) that only worked because ethabi's parsing bug accidentally decoded the beneficiary as Uint(8).

Reproduction

Full test with real transaction calldata: https://github.com/ellipfra/abi-decode-test

cargo test -- --nocapture

Key output:

ethabi with ' address' (space):
  Parsed type: Tuple([Array(Tuple([...])), Uint(8)])
  tuple[1] kind = Uint ← ethabi decoded ' address' as Uint(8)!
  tuple[1].toBigInt() = Ok("✓ 982702592990646225178390519836158331213355178571")

alloy with ' address' (space):
  Parsed type: Tuple([Array(Tuple([...])), Address])
  tuple[1] kind = Address ← alloy correctly parses ' address'
  tuple[1].toBigInt() = Err("✗ not int/uint — THIS IS THE CRASH")

Can graph-node provide backwards compatibility?

No. We investigated:

  1. Strip whitespace from type strings: Does not help — alloy already handles whitespace correctly inside tuple context and returns Address. The subgraph would still fail at .toBigInt().
  2. Replicate ethabi's parsing bug: " address" → Uint(8) is fundamentally wrong.
  3. Auto-convert Address to BigInt in .toBigInt(): Would change WASM API semantics and mask bugs in all subgraphs.

The subgraph needs to be recompiled (use .toAddress() instead of .toBigInt() for the beneficiary field).

Recommendation

Consider documenting this as a known behavioral change in the 0.42.0 release notes. Other subgraphs may have similar latent bugs where whitespace in ethereum.decode() type strings caused ethabi to produce wrong types that happened to work by accident.

For subgraph developers

If you encounter "Ethereum value is not an int or uint" after upgrading to graph-node 0.42.0:

  1. Check your ethereum.decode() type strings for whitespace
  2. Verify that you're using the correct accessor (.toAddress() for addresses, .toBigInt() for integers)
  3. Remove any unnecessary type conversions (address → BigInt → address)

Activity

  1. madumas commented on Mar 29, 2026

    @madumas
    Author

    Additional affected deployments found

    A full scan of our indexer's Redis IPFS cache (15,065 WASM files, 45,937 IPFS keys) identified 11 total deployments using the affected WASM, not just 6:

    Mainnets (7):

    Deployment Network
    QmeBrPAc2KZrfopxCiKHZV5QH2qHkwdjbmFLsuP4x4wQRq BSC
    QmRxWZUuUj2YUAdAormTjaFrmuXFz5wxLoP7UCvKcNhFUE Optimism
    QmWFAFmcKXaksfC1TpDDr8dJHt6gjJcEWKLowEyKnKoxoT Mainnet
    QmTfNJcEqPAhVSDNqDvVQFaDoKpcZXhndPt8Yqmhqax15H Gnosis
    QmRMTqyq4MF8hQbZm2rh4kyt288RDihrt6L5LyRfJA6uB8 Fantom
    QmPqHW8mpD8nU3t1LNkTd8wEdEExpe5tbfKyXxGWwXQ6v5 Base
    QmaARoKJAsbsSPFRLH8DkGpPNEFqwVE8AtwYHhSFn4LeTk Arbitrum One

    Testnets (4):

    Deployment Network
    QmWPwxV7qmBzjuSecBWCTsRFcnStJnYeUFH4KQgYcRbjcw Optimism Sepolia
    Qmb9wDg1Efzg1BhgFPwgFC82u9hJCCCg7EqqpKq5K8s5vG Arbitrum Sepolia
    QmXni4hYDfpVREzmEyAWLr9xs3Ew2CeoFSmucbNPaebwsj Celo Alfajores
    QmQ42dPbP9YM7Ycmw9fdjvXJLVLiZQpEqesAGCd1xyDz6y Base Sepolia

    All 11 share the same WASM mapping (QmX1PEqGky924qHWEi62wVoCQkjUHkkHMZXtrAGiBptyY1) and the same 3 EntryPoint contract addresses (v0.5, v0.6, v0.7).

    A second, older version of the same WASM (Qmedt2CVgKYvA1Np64Gdx2mcgk4JbkQtskxgETzTbmr8Gd, 92KB vs 94KB) was also found in cache with the identical ", address" whitespace bug, but no manifest referencing it remains cached.

  2. incrypto32 commented on May 18, 2026

    @incrypto32
    Contributor

    Thanks for the thorough investigation. Agreed there's no backwards-compatible fix on the graph-node side. Ive created #6572 to add this to NEWS md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions