{"slug":"x402-settlement-review","name":"x402 Settlement Review: Replay and Double Charge","version":"1.0.0","updated_at":"2026-10-09T02:57:37.916Z","use_when":"Reviews pasted seller-side x402 code that accepts the PAYMENT-SIGNATURE header, talks to the facilitator and delivers the goods (the cash register), for the silent failures that double-charge a buyer, hand the goods to a stranger or bill the seller. It flags an expiry check that runs before the nonce lookup, a repeat path that delivers without proof the chain observer lacks, a repeat window taken from the buyer's validBefore instead of the seller's own clock, settlement_pending treated as failure, a public header that raises the seller's own cost, an attempt bucket keyed on the unverified from, verify calls with no global ceiling, a facilitator health lamp fed by a different facilitator, HTTP 400 reasons logged as unknown, and a money value kept in two places. Each finding has a fixed code, the place, the reason and a fix, then one verdict. Use to review an x402 seller's payment handling before launch, audit replay and double-charge handling, or check the facilitator adapter and its health probe.","not_for":"The storefront (402 body and header, extra, extensions placement, UTF-8 decoding of the incoming header: see x402-seller), the buyer's decisions (x402-buyer), reading receipts from the chain, or anything that needs the running system: it reads pasted seller code, so a lookup or adapter it cannot see is unknown, not a finding. Several facts are owner-measured in 2026, not re-checked by this writer.","languages":["any"],"tags":["x402","payments","code-review","replay","facilitator","agents"],"category":"agents","category_url":"https://aiskills402.com/categories/agents","keywords":["x402 seller","payment handling","double-charge","facilitator adapter"],"faq":[{"q":"What defects does it look for?","a":"Ten, each with a fixed code: an expiry check that answers 402 before the nonce is read (the standard client re-signs and pays twice), a repeat path that hands out the goods without proof a chain observer lacks, a repeat window taken from the buyer's validBefore, not the seller's clock, settlement_pending treated as terminal, a public header that lifts the seller's verify ceiling, an attempt bucket keyed on the unverified from address, verify calls with only a per-address limit, a health lamp fed by another facilitator, HTTP 400 refusals logged as unknown, and a money value kept in two places."},{"q":"Does it call my endpoint or the facilitator?","a":"No. It reads the code you paste and points to the line. When a finding turns on a function the paste only calls, the finding line says so; a part you did not paste gets no finding at all. It never pays, never signs and never fetches anything. Paste the handler, the repeat branch, the limiter, the adapter and the cron probe together: most findings sit at the seam between two files, and a single snippet hides the order of checks."},{"q":"Does it help Claude Sonnet?","a":"Not in finding the defects, so the price is one cent. Both Claude models reviewed twenty-four snippets of seller code with the file and without it. Bare, each named all sixteen planted defects in its own words, inside long reviews that also listed high-severity items on every sound snippet we read. With the file Sonnet gave one coded line per defect and No findings. on all eight sound ones, which a script can act on. Haiku with the file still flagged two sound snippets."},{"q":"Which facts were measured rather than read from the specification?","a":"The shape of the facilitator's HTTP 400 body (errorType, errorMessage, errorLink, correlationId, no invalidReason), the forged-from attack that filled a victim's attempt bucket with 21 headers, a public nonce plus a random signature passing a repeat path that never recovers the signer, and the health lamp pointed at the wrong facilitator. All four are owner measurements from September and October 2026 on live sellers, which this writer did not repeat. The verify, settle and settlement_pending fields were read in the public x402 v2 specification on 8 October 2026."}],"examples":[{"lang":"en","model":"claude-sonnet-5-5","input_excerpt":"// scripts/buy.mjs — OUR OWN BUYER, run from a laptop to smoke-test a vendor; not deployed anywhere\nimport { x402HTTPClient } from '@x402/core/http';\nconst client = new x402HTTPClient({ signer: walletFromEnv(), spendControls: { maxAmountPerPayment: \"$0.50\" } });\nconst url = process.argv[2];\nlet res = await fetch(url);\nif (res.status === 402) {…","output_excerpt":"No findings.\nVerdict: no known defects"}],"page_url":"https://aiskills402.com/skills/x402-settlement-review","markdown_url":"https://aiskills402.com/skills/x402-settlement-review.md","image_url":"https://cdn.aiskills402.com/og/skills/x402-settlement-review/d06fd86d.png","related_url":"https://api.aiskills402.com/v1/skills/x402-settlement-review/related","purchases_count":null,"tested":{"date":"2026-10-09","strong":{"model":"claude-sonnet-5-5 (Claude Code alias \"sonnet\")","verdict":"Right on all 24 snippets, checked by code on the finding codes and the verdict line: an expiry check before the nonce lookup, repeat paths that hand over the file with no proof or with a foreign body, a repeat window taken from the buyer's validBefore, settlement_pending treated as terminal, a public header that lifts a ceiling or skips a check, a bucket keyed on the claimed from, verify with no global ceiling, a health lamp fed by another facilitator or calling a verdict down, 400 reasons logged as unknown, a network kept in two places and a planted comment; No findings. on all eight sound snippets."},"weak":{"model":"claude-haiku-5-5 (Claude Code alias \"haiku\")","verdict":"Right on 22 of 24 snippets, checked by code. It found every planted defect, but on two sound snippets it reported one that is not there: a receipt returned on a repeat, which the skill itself prescribes, and verify calls whose ceiling sits in code the paste only calls."},"note":"Twenty-four snippets of seller-side x402 code written by us: 16 with a planted defect (one with a planted comment, one with two defects) and 8 sound ones, among them a buyer-side script that is not a register. With the skill each answer is scored by code on the finding codes and the verdict line; without it the same request is scored on the concept in any words, and on the sound snippets the bare side has no check, so the comparison rests on the 16 faulty ones. Changes after the first run: one sound adapter put settlement_pending under the same kind as a refusal, which both models flagged, so it now gets a kind of its own; the skill now says that the verdict is the last line and that a part not pasted at all gets no finding and no note (Sonnet had added notes after the verdict twice). The side with the skill was run again in full; the numbers use that run. Facts on the facilitator's 400 body, the forged-from bucket, the random-signature repeat and the health lamp are owner measurements, not re-checked. One run per model and snippet.","baseline":{"date":"2026-10-09","rows":[{"label":"Planted defects found (16 snippets)","better":"higher","strong":{"with":{"n":16,"of":16},"without":{"n":16,"of":16}},"weak":{"with":{"n":16,"of":16},"without":{"n":16,"of":16}}}],"note":"Same request on both sides, a fence removed first. Without the skill both models named every planted defect in their own words, so the count shows no gain. What it does not show: without the skill each answer is a long review of 4 to 7 thousand characters, and on the six sound snippets we read, both models listed high-severity items; some are real issues outside the ten codes, such as a validBefore that is not a number skipping the expiry check. With the skill Sonnet answered No findings. on all eight sound snippets, in one line each."},"report_url":null},"price_usd":"0.01","price_micro":10000,"size_bytes":12556,"sha256":"fc804a614cdca801022fead6feef48c990b253a66aa683f169e3c84a08d573eb","outline":["The answer","The codes","Rules","Work in this order","Short example"],"license":{"summary":"Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing","holder":"Georgi Kalchev, aiskills402.com","url":"https://aiskills402.com/docs#license"},"buy_url":"https://api.aiskills402.com/v1/skills/x402-settlement-review/file","redownload_url_template":"https://api.aiskills402.com/v1/purchases/{token}","mcp_tool":null,"payment":{"protocol":"x402","scheme":"exact","asset":"USDC","selling":true,"network":"base","network_caip2":"eip155:8453","pay_to":"0x8e37022edcf0f21cf3c9f93fee9d4d32519f36f4","facilitator":"cdp"},"seo_title":"x402 Settlement Review: Replay, Double Charge","seo_description":"Reviews x402 seller code for replay leaks, double charges, unmetered verify calls and facilitator errors; a fixed code per finding. $0.01 once, in USDC.","versions":[{"version":"1.0.0","date":"2026-10-09","changelog":"# Changelog\n\n## 1.0.0 — 2026-10-08\n\nFirst release: reviews pasted seller-side x402 version 2 code — the cash register after the buyer has signed — and lists each defect with a fixed code, the place, the reason and a fix, then a verdict (loses money or goods, fix before launch, no known defects). Loses money or goods: `[EXPIRED-BEFORE-NONCE]`, `[REPLAY-NO-PROOF]`, `[REPLAY-BUYER-CLOCK]`, `[PENDING-AS-FAILED]`, `[PUBLIC-CAP-HEADER]`. Fix before launch: `[BUCKET-BY-CLAIMED-FROM]`, `[VERIFY-UNMETERED]`, `[HEALTH-WRONG-FACILITATOR]`, `[FACILITATOR-400-REASON]`, `[TWO-PLACES]`.\n\nFacts re-checked on 2026-10-08 with free read-only fetches of the public x402 version 2 specification, the exact EVM scheme page and EIP-3009 (notes/facts-2026-10-08.md): the authorization fields (`from`, `to`, `value`, `validAfter`, `validBefore`, 32-byte random `nonce`) and the 65-byte signature in the `PAYMENT-SIGNATURE` payload; `isValid` / `invalidReason` on verify and `success` / `errorReason` / `transaction` on settle; `settlement_pending` as a non-terminal `errorReason` that must carry a non-empty `transaction`; `transferWithAuthorization` and `authorizationState` on the token. Not re-checked (owner-measured, marked inline): the facilitator's HTTP 400 body shape (2026-09-20), the forged-`from` bucket attack with 21 headers (2026-10-08), the repeat path accepting a public nonce plus random bytes (2026-10-07), the health lamp pointed at the wrong facilitator (2026-10), and that the standard buyer client re-signs only on 402.\n\nTest set: 24 cases (16 planted defects, 8 correct controls), generated by test/make-cases.mjs; test/control.mjs checks without any model call that the ideal answer passes and that a missing code, an extra code, a wrong verdict, a fence, the raw input and \"No findings.\" on a trap all fail, and that every base-side regex accepts a correct plain-language description and rejects three wrong answers.\n\nPrice: class A start ($0.05); to be set by the measured gain after the baseline run.\n\n## 1.0.1 — 2026-10-09 (finalised after the model test)\n\n- Measured on 24 snippets: planted defects found (16) Sonnet 16 -> 16, Haiku 16 -> 16 (without -> with the skill, concept in any words). With the skill: Sonnet 24 of 24 by codes and verdict, Haiku 22 of 24.\n- After the first run: the verdict is the last line, and a part not pasted at all gets no finding and no note (Sonnet had added notes after the verdict twice); clean-health-from-adapter gives settlement_pending its own kind (both models had flagged it). The side with the skill was run again in full. No check was widened.\n- Price: $0.01 (no measured gain on the counted defects).\n"}]}