Quartermaster

Guides / Common Solana x402 mistakes (and how to fix them)

Common Solana x402 mistakes (and how to fix them)

Solana is a first-class rail in x402 v2, and it fails in different places than Base. Token accounts instead of plain addresses, a blockhash that expires in about a minute, and a required fee-payer field that EVM integrations never see. These are the ten mistakes we see most when looking at Solana endpoints — roughly ordered by how often they break a payment outright — with the fix for each.

The v2 flow itself is rail-agnostic: the server answers with HTTP 402 and a PAYMENT-REQUIRED header (base64 JSON), the client pays and retries with PAYMENT-SIGNATURE, and the server returns 200 plus a PAYMENT-RESPONSE receipt. Everything below is about what Solana changes inside that loop.

Configuration mistakes that break every payment

1. Missing extra.feePayer — clients cannot build the transaction

On SVM the client builds a partially signed versioned transaction and hands it over; the fee payer (usually the facilitator) co-signs and submits it. That is why buyers need zero SOL — the sponsor pays the network fee. The sponsor's public key travels in extra.feePayer, and on Solana it is required, not optional. Leave it out and clients cannot construct the transaction at all. Nothing ever reaches the chain.

A correct SVM accepts entry looks like this:

{
  "scheme": "exact",
  "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
  "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "payTo": "<your owner wallet, base58>",
  "amount": "10000",
  "extra": { "feePayer": "<facilitator fee-payer pubkey>" }
}

Two details worth pinning down: exact is currently the only scheme on SVM (EVM also has upto and batch settlement), and the amount is a string of atomic units — USDC has 6 decimals, so "10000" is $0.01. The payload the client eventually sends is a base64-encoded partially-signed transaction: compute-budget instructions, a TransferChecked, and a Memo (three to six instructions total, with only Memo and Lighthouse extras allowed).

2. The recipient's USDC token account does not exist

payTo is your owner wallet, but the funds actually land in that wallet's USDC Associated Token Account (ATA) — and the x402 payment flow cannot create it. If the ATA does not exist, payments to you can never land, no matter how correct the rest of your configuration is. The failure is invisible from your side: the 402 looks fine, the client pays, settlement fails.

The fix is a one-time, one-cent operation: send any tiny amount of USDC to the wallet before you go live. A standard wallet transfer auto-creates the ATA on the sender's side. Done once, done forever.

3. Wrong asset field — a symbol or the wrong mint

On SVM, asset is a token mint address, not a symbol. "USDC" is wrong, and so is any mint that is not the Circle-issued one:

mainnet  EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
devnet   4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU

This matters twice. A seller who publishes the wrong mint gets paid in nothing. A verifier who matches by token name gets paid in anything: anyone can deploy a token called USDC, so a verifier that does not pin the exact mint can be satisfied by a worthless spoofed token. Pin the mint on both sides and compare it verbatim.

4. v1 network names instead of CAIP-2

x402 v2 identifies networks with CAIP-2 ids. On Solana those are derived from the genesis hash — truncate(genesis-hash, 32):

mainnet  solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
devnet   solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1

The bare string "solana" is v1. v2 clients match on the CAIP-2 id, so a v1 name in a v2 accepts entry means no client ever selects your Solana option. On the client side, @x402/svm registers against the same namespace, side by side with EVM:

new x402Client()
  .register("solana:*", new ExactSvmScheme(svmSigner))
  .register("eip155:*", new ExactEvmScheme(evmSigner));
Mistakes 1, 3, and 4 are statically visible in your 402 response, and the free x402 Inspector flags them automatically — a missing feePayer, an unrecognized asset mint, and non-CAIP-2 network ids, on Base and Solana alike. Mistake 2 is on-chain account state: check it by sending your wallet any tiny USDC transfer, which creates the ATA if it is missing.

Flow and verification mistakes

5. Treating the 402 flow as untimed

A Solana transaction references a recent blockhash, and a blockhash is only valid for roughly 60–90 seconds (about 150 slots). The exact scheme does not use durable nonces, so the whole round-trip — receive the 402, build and sign the transaction, retry the request, facilitator co-signs and submits — has to finish inside that window. Past it, the transaction can never land.

