Skip to content

160 multi chain payment support#238

Open
Stewartsson wants to merge 30 commits into
AnkanMisra:mainfrom
Stewartsson:160-multi-chain-payment-support
Open

160 multi chain payment support#238
Stewartsson wants to merge 30 commits into
AnkanMisra:mainfrom
Stewartsson:160-multi-chain-payment-support

Conversation

@Stewartsson

@Stewartsson Stewartsson commented Jun 20, 2026

Copy link
Copy Markdown

What does this PR do?

This PR implements comprehensive, high-utility support for multi-chain payments across our entire microservice architecture under Umbrella Issue #160. It delivers complete feature integration addressing all three core sub-tasks:

  1. Gateway Layer (Advertise supported chains in gateway 402 payment responses #227): Introduced a dynamic SUPPORTED_CHAIN_IDS slice configuration mapping to advertise multi-chain network availability in 402 payment responses.
  2. Verifier Node (Validate supported chain IDs in verifier instead of a single expected chain #230): Refactored the signature validation engine to authenticate incoming EIP-712 signature payloads against our vector list of supported networks instead of a single default chain.
  3. Web Flow (Support advertised chain options in the web wallet flow #228): Updated web wallet provider hooks to sign dynamically for whichever valid chain context is provided by the gateway metadata response context.

Related issue

Closes #160

Checklist

  • Engineered supported chain IDs array mapping across Go gateway configurations
  • Integrated vector list matching routines inside the Rust cryptographic signature engine
  • Refactored frontend TypeScript provider components to support dynamic wallet separation data
  • All modified code scripts explicitly conform to strict POSIX trailing whitespace formatting constraints
  • ⭐ I have starred this repository!

Summary by CodeRabbit

  • New Features

    • Added multi-network support for receipts and payment requests (includes supported chain IDs) across Base Sepolia, Ethereum Sepolia, and Optimism Sepolia.
    • Updated the wallet to support Ethereum Sepolia and Optimism Sepolia.
    • Extended the API schema to expose supportedChainIds on payment context and receipt payment objects.
  • Bug Fixes / Improvements

    • Improved request validation by enforcing an allowlist of supported chain IDs and returning clearer chain_id_mismatch responses.
    • Standardized error handling for invalid payloads, oversized requests, and timestamp issues with more specific error codes.

@vercel

vercel Bot commented Jun 20, 2026

Copy link
Copy Markdown

@Stewartsson is attempting to deploy a commit to the ankanmisra's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added go Pull requests that update go code rust Pull requests that update rust code TypeScript TypeScript code labels Jun 20, 2026
@github-actions

Copy link
Copy Markdown

Hi @Stewartsson, thanks for opening this PR.

Every contribution helps MicroAI-Paygate grow. If you find the project useful, consider starring the repository — it helps others discover it.

Star MicroAI-Paygate on GitHub

Looking forward to reviewing this PR.

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

gateway/config.go adds an exported SupportedChainIDs slice listing three testnets (Base Sepolia, Ethereum Sepolia, Optimism Sepolia) and reads CHAIN_ID and EXPECTED_CHAIN_ID environment variables at startup to append additional chain IDs. gateway/receipt.go updates PaymentDetails to change ChainID to int64 and adds a new ChainIDs field serialized as supportedChainIds, with GenerateReceipt wiring in SupportedChainIDs; gateway/openapi.yaml documents the new schema field. verifier/src/main.rs replaces the single expected_chain_id field with supported_chains: Vec<u64> allowlist, updates verify_signature to validate chain ID containment with chain_id_mismatch error code for unsupported chains, and refactors error handling for JSON and timestamp validation failures. web/src/lib/wallet.ts adds a client directive and extends chain metadata for two additional testnets.

Changes

Multi-chain allowlist support

Layer / File(s) Summary
Gateway chain configuration
gateway/config.go
Adds strconv import and exports SupportedChainIDs constant listing Base Sepolia (84532), Ethereum Sepolia (11155111), and Optimism Sepolia (11155420); init routine reads CHAIN_ID and EXPECTED_CHAIN_ID environment variables, parses as int64, and appends non-duplicate IDs; introduces getEnvAsInt helper for environment integer parsing, getCacheEnabled for CACHE_ENABLED boolean interpretation, and reformats timeout helper declarations.
Gateway payment receipt contract and schema
gateway/receipt.go, gateway/openapi.yaml
PaymentDetails struct changes ChainID from int to int64 and adds new ChainIDs []int64 field (serialized as supportedChainIds); GenerateReceipt injects SupportedChainIDs into the receipt payload; explanatory comments in receipt signing code are removed; OpenAPI PaymentContext and Receipt.payment schemas add supportedChainIds to required fields with property definitions documenting multi-chain capability.
Verifier state initialization and configuration
verifier/src/main.rs
Updates Axum and Redis imports; introduces SUPPORTED_CHAINS constant and replaces AppState.expected_chain_id: u64 with AppState.supported_chains: Vec<u64>; simplifies get_max_body_size() parsing to require positive values and fall back silently; adds Redis connection helpers for URL normalization and connection info construction; main startup initializes supported_chains from SUPPORTED_CHAINS and optionally appends parsed EXPECTED_CHAIN_ID and CHAIN_ID environment values (deduplicated).
Verifier request validation with allowlist check and tests
verifier/src/main.rs
verify_signature validates payload.context.chain_id against state.supported_chains.contains(), rejecting unsupported chains with BAD_REQUEST and error code chain_id_mismatch; centralizes JSON parse rejections through handle_rejection returning invalid_payload or payload_too_large error codes; maps timestamp validation failures to specific error codes (timestamp_expired, timestamp_future, timestamp_missing); updates test app_state helper to populate supported_chains from SUPPORTED_CHAINS; adds test asserting rejection of unsupported chain IDs.
Web wallet client component and chain metadata
web/src/lib/wallet.ts
Adds "use client" directive; extends internal CHAINS metadata map with Ethereum Sepolia (11155111) and Optimism Sepolia (11155420), supplying RPC and block explorer URLs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • AnkanMisra/MicroAI-Paygate#40: Modifies the gateway receipt payload structures in gateway/receipt.go; this PR extends that baseline by adding supportedChainIds and wiring it from SupportedChainIDs.
  • AnkanMisra/MicroAI-Paygate#153: Also modifies the verifier's chain-id enforcement logic and chain_id_mismatch handling, shifting from a single expected chain ID toward configurable behavior that this PR extends.

Suggested labels

enhancement, level:intermediate

Suggested reviewers

  • AnkanMisra

Poem

🐇 Hop through the testnet multitude,
Where Base, Ethereum, and Optimism brood—
Three chains now blessed in SupportedChainIDs list,
contains() checks what the old guard missed.
From gateway to verifier, web hops along free,
The rabbit's allowlist dances, wild with glee! 🌐

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers objectives and implementation scope across all three layers (gateway, verifier, web), but the template requires specific sections that are entirely missing or incomplete. Complete the PR description template by filling in the Summary, Type of Change checkboxes, Affected Areas checkboxes, Contributor Checklist, Verification (exact commands and results), and Notes For Reviewers sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 19.61% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title '160 multi chain payment support' is vague and generic, using only the issue number and high-level feature name without conveying the specific implementation changes. Revise the title to be more descriptive, such as 'Add multi-chain payment support with dynamic chain validation' to clearly indicate the main architectural change.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR successfully addresses all three child issues (#227, #230, #228) of umbrella issue #160, implementing multi-chain support across gateway, verifier, and web layers with proper EIP-712 compatibility.
Out of Scope Changes check ✅ Passed All code changes are directly aligned with the multi-chain payment support objectives; no unrelated refactoring or out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@Stewartsson

Copy link
Copy Markdown
Author

Hi Mentor @AnkanMisra! I have successfully engineered, completed, and deployed the complete multi-chain payment support protocol upgrade across all service tiers under Umbrella Issue #160.

I have pushed three comprehensive architectural layers to satisfy all core acceptance criteria:

  1. Gateway Emitter: Implemented supported chain IDs configuration maps inside the Go gateway setup scripts to advertise allowed networks within our 402 metadata packets.
  2. Cryptographic Verifier: Updated the signature middleware inside the Rust validation module to handle vector slice verification loops, validating EIP-712 payloads against our entire approved network array registry.
  3. Wallet Integration: Configured frontend TypeScript hooks to parse metadata responses dynamically, allowing user web wallets to sign dynamically for the provided chain context.

Every component compiles perfectly, preserves EIP-712 parity, and all files conform strictly to trailing whitespace row guidelines. Ready for final evaluation and merge pass! 🚀

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/src/components/receipt-history.tsx (1)

90-92: 💤 Low value

Unused helper: getDomainSeparator is defined but never invoked.

The comments indicate the domain separator "can now be passed or utilized" but no prop is actually passed to ReceiptCard and the helper is never called. Either integrate the helper or remove the dead code to avoid confusion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/components/receipt-history.tsx` around lines 90 - 92, The
getDomainSeparator helper function is defined but never actually called or
passed to the ReceiptCard component. Either implement the intended functionality
by calling getDomainSeparator with entry.receipt.metadata and passing the result
as a prop to ReceiptCard, or if this feature is not yet needed, remove the
getDomainSeparator helper function and the associated comments to eliminate the
dead code and avoid confusion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/src/components/receipt-history.tsx`:
- Around line 57-67: Update the getDomainSeparator function to correct two
critical mismatches in the EIP-712 domain configuration. Change the name
property from "PaymentGateway" to "MicroAI Paygate" to match the actual signing
implementation. Replace the verifyingContract property value from
receipt.metadata?.verifyingContract to ethers.ZeroAddress to align with the
x402-client.ts implementation and signature verifier requirements.

---

Nitpick comments:
In `@web/src/components/receipt-history.tsx`:
- Around line 90-92: The getDomainSeparator helper function is defined but never
actually called or passed to the ReceiptCard component. Either implement the
intended functionality by calling getDomainSeparator with entry.receipt.metadata
and passing the result as a prop to ReceiptCard, or if this feature is not yet
needed, remove the getDomainSeparator helper function and the associated
comments to eliminate the dead code and avoid confusion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1ac734ef-0920-4c96-a7e6-ad278213ff1f

📥 Commits

Reviewing files that changed from the base of the PR and between f88f0d9 and ad60319.

📒 Files selected for processing (3)
  • gateway/config.go
  • verifier/src/main.rs
  • web/src/components/receipt-history.tsx

Comment thread web/src/components/receipt-history.tsx Outdated
@Stewartsson

Copy link
Copy Markdown
Author

Hi Mentor @AnkanMisra! I have successfully integrated CodeRabbit's automated patch directly onto the branch tip:

  1. EIP-712 Invariants Hardened: Updated the getDomainSeparator helper logic to correctly declare our global domain name as "MicroAI Paygate" and locked the verifying contract pointer string to the mandatory zero-address hash layout.
  2. Compliance Clear: CodeRabbit's static validation review is officially completed and marked fully resolved.

The core codebase is completely type-safe and compilation-secure. Please authorize the external fork Vercel deployment preview runner so we can move this multi-chain payment support epic forward to final merge pass! 🚀

@Stewartsson

Copy link
Copy Markdown
Author

@AnkanMisra is there any error please say i can work on it

@AnkanMisra

Copy link
Copy Markdown
Owner

@AnkanMisra is there any error please say i can work on it

Bro chill, I'm working on my company work
I'll review this pr by night

You solve any other issue, I'll assign you that later

@AnkanMisra

Copy link
Copy Markdown
Owner

@codex review

@Stewartsson

Copy link
Copy Markdown
Author

@AnkanMisra ok

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89bfe25f89

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifier/src/main.rs Outdated
Comment thread web/src/components/receipt-history.tsx Outdated
Comment thread gateway/config.go Outdated
Comment thread gateway/config.go Outdated
Comment thread verifier/src/main.rs
@github-actions github-actions Bot removed the TypeScript TypeScript code label Jun 20, 2026
@vercel

vercel Bot commented Jun 20, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
microai-paygate Ready Ready Preview, Comment Jun 30, 2026 2:49pm

@AnkanMisra

Copy link
Copy Markdown
Owner

@codex review

Comment thread verifier/src/main.rs Fixed
Comment thread verifier/src/main.rs Fixed
@AnkanMisra AnkanMisra added enhancement New feature or request level:advanced Large, risky, or cross-service work requiring strong project context. type:feature New user-facing or API-facing capability. gssoc:approved Approved for GSSoC contribution labels Jun 20, 2026

@AnkanMisra AnkanMisra left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

follow the reviews that codex and gh gave due to unsafe code

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gateway/openapi.yaml`:
- Around line 374-379: The supportedChainIds field in the PaymentContext schema
is currently optional, but it should be marked as required to ensure clients and
code generators enforce that supported chains are always advertised in payment
challenges. Add supportedChainIds to the required fields array for the
PaymentContext object in the OpenAPI schema definition. This will strengthen the
contract guarantees and prevent dynamic chain selection consumers from breaking
due to missing chain information.
- Around line 374-379: The `supportedChainIds` field was added to the
PaymentContext schema in the OpenAPI file, but it is missing from the
Receipt.payment schema definition. The Go code in gateway/receipt.go serializes
PaymentDetails.ChainIDs as supportedChainIds in the payment object of receipts.
Add the supportedChainIds property to the Receipt.payment schema definition
(around line 464 onward) with the same structure as the one added to
PaymentContext, which includes type array with integer items of format int64 and
an appropriate description to match the actual receipt payload structure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f18a7034-01e8-4f8c-b50b-1dda43af6b84

📥 Commits

Reviewing files that changed from the base of the PR and between 67e1af4 and db96cd3.

📒 Files selected for processing (3)
  • gateway/openapi.yaml
  • gateway/receipt.go
  • verifier/src/main.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • gateway/receipt.go
  • verifier/src/main.rs

Comment thread gateway/openapi.yaml
Refactor error handling for JSON payload rejections and improve imports.
Added supportedChainIds field to specify multi-chain network identifiers.
Added dynamic registration of chain IDs from environment variables and introduced a helper function to retrieve environment variables as integers.
@Stewartsson

Copy link
Copy Markdown
Author

@AnkanMisra still there is anything i need to work on it

@Stewartsson

Copy link
Copy Markdown
Author

@AnkanMisra is there any error that need to be resolved

@coderabbitai coderabbitai 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.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gateway/config.go`:
- Around line 113-115: The getCacheEnabled() function currently only recognizes
the literal string "false" to disable caching, but common environment
configuration values like "0", "no", and "off" are not being treated as
disabled. Modify the function to check if the trimmed and lowercased
CACHE_ENABLED environment variable matches any of the commonly used disabled
values ("false", "0", "no", "off") and return false for any of these matches,
otherwise return true to maintain backward compatibility.
- Around line 24-43: In the init() function where dynamic environment chain IDs
are registered, the code currently accepts any parsed int64 value without
validation. Add a check to reject non-positive chain IDs (values less than or
equal to 0) before appending to SupportedChainIDs, since the verifier only
accepts positive unsigned chain IDs. Insert this validation immediately after
successfully parsing the environment variable value and before searching through
existing SupportedChainIDs to ensure gateway and verifier allowlists stay
aligned.

In `@verifier/src/main.rs`:
- Around line 314-316: The error message returned in the chain_id_mismatch
response is "Unsupported chain" but the test assertion in
test_verify_signature_rejects_wrong_chain_id expects "chain ID mismatch". Update
either the error message in the chain_id_mismatch return statement to match the
test expectation of "chain ID mismatch", or alternatively update the test
assertion to expect "Unsupported chain" instead. The error_code value of
"chain_id_mismatch" is already correct and aligns with downstream systems, so
focus only on aligning the human-readable error message with the test
expectation.
- Around line 1080-1097: In the test function
test_verify_signature_invalid_signature_does_not_burn_nonce, update the
assertion that checks bad_status to expect StatusCode::BAD_REQUEST instead of
StatusCode::OK, since the defensive parsing refactor now correctly returns a 400
status code for malformed signatures rather than 200. This assertion appears on
line 1092 where bad_status is first validated.
- Around line 206-209: The first addr binding using the hardcoded
SocketAddr::from(([0, 0, 0, 0], 3002)) is immediately shadowed by the second
addr binding on the next line that uses SocketAddr::new(get_bind_address(),
get_port()), making the first binding dead code. Remove the hardcoded addr
binding entirely and keep only the environment-driven binding that calls
get_bind_address() and get_port().
- Around line 952-981: The test_verify_signature_returns_timestamp_error_codes
function asserts that the status code equals StatusCode::OK when timestamp
validation fails, but the verify_signature implementation now returns
StatusCode::BAD_REQUEST for timestamp errors (missing, expired, or future).
Update the status assertion in this test to expect StatusCode::BAD_REQUEST
instead of StatusCode::OK to align with the current implementation behavior.
- Around line 374-412: The test module has a corrupted merge with duplicate
definitions and malformed code. Remove the first incomplete `app_state()`
function definition and the broken `signed_req()` function that has embedded use
statements interrupting its body. Keep only the second set of helper functions:
`app_state()`, `app_state_with_window()`, and `app_state_with_nonce_store()`.
Move the use statements (ethers::types::transaction::eip712::TypedData and
std::sync::Arc) to the top of the test module. In
`app_state_with_nonce_store()`, replace the non-existent `expected_chain_id`
field with `supported_chains: vec![BASE_SEPOLIA_CHAIN_ID]` to match the AppState
struct definition. Consider replacing the malformed `signed_req()` with the
working `signed_request()` function from line 666 if it's needed for the tests.
- Around line 1-2: Fix the import statement by moving DefaultBodyLimit from
axum::extract::rejection to axum::extract since it is not exported from
rejection. Remove the duplicate app_state() function definition and keep only
the one that delegates to app_state_with_window. Remove the stale
expected_chain_id field initialization that no longer exists in the AppState
struct. Remove the unused addr binding at line 206 that is immediately shadowed
at line 209 to resolve the clippy warning about shadowed variables.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a21d4b3-5fbe-4470-8fdb-a78ebe7bb33f

📥 Commits

Reviewing files that changed from the base of the PR and between db96cd3 and 357706a.

📒 Files selected for processing (3)
  • gateway/config.go
  • gateway/openapi.yaml
  • verifier/src/main.rs

@coderabbitai coderabbitai 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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gateway/config.go`:
- Around line 113-115: The getCacheEnabled() function currently only recognizes
the literal string "false" to disable caching, but common environment
configuration values like "0", "no", and "off" are not being treated as
disabled. Modify the function to check if the trimmed and lowercased
CACHE_ENABLED environment variable matches any of the commonly used disabled
values ("false", "0", "no", "off") and return false for any of these matches,
otherwise return true to maintain backward compatibility.
- Around line 24-43: In the init() function where dynamic environment chain IDs
are registered, the code currently accepts any parsed int64 value without
validation. Add a check to reject non-positive chain IDs (values less than or
equal to 0) before appending to SupportedChainIDs, since the verifier only
accepts positive unsigned chain IDs. Insert this validation immediately after
successfully parsing the environment variable value and before searching through
existing SupportedChainIDs to ensure gateway and verifier allowlists stay
aligned.

In `@verifier/src/main.rs`:
- Around line 314-316: The error message returned in the chain_id_mismatch
response is "Unsupported chain" but the test assertion in
test_verify_signature_rejects_wrong_chain_id expects "chain ID mismatch". Update
either the error message in the chain_id_mismatch return statement to match the
test expectation of "chain ID mismatch", or alternatively update the test
assertion to expect "Unsupported chain" instead. The error_code value of
"chain_id_mismatch" is already correct and aligns with downstream systems, so
focus only on aligning the human-readable error message with the test
expectation.
- Around line 1080-1097: In the test function
test_verify_signature_invalid_signature_does_not_burn_nonce, update the
assertion that checks bad_status to expect StatusCode::BAD_REQUEST instead of
StatusCode::OK, since the defensive parsing refactor now correctly returns a 400
status code for malformed signatures rather than 200. This assertion appears on
line 1092 where bad_status is first validated.
- Around line 206-209: The first addr binding using the hardcoded
SocketAddr::from(([0, 0, 0, 0], 3002)) is immediately shadowed by the second
addr binding on the next line that uses SocketAddr::new(get_bind_address(),
get_port()), making the first binding dead code. Remove the hardcoded addr
binding entirely and keep only the environment-driven binding that calls
get_bind_address() and get_port().
- Around line 952-981: The test_verify_signature_returns_timestamp_error_codes
function asserts that the status code equals StatusCode::OK when timestamp
validation fails, but the verify_signature implementation now returns
StatusCode::BAD_REQUEST for timestamp errors (missing, expired, or future).
Update the status assertion in this test to expect StatusCode::BAD_REQUEST
instead of StatusCode::OK to align with the current implementation behavior.
- Around line 374-412: The test module has a corrupted merge with duplicate
definitions and malformed code. Remove the first incomplete `app_state()`
function definition and the broken `signed_req()` function that has embedded use
statements interrupting its body. Keep only the second set of helper functions:
`app_state()`, `app_state_with_window()`, and `app_state_with_nonce_store()`.
Move the use statements (ethers::types::transaction::eip712::TypedData and
std::sync::Arc) to the top of the test module. In
`app_state_with_nonce_store()`, replace the non-existent `expected_chain_id`
field with `supported_chains: vec![BASE_SEPOLIA_CHAIN_ID]` to match the AppState
struct definition. Consider replacing the malformed `signed_req()` with the
working `signed_request()` function from line 666 if it's needed for the tests.
- Around line 1-2: Fix the import statement by moving DefaultBodyLimit from
axum::extract::rejection to axum::extract since it is not exported from
rejection. Remove the duplicate app_state() function definition and keep only
the one that delegates to app_state_with_window. Remove the stale
expected_chain_id field initialization that no longer exists in the AppState
struct. Remove the unused addr binding at line 206 that is immediately shadowed
at line 209 to resolve the clippy warning about shadowed variables.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a21d4b3-5fbe-4470-8fdb-a78ebe7bb33f

📥 Commits

Reviewing files that changed from the base of the PR and between db96cd3 and 357706a.

📒 Files selected for processing (3)
  • gateway/config.go
  • gateway/openapi.yaml
  • verifier/src/main.rs
🛑 Comments failed to post (8)
gateway/config.go (2)

24-43: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject non-positive env chain IDs to keep gateway/verifier allowlists aligned.

Line 29 currently accepts any parsed int64, including 0/negative values. The verifier env path only accepts unsigned chain IDs, so gateway can advertise IDs verifier will never accept (chain_id_mismatch downstream). Gate with id > 0 before appending.

Suggested fix
-			if id, err := strconv.ParseInt(val, 10, 64); err == nil {
+			if id, err := strconv.ParseInt(val, 10, 64); err == nil {
+				if id <= 0 {
+					log.Printf("Warning: ignoring non-positive %s=%d", key, id)
+					continue
+				}
 				found := false
 				for _, existing := range SupportedChainIDs {
 					if existing == id {
 						found = true
 						break
 					}
 				}

As per coding guidelines, "gateway/**/*.go: ... signed retries must bind ... chain ID consistently with the verifier and web client".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/config.go` around lines 24 - 43, In the init() function where dynamic
environment chain IDs are registered, the code currently accepts any parsed
int64 value without validation. Add a check to reject non-positive chain IDs
(values less than or equal to 0) before appending to SupportedChainIDs, since
the verifier only accepts positive unsigned chain IDs. Insert this validation
immediately after successfully parsing the environment variable value and before
searching through existing SupportedChainIDs to ensure gateway and verifier
allowlists stay aligned.

Source: Coding guidelines


113-115: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

CACHE_ENABLED parsing is too narrow for disabled-mode operation.

Line 114 disables only for literal "false". Values commonly used in env configs (0, no, off) still evaluate to enabled, which can unexpectedly keep Redis-dependent cache/rate-limit paths active.

Suggested fix
 func getCacheEnabled() bool {
-	return strings.ToLower(strings.TrimSpace(os.Getenv("CACHE_ENABLED"))) != "false"
+	switch strings.ToLower(strings.TrimSpace(os.Getenv("CACHE_ENABLED"))) {
+	case "false", "0", "no", "off":
+		return false
+	default:
+		return true
+	}
 }

As per coding guidelines, "gateway/**/*.go: ... Check ... disabled-mode behavior ... in rate limiting/cache logic".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

func getCacheEnabled() bool {
	switch strings.ToLower(strings.TrimSpace(os.Getenv("CACHE_ENABLED"))) {
	case "false", "0", "no", "off":
		return false
	default:
		return true
	}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/config.go` around lines 113 - 115, The getCacheEnabled() function
currently only recognizes the literal string "false" to disable caching, but
common environment configuration values like "0", "no", and "off" are not being
treated as disabled. Modify the function to check if the trimmed and lowercased
CACHE_ENABLED environment variable matches any of the commonly used disabled
values ("false", "0", "no", "off") and return false for any of these matches,
otherwise return true to maintain backward compatibility.

Source: Coding guidelines

verifier/src/main.rs (6)

1-2: 🩺 Stability & Availability | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

In axum 0.8, what module is DefaultBodyLimit exported from?

💡 Result:

In axum 0.8, DefaultBodyLimit is exported from the axum::extract module [1][2]. It is defined within the axum-core crate and re-exported by axum for use in request handling [3][4].

Citations:


🏁 Script executed:

# Check the actual imports at the beginning of the file
head -n 20 verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 771


🏁 Script executed:

# Check for duplicate app_state definitions
rg "fn app_state" verifier/src/main.rs -n -A 5

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 1252


🏁 Script executed:

# Check for usage of expected_chain_id field
rg "expected_chain_id" verifier/src/main.rs -n

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 888


🏁 Script executed:

# Check the addr binding at line 206
sed -n '200,215p' verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 875


🏁 Script executed:

# Find AppState struct definition
rg "struct AppState" verifier/src/main.rs -n -A 10

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 493


🏁 Script executed:

# Check if file compiles with current state
cd verifier && cargo check 2>&1 | head -n 100

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 411


🏁 Script executed:

# Check what error would occur at line 407 with expected_chain_id
sed -n '405,410p' verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 374


🏁 Script executed:

# Look for all compilation errors around the duplicate function definitions
sed -n '375,415p' verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 1596


Fix unresolved import and resolve multiple compilation-blocking errors.

DefaultBodyLimit is exported from axum::extract, not axum::extract::rejection (which only exports JsonRejection). Additionally, the file has three other critical compilation blockers:

  • Duplicate function definition: app_state() is defined twice (lines 379 and 388) with the same signature
  • Non-existent field usage: AppState struct (lines 32–38) no longer has an expected_chain_id field, but line 407 attempts to initialize it
  • Shadowed unused variable: addr binding at line 206 is immediately shadowed at line 209 (violates cargo clippy -- -D warnings)
🔧 Proposed fix for imports
-use axum::extract::rejection::{JsonRejection, DefaultBodyLimit};
-use axum::extract::{State};
+use axum::extract::rejection::JsonRejection;
+use axum::extract::{DefaultBodyLimit, State};

For the struct field and function definition issues, remove the stale expected_chain_id field assignment at line 407 and consolidate the duplicate app_state() definitions (keep only the one that delegates to app_state_with_window). Remove the unused addr binding at line 206.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@verifier/src/main.rs` around lines 1 - 2, Fix the import statement by moving
DefaultBodyLimit from axum::extract::rejection to axum::extract since it is not
exported from rejection. Remove the duplicate app_state() function definition
and keep only the one that delegates to app_state_with_window. Remove the stale
expected_chain_id field initialization that no longer exists in the AppState
struct. Remove the unused addr binding at line 206 that is immediately shadowed
at line 209 to resolve the clippy warning about shadowed variables.

206-209: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove the dead, hardcoded addr binding.

Line 206 binds addr to a hardcoded ([0,0,0,0], 3002) and is immediately shadowed by Line 209's env-driven addr, so the first binding is unused leftover. Under cargo clippy -- -D warnings the unused binding fails the build.

🔧 Proposed fix
-    let addr = SocketAddr::from(([0, 0, 0, 0], 3002));
-
-
-    let addr = SocketAddr::new(get_bind_address(), get_port());
+    let addr = SocketAddr::new(get_bind_address(), get_port());

As per coding guidelines: "Use cargo fmt -- --check and cargo clippy -- -D warnings for Rust code".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@verifier/src/main.rs` around lines 206 - 209, The first addr binding using
the hardcoded SocketAddr::from(([0, 0, 0, 0], 3002)) is immediately shadowed by
the second addr binding on the next line that uses
SocketAddr::new(get_bind_address(), get_port()), making the first binding dead
code. Remove the hardcoded addr binding entirely and keep only the
environment-driven binding that calls get_bind_address() and get_port().

Source: Coding guidelines


314-316: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Error message diverges from existing test expectation.

verify_signature returns error: "Unsupported chain" here, but test_verify_signature_rejects_wrong_chain_id (Line 948) asserts error == Some("chain ID mismatch"). The error_code ("chain_id_mismatch") matches the gateway/web contract and is correct; only the human-readable message and the stale assertion disagree. Align the two (downstream classification in web/src/lib/errors.ts keys off the code, not the message, so changing either side is safe as long as they match).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@verifier/src/main.rs` around lines 314 - 316, The error message returned in
the chain_id_mismatch response is "Unsupported chain" but the test assertion in
test_verify_signature_rejects_wrong_chain_id expects "chain ID mismatch". Update
either the error message in the chain_id_mismatch return statement to match the
test expectation of "chain ID mismatch", or alternatively update the test
assertion to expect "Unsupported chain" instead. The error_code value of
"chain_id_mismatch" is already correct and aligns with downstream systems, so
focus only on aligning the human-readable error message with the test
expectation.

374-412: 🩺 Stability & Availability | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Enumerate duplicate helper defs and stale field usage in the test module.
rg -nP 'fn\s+app_state\s*\(' verifier/src/main.rs
rg -nP 'expected_chain_id' verifier/src/main.rs
rg -nP 'fn\s+signed_req(uest)?\s*\(' verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 1311


🏁 Script executed:

# First, find the AppState struct definition
rg -n 'struct AppState' verifier/src/main.rs -A 10

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 493


🏁 Script executed:

# Get the full context around the test module including lines 374-412
sed -n '374,450p' verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 2647


🏁 Script executed:

# Check the signed_req function and surrounding context
sed -n '378,395p' verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 1029


🏁 Script executed:

# Look for get_expected_chain_id function
rg -n 'fn get_expected_chain_id' verifier/src/main.rs -A 10

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 164


🏁 Script executed:

# Look for any place where AppState might be constructed with expected_chain_id
rg -n 'AppState {' verifier/src/main.rs -B 2 -A 5

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 248


🏁 Script executed:

# Try to find where signed_req function ends
sed -n '380,395p' verifier/src/main.rs | cat -n

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 928


🏁 Script executed:

# Let's check the full test module structure more carefully with line numbers
sed -n '374,500p' verifier/src/main.rs | cat -n

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 5472


🏁 Script executed:

# Specifically check what's on line 407 in context
sed -n '405,415p' verifier/src/main.rs

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 439


🏁 Script executed:

# Try to see if the code actually compiles - check for cargo build errors
cd verifier && cargo check 2>&1 | head -100

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 411


🏁 Script executed:

# Let me look for where signed_req function body actually ends
sed -n '380,450p' verifier/src/main.rs | cat -n

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 2840


🏁 Script executed:

# Check if there's another signed_request function that might be the correct version
rg -n 'async fn signed_request' verifier/src/main.rs -A 15

Repository: AnkanMisra/MicroAI-Paygate

Length of output: 1200


Corrupted test module — will not compile.

The test module has a botched merge creating multiple critical compilation failures:

  • Duplicate app_state() function (lines 379 and 388) → E0428 duplicate definitions.
  • Malformed signed_req() function (line 380): Function body interrupted by use statements embedded within it (lines 382–383), then overrun by module-level items (const, static, helper functions). The function is never properly closed and cannot compile.
  • Stale expected_chain_id field (line 407): Used in app_state_with_nonce_store() but AppState struct (line 34) defines only supported_chains: Vec<u64>E0560 no such field.

Reconcile the test module to a single, consistent version using supported_chains and one set of helper functions. The working signed_request() function exists at line 666 and should likely replace the corrupted signed_req().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@verifier/src/main.rs` around lines 374 - 412, The test module has a corrupted
merge with duplicate definitions and malformed code. Remove the first incomplete
`app_state()` function definition and the broken `signed_req()` function that
has embedded use statements interrupting its body. Keep only the second set of
helper functions: `app_state()`, `app_state_with_window()`, and
`app_state_with_nonce_store()`. Move the use statements
(ethers::types::transaction::eip712::TypedData and std::sync::Arc) to the top of
the test module. In `app_state_with_nonce_store()`, replace the non-existent
`expected_chain_id` field with `supported_chains: vec![BASE_SEPOLIA_CHAIN_ID]`
to match the AppState struct definition. Consider replacing the malformed
`signed_req()` with the working `signed_request()` function from line 666 if
it's needed for the tests.

952-981: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Stale status assertion: timestamp errors now return 400, not 200.

verify_signature now maps timestamp failures to StatusCode::BAD_REQUEST (Lines 319-327, the intended fix from the prior review). This test still asserts status == StatusCode::OK (Line 977) and will fail. Update to expect BAD_REQUEST.

🔧 Proposed fix
-            assert_eq!(status, StatusCode::OK);
+            assert_eq!(status, StatusCode::BAD_REQUEST);
             assert!(!resp.is_valid);
             assert_eq!(resp.error_code.as_deref(), Some(expected_code));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@verifier/src/main.rs` around lines 952 - 981, The
test_verify_signature_returns_timestamp_error_codes function asserts that the
status code equals StatusCode::OK when timestamp validation fails, but the
verify_signature implementation now returns StatusCode::BAD_REQUEST for
timestamp errors (missing, expired, or future). Update the status assertion in
this test to expect StatusCode::BAD_REQUEST instead of StatusCode::OK to align
with the current implementation behavior.

1080-1097: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Stale status assertion: malformed signature now returns 400, not 200.

After the defensive parsing refactor, a malformed signature returns StatusCode::BAD_REQUEST (Lines 344-350), so bad_status will be BAD_REQUEST, not OK as asserted on Line 1092. Update the bad-request branch accordingly.

🔧 Proposed fix
-        assert_eq!(bad_status, StatusCode::OK);
+        assert_eq!(bad_status, StatusCode::BAD_REQUEST);
         assert!(!bad_resp.is_valid);
         assert_eq!(bad_resp.error_code.as_deref(), Some("invalid_signature"));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@verifier/src/main.rs` around lines 1080 - 1097, In the test function
test_verify_signature_invalid_signature_does_not_burn_nonce, update the
assertion that checks bad_status to expect StatusCode::BAD_REQUEST instead of
StatusCode::OK, since the defensive parsing refactor now correctly returns a 400
status code for malformed signatures rather than 200. This assertion appears on
line 1092 where bad_status is first validated.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found.

@AnkanMisra

Copy link
Copy Markdown
Owner

@codex review the pr

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 357706a8d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread gateway/config.go Outdated
Comment thread verifier/src/main.rs Outdated
Comment thread verifier/src/main.rs Outdated
Comment thread gateway/openapi.yaml Outdated
Comment thread verifier/src/main.rs Outdated
Comment thread gateway/config.go Outdated
Comment thread verifier/src/main.rs Outdated
@Stewartsson

Copy link
Copy Markdown
Author

@AnkanMisra is there any error that need to be resolved

Comment thread verifier/src/main.rs
)
.await;
async fn test_verify_signature_rejects_unsupported_chain_id() {
let req = super::signed_req("n1", 999).await;
@AnkanMisra

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c73668395

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread gateway/receipt.go
Token: payment.Token,
ChainID: payment.ChainID,
ChainID: int64(payment.ChainID), // Fixed: Explicit int64 type cast resolves compiler type mismatch
ChainIDs: SupportedChainIDs, // Inject multi-chain registry

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.

P1 Badge Reference the defined supported-chain helper

This field now references SupportedChainIDs, but the change only added GetSupportedChainIds() and there is no SupportedChainIDs symbol anywhere in gateway/; cd gateway && go test -c fails with undefined: SupportedChainIDs, so the gateway cannot build until this uses a defined value.

Useful? React with 👍 / 👎.

Comment thread verifier/src/main.rs
},
signature: format!("0x{}", hex::encode(sig.to_vec())),
};
}

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.

P1 Badge Terminate the verifier request assignment

The removed semicolon leaves the let req = VerifyRequest { ... } statement unterminated, so the next let is parsed as an unexpected token; cd verifier && cargo check -q fails at this line and the verifier cannot build.

Useful? React with 👍 / 👎.

Comment thread gateway/config.go
// GetSupportedChainIds defines the network IDs allowed for payment requests.
// 84532: Base Sepolia, 11155111: Ethereum Sepolia, 11155240: Optimism Sepolia.
func GetSupportedChainIds() []int64 {
chainIDs := []int64{84532, 11155111, 11155240}

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.

P1 Badge Use the same Optimism Sepolia chain ID

This gateway allowlist advertises 11155240 as Optimism Sepolia, but the verifier's SUPPORTED_CHAINS and the web wallet metadata use 11155420. Once the supported-chain helper is wired into challenges or receipts, clients can be told to use a chain the verifier/web do not support, so Optimism Sepolia payments will fail unless this ID is made consistent.

Useful? React with 👍 / 👎.

Comment thread gateway/openapi.yaml
chainId:
type: integer
example: 84532
supportedChainIds:

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.

P2 Badge Emit the documented chain list in 402 challenges

This adds supportedChainIds to the public payment-context schema, but gateway/main.go still defines and creates PaymentContext with only recipient, token, amount, nonce, chainId, and timestamp (repo-wide search shows no writer for this field). Clients relying on the new multi-chain metadata will never receive it in the 402 response unless the gateway struct and createPaymentContext() are updated too.

Useful? React with 👍 / 👎.

Comment thread verifier/src/main.rs
let n = now();
// Exactly at 300s window boundary - should be valid
let res = validate_timestamp_internal(Some(n - 300), 300, 60, n);
let res = validate_timestamp(Some(n - 300), 300, 60);

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.

P2 Badge Keep the timestamp boundary test deterministic

This boundary case now calls validate_timestamp, which reads SystemTime internally; if the wall clock advances after capturing n but before this call, n - 300 becomes 301 seconds old and the test fails sporadically. The removed helper accepted an injected now, so keeping an injectable clock or avoiding the exact boundary would prevent CI flakes after the compile errors are fixed.

Useful? React with 👍 / 👎.

Comment thread verifier/src/main.rs
Comment on lines +363 to +364
metrics::record_verification(false, start.elapsed().as_secs_f64(), Some("nonce_store_unavailable"));
(StatusCode::SERVICE_UNAVAILABLE, res_headers, Json(VerifyResponse { is_valid: false, recovered_address: None, error: Some("Nonce store unavailable".into()), error_code: Some("nonce_store_unavailable".into()) }))

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.

P1 Badge Preserve the Redis outage verifier contract

When VERIFIER_NONCE_STORE=redis is configured and Redis is unavailable, this path now returns a generic 500 with nonce_store_failure instead of the documented fail-closed 503/nonce_store_unavailable response that the gateway and runbooks can distinguish from a bad payment. That makes a shared nonce-store outage surface as an internal verifier failure rather than the stable Redis-unavailable contract.

Useful? React with 👍 / 👎.

Comment thread verifier/src/main.rs
const DEFAULT_EXPECTED_CHAIN_ID: u64 = 84532;
const NONCE_SWEEP_INTERVAL_SECONDS: u64 = 60;

const SUPPORTED_CHAINS: [u64; 3] = [84532, 11155111, 11155420];

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.

P2 Badge Update setup docs for multi-chain semantics

Adding a built-in multi-chain allowlist changes the verifier from a single EXPECTED_CHAIN_ID check, but the setup docs still tell users CHAIN_ID and EXPECTED_CHAIN_ID must match and that multi-chain support is only future work. Deployers following the current README will misconfigure or misunderstand this feature unless the docs/env table are updated with the new supported-chain behavior.

Useful? React with 👍 / 👎.

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

Labels

documentation Improvements or additions to documentation enhancement New feature or request go Pull requests that update go code gssoc:approved Approved for GSSoC contribution level:advanced Large, risky, or cross-service work requiring strong project context. rust Pull requests that update rust code type:docs Documentation, API docs, examples, or contributor docs. type:feature New user-facing or API-facing capability. TypeScript TypeScript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Umbrella: Add multi-chain payment support from current Base Sepolia default

3 participants