Architecture

x402 settles how an agent pays. x401 settles who authorized it. Neither checks whether the work was correct. Merit verifies that a cited source actually supports the claim made from it, and makes that verdict the settlement switch.

Everything below is deployed and exercised on Arc testnet. Every address and behaviour was verified against the live chain, not read off a datasheet. The source for these diagrams is docs/ARCHITECTURE.md.

1 · System

Who calls Merit, what happens inside it, and which Circle and Arc primitives carry the money.

System diagram. Buyers — AI agents on six frameworks, the Circle Agent Stack CLI, humans on onmerit.xyz, and MCP clients — discover Merit through its x402 discovery document, OpenAPI spec and price ladder. Requests enter a four-stage verification engine: a deterministic numeric gate, an NLI factual-consistency check, an adversarial LLM judge, and a premium 0G TEE-attested consensus jury, producing a signed verdict. The verdict drives a settlement decision: release, or refuse with zero USDC moved. A release passes compliance screening, transaction simulation and spend caps, then settles through Circle Gateway nanopayments or an Arc Memo-wrapped USDC transfer, optionally batched through Multicall3From, alongside ERC-8004 registry writes and ERC-8183 hook-gated escrow. Both of Arc's USDC emitters feed the public reconciliation surface.
Merit end to end. Green is the verification engine — the part no other payment rail has.

2 · The money path

The sequence that distinguishes Merit from every other rail: the payment is conditional on the work being right, and the proof of that condition travels inside the transaction.

Sequence diagram. An agent posts a claim and source to the metered oracle and receives a 402 carrying payment requirements in both the response body and a header. It retries with an EIP-3009 authorization, which Merit settles through Circle Gateway. The verification engine returns a signed verdict. If SUPPORTED, Merit screens the payee for compliance, then sends the USDC transfer wrapped in Arc's Memo contract, so the memo id derives from the payout digest, the memo data names the verification ids, and the calldata hash binds the memo to that exact transfer; the creator receives USDC with the sender preserved as Merit's EOA, and reputation and validation are written to ERC-8004. If REFUSED, nothing is paid and the refusal is recorded in the public ledger. The agent can then reconcile the ledger against both of Arc's USDC emitters.
SUPPORTED pays and leaves an on-chain memo naming the verifications. REFUSED moves $0 — and is still recorded.

3 · Verification engine

Price scales with how hard the check tries, never with retrieval. The first gate uses no model at all — which is why a fabricated figure is still caught when every LLM provider is down.

Flowchart of the verification engine. A claim and source enter a deterministic numeric gate; a figure that contradicts the source is refused immediately with zero settlement. Otherwise an NLI factual-consistency check runs, refusing anything below the entailment floor. Surviving claims reach an injection-resistant adversarial judge, and on the premium tier a 0G TEE-attested consensus jury. Any gate can refuse. Both SUPPORTED and REFUSED outcomes produce a signed verdict recoverable offline.
Four gates, any one of which can refuse. Both outcomes are signed — a refusal is as checkable as an approval.

Measured, not asserted. A forkable 275-case adversarial benchmark across 14 failure modes: 100% recall — every adversarial case caught, 197 held, 0 slipped — at 90.4% precision / 94.9% F1. The verifier is conservative by design: it over-refuses roughly 30% of genuinely-supported claims rather than risk paying for one that is not. That is the safe direction when the output is money. Reproduce with npm run bench-judge.

4 · Network configuration

Arc mainnet is not published yet — the Arc docs say mainnet addresses are unavailable, and Circle's Gateway SDK ships arcTestnet with no mainnet counterpart. So Merit treats the network as configuration and invents nothing.

Flowchart of network configuration. The ARC_NETWORK environment variable selects either testnet — the default, chain 5042002, with every address verified on the live chain — or mainnet, assembled from ARC_MAINNET environment values. A readiness check names every missing value and what it gates. When chain id, RPC and USDC are all present the deployment is settlement-ready; when a value is absent the feature degrades honestly and a testnet address is never substituted for a mainnet one.
Moving to Arc mainnet is environment variables, not a code change — proven by tests/arc-network.test.ts.

5 · Where each Circle and Arc product is used

ProductWhereWhat it does here
ArceverywhereSettlement chain. USDC-native gas, sub-second finality.
USDClib/pay.ts · lib/custody.ts · lib/balance.tsThe unit of account for every toll, payout and refund.
Circle Gateway / Nanopaymentslib/seller.ts · lib/pay.tsx402 batched sub-cent tolls — Merit is both seller and buyer.
Circle Developer-Controlled Walletscircle-dcw/ · lib/wallet.tsKMS-custodied payout wallet; no plaintext key on the server.
Circle Compliance Enginelib/compliance.tsKYT + denylist screen before any payout. Fails closed.
CCTPlib/crosschain.tsA creator takes verified earnings to Base / Arbitrum / Optimism / Avalanche.
Arc Memolib/memo.tsThe verdict travels inside the payment as an indexed on-chain event.
Arc Multicall3Fromlib/custody.tsk creators paid in one transaction, msg.sender preserved per line.
EIP-7708 system emitterlib/reconcile.tsIndependent second witness for every USDC movement, at 18 decimals.
EIP-3009lib/relay.tsGasless funding — the payer signs, Merit broadcasts and pays the gas.
ERC-8004lib/reputation.tsIdentity, reputation and validation registry writes — Merit fills the empty third slot.
ERC-8183 + IACPHookcontracts/ · lib/job.tsEscrow whose release is gated on the citation verdict, on-chain.