In practice this rules out human-in-the-loop approval between quote and payment, long client-side caching of payment requirements, and leisurely retry loops. Agents that pay immediately are fine; anything that pauses should re-request a fresh 402 first.

6. Verifying by parsing instructions instead of balance deltas

The tempting way to verify a settlement is to decode the TransferChecked instruction and read its amount. It breaks: under Token-2022 fee-on-transfer, the instruction amount is not what the recipient actually receives, and instruction parsing also drags you into ATA derivation. The robust way is to diff token balances:

const tx = await rpc.getTransaction(signature, {
  encoding: "jsonParsed",
  commitment: "confirmed",
  maxSupportedTransactionVersion: 0
});
if (!tx || tx.meta.err !== null) throw new Error("not settled");
// diff meta.preTokenBalances vs meta.postTokenBalances;
// match the NET delta where owner === your wallet
//   AND mint === the pinned USDC mint;
// compare amounts as integers in atomic units (never floats)

Balance-delta verification needs no ATA math and nets out transfer fees automatically. The signature you are looking up is the base58 string (87–88 characters) from the PAYMENT-RESPONSE receipt — not an 0x hash as on Base, where verification reads ERC-20 Transfer event logs from the receipt instead.

7. Accepting "processed" commitment

"processed" is not a settlement guarantee and can be rolled back. Use "confirmed": it lands in about 1–2 seconds, and no optimistically-confirmed Solana block has ever been rolled back. "finalized" (about 13 seconds) is there if your risk posture demands it, but "confirmed" is the sensible default for API payments.

Two RPC caveats while you are here: api.mainnet-beta.solana.com blocks datacenter IPs and is not for production, and public nodes are non-archival, so old signatures return null. Verify payments promptly and persist your own receipt, or use an archive-backed provider. getSignatureStatuses({ searchTransactionHistory: true }) covers later status checks.

Testing and ecosystem mistakes

8. Testing against mainnet first

Every mistake above is cheaper to find on devnet: same flow, the devnet CAIP-2 id and devnet USDC mint from mistakes 3 and 4, and no real money at stake. Facilitators with live-verified Solana support as of mid-July 2026:

Prove the full loop on devnet, then flip the network id and mint to mainnet. Note that x402.org and x402.rs cannot follow you there.

9. Forgetting Bazaar discovery metadata

Settlement alone does not make you discoverable. Settlements through the CDP facilitator that carry discovery metadata get indexed in the x402 Bazaar; settlements without it never index, and your endpoint stays invisible to agents however much traffic it takes. Solana is not a niche there — roughly a quarter of Bazaar resources in a July 2026 sample were Solana endpoints, all mainnet USDC. Add the metadata before launch, not after your first quiet month.

10. Trusting raw settlement counts as demand

Solana leads the x402 ecosystem in transaction count, driven by micro-settlements and RPC metering, while Base leads cumulative USD value settled. Before reading either number as market demand, one honest caveat: independent analyses estimated that a large majority of peak-period x402 transactions were non-organic — bots and self-dealing. Raw counts overstate real demand, on every rail. When you size a market or judge your own traction, weight by distinct payers and settled value rather than settlement count. The protocol itself is on firmer footing than its vanity metrics: x402 now sits with the x402 Foundation under the Linux Foundation, with the Solana Foundation as a member.

Check your endpoint before an agent does

The free x402 Inspector catches mistakes 1–4 automatically on any Base or Solana endpoint. For a scored pass over everything on this list, GET /v1/x402-audit is $0.01 per run, and /v1/payment-proof ($0.003) and /v1/settlement-assurance ($0.03) accept an 0x Base hash or a base58 Solana signature interchangeably. When you want a human-readable verdict, the $9 full AI-reviewed endpoint report covers every rail at the same price.

Last updated 2026-07-17. Written from the x402 specification, the x402-foundation reference implementation, facilitator /supported endpoints, and live Coinbase Bazaar data. Corrections: dev@surewhynot.app.

More guides: Accept Solana USDC in your API with x402 · Base vs Solana for x402 sellers: an honest comparison · How to verify a Solana x402 settlement