Verify the core claims in 30 seconds β zero keys, zero accounts, fully offline:
npm install && npm run bench # β 8/8 attacks blocked
forge install foundry-rs/forge-std OpenZeppelin/openzeppelin-contracts && forge test # β 21/21 + fuzz + reentrancy
npm run agent # β autonomous agent; GuardianRail blocks 5/5 unsafe buys (offline, no key)Want the live on-chain settlement too? It's a real testnet tx you can verify without running anything β see Phase 1 on-chain proof. To reproduce it locally (needs a funded Atlantic test wallet):
cp .env.example .env # fill AGENT_PK, FACILITATOR_PK, RECEIVER_ADDRESS (see comments)
forge script script/DeployMockUSDC.s.sol --rpc-url atlantic --broadcast # prints MockUSDC β set USDC_ADDRESS
npm run probe # prove EIP-3009 settlement on Atlantic
npm run server # terminal 1 β x402-protected resource server
npm run demo # terminal 2 β guarded agent pays end-to-end (settles 0.001 USDC)GuardianRail faces 8 attack vectors β every unauthorized spend is blocked before the agent ever signs:
π‘οΈ PayGuard Β· GuardianRail β Attack β Blocked
βββββββββββ¬ββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββββββ
β (index) β Attack Vector β Result β Guard Code β
βββββββββββΌββββββββββββββββββββββββββββββββββΌββββββββββββββββββΌββββββββββββββββββββββ€
β 0 β 1. The Drainer (10,000 USDC) β π BLOCKED β MAX_SPEND β
β 1 β 2. The Phish (0xFakeToken) β π BLOCKED β INVALID_ASSET β
β 2 β 3. The Rogue Node (bad payTo) β π BLOCKED β UNAPPROVED_PAYEE β
β 3 β 4. The Revert (sim fails) β π BLOCKED β SIMULATION_FAILED β
β 4 β 5. The Inflator (negative amt) β π BLOCKED β MAX_SPEND β
β 5 β 6. The Malformed (float amt) β π BLOCKED β INVALID_ASSET β
β 6 β 7. The Clean Run β β
AUTHORIZED β AUTHORIZED β
βββββββββββ΄ββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββ΄ββββββββββββββββββββββ
β
TOC/TOU pin β 2-entry offer collapsed to the single validated requirement
β
8/8 vectors handled correctly β 100% of unauthorized agent spends blocked.
npm run agent turns GuardianRail loose on an autonomous agent. A procurement agent is given a budget and a
goal ("assemble a trading-research data bundle") and shops an x402 data marketplace β every purchase gated
by the shipped createGuardedFetch before any signature. Set ANTHROPIC_API_KEY for a live Claude
(claude-opus-4-8) tool-use loop; with no key it runs a deterministic planner (offline, identical every run):
π€ autonomous agent Β· goal: assemble a safe research bundle under 5 USDC/day
β
DataHub AUTHORIZED β charged 0.5 USDC
π AlphaDrainer BLOCKED [MAX_SPEND] 10,000 USDC > 5 USDC per-call cap
β
WeatherWire AUTHORIZED β charged 2 USDC
π CheapFeed BLOCKED [INVALID_ASSET] spoofed token, not USDC
π GhostNode BLOCKED [UNAPPROVED_PAYEE] payee not in allowlist
π PausedOracle BLOCKED [SIMULATION_FAILED] eth_call would revert
π NewsFeed BLOCKED [BUDGET_EXCEEDED] 3 USDC > 2.5 USDC left today
π° spent 2.5 / 5 USDC Β· 5 unsafe payments blocked β every drain, spoof, rogue-payee,
revert, and over-budget attempt stopped BEFORE the agent ever signs.
It reuses the shipped guard unchanged β the real GuardianRail protecting a real agent loop, not a reimplementation. The EIP-3009 authorization for a blocked buy is never created.
x402 is Pharos's flagship agent-payment rail β but it signs and settles whatever a server's
402 PAYMENT-REQUIRED demands. One LLM hallucination or one rogue endpoint can drain an agent's
wallet in seconds: no spend caps, no simulation, no asset checks, no escrow.
PayGuard is the safety layer x402 is missing β two composable, atomic Skills any Pharos agent imports:
- π¦ GuardianRail β a pre-flight interceptor that enforces spend caps, asset-spoof protection, payee allowlists, and an
eth_callsimulation before the agent signs the EIP-3009 authorization. - π¦ AgentVault β a minimal, non-upgradeable, CertiK-grade USDC escrow for conditional / milestone payments.
- π°οΈ Proven end-to-end β a guarded agent really settles USDC on Pharos Atlantic (verifiable tx below).
Nests under the x402 client via createGuardedFetch, so it gates the 402 offer before signing:
const guarded = createGuardedFetch(fetch, policy, { rpcUrl });
const safeFetch = wrapFetchWithPayment(guarded, client); // throws AgentSecurityError on violationEnforces: canonical-asset (anti-spoof) Β· per-call cap Β· daily budget Β· payee allowlist Β· eth_call simulation.
Minimal, non-upgradeable, strict-CEI escrow (SafeERC20 + ReentrancyGuard) for milestone payments:
lock(payee, amount, conditionHash, deadline) β release(id, preimage) / refund(id).
graph TD
Agent[Agent] --> Guard["createGuardedFetch(policy)<br/>enforce + eth_call sim (pre-signature)"]
Guard --> Client["x402 client (EIP-3009 sign)"]
Guard --> Server["x402 server (/api/data, 402)"]
Server --> Fac[Facilitator]
Fac --> Def["default: official Pharos FACILITATOR_URL"]
Fac --> Fall["fallback: in-process x402Facilitator (self-hosted)"]
Def --> Settles["settles USDC on Atlantic (688689)"]
Fall --> Settles
AV["High-value path: AgentVault.sol"] --> Actions["lock β release(proof) / refund(deadline)"]
The in-process facilitator implements FacilitatorClient directly, so the self-hosted fallback
needs no HTTP-facilitator service β the demo is deterministic even if the public facilitator is down.
For judges β exactly which Pharos / sponsor tech PayGuard uses and where to find it.
| Track / Tech | How PayGuard uses it | Where in the code |
|---|---|---|
Pharos x402 (flagship rail) |
guarded client Β· resource server Β· in-process facilitator settling EIP-3009 | src/guardrail.ts Β· src/server.ts Β· src/facilitator.ts Β· src/demo.ts |
| Phase 1 β Skill | Anthropic Agent Skill module (the deliverable) | SKILL.md |
| CertiK Skill Scanner (security standard) | minimal SafeERC20 + ReentrancyGuard + strict-CEI escrow Β· 100% test coverage Β· Slither-clean | contracts/AgentVault.sol |
| Pharos Atlantic (688689) | real, verifiable on-chain settlement | tx 0xfd6e66β¦ |
$ npm run bench # GuardianRail β offline, deterministic
β
8/8 vectors handled correctly β 100% of unauthorized agent spends blocked.
$ forge test # AgentVault + MockUSDC β OZ v5.6.1 / solc 0.8.28
[PASS] testFuzz_BalanceMatchesTotalLocked(uint256) (runs: 256)
[PASS] test_ReentrancyGuardBlocksReentry() β¦ (+19 more)
21 tests passed; 0 failed; 0 skipped
$ forge coverage # contracts/ (AgentVault + MockUSDC)
100% lines Β· 100% statements Β· 100% branches Β· 100% functions
$ npm run server & npm run demo # full guarded payment, end-to-end on Atlantic
β
paid + received: { secret: 'PayGuard: safe x402 payment settled on Pharos Atlantic.' }
# receiver USDC balance 2000 β 3000 on-chain β a real settlement, not just a 200
The complete flow is verified end-to-end on Atlantic: a GuardianRail-guarded agent pays the
x402 server, the in-process facilitator verifies and settles 0.001 USDC on-chain, and the
agent receives the protected content β all on @x402/* v2.14.
| Layer | Tool | Status |
|---|---|---|
| Type safety | tsc --noEmit |
β |
| Skill tests | GuardianRail attack bench (8 vectors) | β 8/8 |
| Contract tests | Foundry β 256-run fuzz + reentrancy + EIP-3009 | β 21/21 |
| Contract coverage | forge coverage (contracts/) |
β 100% |
| Static analysis (Solidity) | Slither | β 0 high / 0 medium |
| Static analysis (TypeScript) | CodeQL | β |
| On-chain E2E | guarded payment settles on Atlantic | β |
| Secret scanning | TruffleHog (--only-verified) |
β |
| Supply chain | npm audit + Dependabot | β |
A 3-stage GitHub Actions pipeline (Quality Β· Security Β· Gate) runs on every push/PR β see
.github/workflows/ci.yml. Locally: npm run ci Β· npm run typecheck Β· make security-scan.
| Control | Attack stopped |
|---|---|
targetAsset strict-equality |
token-spoofing / look-alike phishing |
maxSpendPerCall + dailyBudgetRemaining |
wallet draining via looping / hallucinating agents |
allowedPayees allowlist |
exfiltration to a rogue payee |
eth_call pre-flight simulation |
paying into reverts / paused / blacklisted contracts |
SafeERC20 + ReentrancyGuard + CEI |
reentrancy / non-standard-token drains |
| minimal contract (no streaming / upgrade / delegatecall) | reduced scanner attack surface |
| Artifact | Value |
|---|---|
| MockUSDC (EIP-3009) | 0xe54205649D6d41Aa9cCdD5667eaDB62f1dFA84AC |
| Settlement tx | 0xfd6e66157765066d9ff76068ee9476549153ade951036f3f7863a29f2ffbc253 |
Verified on-chain β
status: success, block24099194. Check it yourself:eth_getTransactionByHashon RPChttps://atlantic.dplabs-internal.com/.
SKILL.md Anthropic Agent Skill (the submission artifact)
src/guardrail.ts Tool 1 β createGuardedFetch + pure evaluateRequirement
src/simulate.ts eth_call pre-flight (injectable)
src/rpc.ts rate-limit-hardened viem transport (retryingHttp)
src/facilitator.ts in-process x402Facilitator (self-hosted fallback)
src/server.ts x402-protected resource server
src/demo.ts end-to-end guarded payment
src/agent.ts Skill-to-Agent β autonomous Claude agent on the guard
src/probe.ts EIP-3009 settlement probe
contracts/AgentVault.sol Tool 2 β conditional escrow (100% coverage)
contracts/MockUSDC.sol EIP-3009 test USDC (100% coverage)
script/DeployMockUSDC.s.sol deploy MockUSDC β USDC_ADDRESS
test/AgentVault.t.sol AgentVault suite (fuzz + reentrancy)
test/MockUSDC.t.sol EIP-3009 transferWithAuthorization suite
bench/malicious_bench.ts 8/8 attack-vector bench
@x402/* v2.14 Β· viem v2.52 Β· express Β· Foundry (solc 0.8.28, OZ v5.6.1) Β· TypeScript/ESM. MIT Β© 2026 Edy Cu.