Skip to content

feat(gateway): ABI-decode revert data into human-readable API errors - #842

Open
agentotto[bot] wants to merge 7 commits into
mainfrom
feat/gateway-abi-error-decoding
Open

feat(gateway): ABI-decode revert data into human-readable API errors#842
agentotto[bot] wants to merge 7 commits into
mainfrom
feat/gateway-abi-error-decoding

Conversation

@agentotto

@agentotto agentotto Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

ABI-decode World ID registry reverts in the gateway so API callers receive stable error codes and human-readable messages instead of opaque selector hex.

Changes

  • Decode and validate revert data using the sol!-generated WorldIdRegistryV2Errors variants.
  • Map typed variants to GatewayErrorCode and WorldID:-prefixed messages without string-based dispatch or selector scanning.
  • Apply decoding to request simulation, registry reads, and batch submission failures.
  • Preserve undecodable errors as generic bad_request responses with their original message.

Validation

  • Gateway library tests and Clippy pass.
  • Integration test target compiles; duplicate-authenticator assertions use the stable error code.

Linear: PROTO-4873


Note

Medium Risk
Changes how all on-chain failure paths surface to API clients and async batch status; behavior is improved but any mapping gap could misclassify reverts as generic bad_request.

Overview
Replaces string/selector hex scanning for World ID registry failures with ABI decoding of revert data via WorldIdRegistryV2Errors, so clients get stable GatewayErrorCode values and WorldID:-prefixed messages instead of opaque RPC blobs.

A new contract_errors module decodes revert bytes from alloy transport and contract errors, maps variants to codes and human text (including V2 recovery and broader registry errors), and leaves undecodable failures as generic bad requests with the original message. GatewayErrorResponse drops from_simulation_error / parse_contract_error in favor of from_rpc_error, from_contract_error, and from_decoded_revert. Simulation (validation), is_valid_root reads, and batch submit failures all use this path; the gateway hex dependency is removed. Unit tests use test-case; integration tests assert authenticator_already_exists on duplicate-authenticator flows.

Reviewed by Cursor Bugbot for commit 731cf58. Bugbot is set up for automated code reviews on this repo. Configure here.

The gateway previously surfaced raw RPC errors (hex-encoded custom-error
selectors buried in JSON-RPC messages) directly to API callers. Add
structured ABI decoding of revert data so callers see stable, meaningful
error messages instead of opaque hex.

Changes
- New `contract_errors` module: decodes revert data against the V1 and
  V2 WorldIDRegistry ABIs (via the `sol!`-generated `*Errors` enums'
  `name_by_selector`), then maps the recognised variant to a
  `GatewayErrorCode` and a human-readable message. V2 is tried first so
  richer V2-only variants (e.g. `RecoveryAgentUpdateWindowExpired`)
  win when a shared selector matches both ABIs.
- `GatewayErrorResponse`: adds `from_rpc_error` (for
  `RpcError<TransportErrorKind>` from `provider.call`) and
  `from_contract_error` (for `alloy::contract::Error` from
  `sol!`-generated builders). Both attempt structured decoding first
  and fall back to the existing string-matching `from_simulation_error`
  path when revert data is absent or unknown.
- `simulate_calldata` (validation) and `is_valid_root` now use the
  structured decoders, so simulation failures surface as e.g.
  `{"code": "authenticator_already_exists", "message": "WorldID:
  authenticator address is already in use by another account"}`
  instead of `0x…` hex.
- Batcher: when `send_batch` fails, decode revert data before falling
  back to the legacy string scan, so the recorded `Failed` state
  carries a decoded message and correct `GatewayErrorCode`.
- `parse_contract_error` retained (and unit-tested) as the string-based
  fallback for paths where structured errors aren't available.

Tests
- 9 unit tests in `contract_errors` covering V1-only, V2-only, and
  shared selectors; short/unknown data; the `selector_hex` helper.
- 4 unit tests in `error` covering the fallback string-matching path
  and the new `from_decoded_revert` constructor.

PROTO-4873

Co-authored-by: Otto <otto@toolsforhumanity.com>
@agentotto
agentotto Bot requested a review from a team as a code owner July 7, 2026 13:16

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6a4ff7c. Configure here.

Comment thread services/gateway/src/error.rs
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