fix: EIP-681 QR scans 404 — recipient guard rejects address@chainId (main hotfix) - #2612
Conversation
Both country-launch links ship with no inviter. Mapping them in UTM_CAMPAIGN_TO_BADGE_MAP was not enough: classifyBareCampaign only bypasses the invite gate for campaigns registered in WAITLIST_SKIP_CAMPAIGNS or BARE_VANITY_CAMPAIGNS, so a bare ?campaign=naija dead-ended on 'Invalid Invite Code' instead of awarding the badge. Same bug that left touched_grass unclaimable. They go in WAITLIST_SKIP_CAMPAIGNS, not BARE_VANITY_CAMPAIGNS: both badges are in peanut-api-ts POSTLAUNCH_SKIP_BADGE_CODES, and the vanity set is for badges with no card-waitlist skip. Filing them as vanity would show generic claim copy while the backend granted a skip anyway.
…-links fix(badges): register naija and terere as bare claimable campaigns
The Feb-21 SEO guard (couldBeRecipient) only whitelisted bare EVM addresses, so the QR scanner's EIP-681 path — which builds /0x…@42161/34.4USDC and is fully supported by the downstream url parser — dead-ended on a 404 for every real-world EIP-681 payment QR. Strip the @chain suffix before the address/ENS checks; chain validation still happens downstream.
…ed amount segments The widened recipient guard makes /0x…@chain/<garbage-amount> URLs reach generateMetadata, where an unguarded parseAmountAndToken throw 500'd the render (pre-existing for /username/<garbage>, now wider). Fall back to default metadata instead.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughRecipient detection now supports address and ENS links with optional chain suffixes. Metadata generation now handles malformed amount or token segments by using default metadata values. ChangesRecipient link handling
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Code-analysis diffPainscore total: 6346.7 → 6346.94 (+0.24) 🆕 New findings (6)
✅ Resolved (6)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
|
@coderabbitai review |
|
There was a problem hiding this comment.
Pull request overview
Hotfix to main to prevent EIP-681 QR deep links (e.g. /0x…@42161/<amountToken>) from incorrectly 404’ing due to the catch-all recipient route guard rejecting address@chain-shaped segments, and to make metadata generation resilient to malformed amount/token segments.
Changes:
- Updated
couldBeRecipientto validateaddress@chain/ens@chainby stripping the@chainsuffix before applying address/ENS/username checks. - Added regression tests covering
address@chainId, percent-encoded%40<chainId>, andens@chain. - Wrapped
parseAmountAndTokeningenerateMetadatawithtry/catchto avoid 500s on malformed amount segments.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/constants/routes.ts | Adjusts recipient guard to consider only the base recipient when @chain is present. |
| src/constants/tests/routes.test.ts | Adds assertions to ensure address@chain / ens@chain pass the guard. |
| src/app/[...recipient]/page.tsx | Prevents metadata generation from throwing on malformed amount/token URL segments. |
kushagrasarathe
left a comment
There was a problem hiding this comment.
Reviewed via pr-review rulebook: T2, all four checklists pass. Guard widening is bounded (chain validation intact downstream), both throw paths covered (generateMetadata try/catch + SemanticRequestPageWrapper .catch). campaign-maps diff is #2610 riding along pending dev back-merge — benign, BE support confirmed on dev and main. Copilot multiple-@ finding: harmless, garbage @-URLs render the documented error state, not a crash. Known advisory eslint red is pre-existing debt, not worsened by this diff.
Why
Cherry-pick of the EIP-681 fix from #2427, re-targeted at
mainas a hotfix (original PR is based ondevand carries unrelated dev history).Scanning any real-world EIP-681 payment QR (e.g.
ethereum:USDC@42161/transfer?address=0x…&uint256=3.44e7) dead-ends on the 404 page. The scanner builds/0x…@42161/34.4USDCcorrectly and the downstream url parser supportsrecipient@chain— butcouldBeRecipient(the Feb-21/es/argentinaSEO-regression guard) tests the EVM-address regex against the full segment including@42161, fails, andnotFound()s.Repro: Konrad's scan 07-15 13:54 UTC (PostHog
qr_scanned, qr_type EIP_681, Crisp session_50bb92f0).What
Two commits cherry-picked from #2427 (
b085d10a,a423b1e1):couldBeRecipient: strip the@chainsuffix before the address/ENS checks (already stripped for the username check); collapse the deadincludes('@')ternary.generateMetadata([...recipient]/page.tsx): wrapparseAmountAndTokenin try/catch — the widened guard lets/0x…@chain/<garbage>reach it; now falls back to default metadata instead of 500ing.Design notes / accepted trade-offs
/0xADDR@<invalid-chain>now renders a 200 with a clean "Invalid chain" ErrorAlert instead of a hard 404 (@-suffixed inputs never reach PublicProfile). Never-indexable URLs, negligible crawl exposure. Tracked in Recipient route guard duplicates parser rules with no contract test (drift risk) #2428.Risks / breaking changes
main→ back-merge debt main→dev (fix: EIP-681 QR scans 404 — recipient guard rejects address@chainId #2427 covers the dev side).QA
0xADDR@42161, percent-encoded%4042161,vitalik.eth@arbitrumaccepted; locale-regression guards still pass.deferred-link.test.ts, is a worktree env artifact —@capacitor/preferencesmissing from the symlinked node_modules; untouched by this diff).Summary by CodeRabbit
New Features
Bug Fixes