Real testnet evidence

Attack Lab

Every row below is a real NEAR testnet transaction against tab-vault.testnet. Not a browser simulation, not a reference model.

23/23 passed
Last run 24 Oct 2026, 22:57 UTC
Signers
owner tab-demo.testnet
spender tab-merchant.testnet
How to read this: each scenario declares an expected policy result, then sends a real transaction with the owner, merchant or attacker account. The row records the actual contract result. Open any transaction on NearBlocks to inspect the receipt and the NEP-297 event. A failure would be shown as FAIL; the runner exits non-zero.

Conservation

#ScenarioExpectedActualResultTransaction
D0Deposit tUSDC into the vault via ft_transfer_call100000000 ledger100000000 ledgerPASS1N7Xwhi6…
F1Merchant received exactly the executed charges60000000 delta60000000 deltaPASSn/a
F2Contract stats count only confirmed settlements (delta)charges=6, volume=60000000charges=6, volume=60000000PASSn/a
F3Vault ledger conservation3000000030000000PASSn/a

Caps

#ScenarioExpectedActualResultTransaction
S1Legitimate charge inside every capexecutedexecutedPASSE2BnPa2f…
S2Prompt-injection charge above per-charge capPER_CHARGE_CAPPER_CHARGE_CAPPASS9LJTMXod…
S3Second legitimate charge inside period budgetexecutedexecutedPASSGvmLUqUR…
S3bPeriod budget exhaustionPERIOD_CAPPERIOD_CAPPASSBCCXHCPV…

Access control

#ScenarioExpectedActualResultTransaction
S4Phishing charge to an unapproved receiverRECEIVER_NOT_ALLOWEDRECEIVER_NOT_ALLOWEDPASS38ctn7Bx…
S7Unauthorized account calls chargeERR_CALLER_NOT_SPENDERERR_CALLER_NOT_SPENDERPASSHKcc2zWr…

Lifecycle

#ScenarioExpectedActualResultTransaction
S5Charge while the owner has paused the TabTAB_NOT_ACTIVETAB_NOT_ACTIVEPASSDnqk7jwQ…
S12Charge after the on-chain expiry timestampTAB_EXPIREDTAB_EXPIREDPASS4EiewNFx…
S13aCharge before revocationexecutedexecutedPASSHkoAt6nR…
S13bCharge after permanent revocationTAB_NOT_ACTIVETAB_NOT_ACTIVEPASSGazzFcuv…

Rollover

#ScenarioExpectedActualResultTransaction
S9aRollover Tab: first charge in period 0executedexecutedPASS5AotsQrC…
S9bRollover Tab: period 0 budget exhaustedPERIOD_CAPPERIOD_CAPPASS3KqECmPm…
S9cRollover Tab: charge succeeds in the new periodexecutedexecutedPASS6wCNDFcC…

Balance

#ScenarioExpectedActualResultTransaction
S8Charge larger than the vault ledger balanceINSUFFICIENT_BALANCEINSUFFICIENT_BALANCEPASS9yqC5Baz…

Transfer rollback

#ScenarioExpectedActualResultTransaction
S10aNEP-141 transfer to an unregistered account failsfailedfailed: FT_TRANSFER_PROMISE_FAILEDPASS3kXkt43o…
S10bCallback restores ledger and cap countersledger 60000000, spent 0, nonce 0ledger 60000000, spent 0, nonce 0PASSn/a

Replay

#ScenarioExpectedActualResultTransaction
S11aReplay Tab: first charge consumes nonce 0executedexecutedPASSEcCFXGgw…
S11bReplay the already-consumed nonceERR_NONCE_MISMATCHERR_NONCE_MISMATCHPASSCMEQqBoq…

Withdrawal

#ScenarioExpectedActualResultTransaction
S14Owner withdraws from the vault+10000000 wallet, -10000000 ledger+10000000 wallet, -10000000 ledgerPASSEBG1SGFu…

Agent, gasless and x402 evidence

Run 26 Oct 2026 · real testnet transactions
NEP-366

Gasless merchant + agent charge

The merchant and agent sign charge delegates with their scoped keys; the relayer pays gas. Both NEAR balances are unchanged. A prompt-injected agent redirect is rejected on-chain.

Checks12/12
Agent Tab#70
Gas meter7 relays · 0.499507 NEAR
Relayertab-relayer.testnet
WEB

Gasless checkout route

The browser calls the merchant route; the server signs the delegate and the keeper relays it. This exercises the same path the merchant page uses with the gasless toggle.

Checks3/3
Tab#72
5qd5UoMBez…
AGENT

Prompt-injection containment

The agent is instructed to pay an attacker. The on-chain allowlist rejects it with RECEIVER_NOT_ALLOWED and moves nothing; the legitimate merchant invoice still settles.

AttackREJECTED
LegitimateEXECUTED
x402

Agent pays a paid API

An unpaid request returns a real HTTP 402 challenge. The MCP tool pays the invoice from a Tab, then the API verifies the on-chain charge_executed event before returning data. Replay, wrong payer, over-cap, redirected receiver and revoked Tab are all rejected.

Checks13/13
Invoice0.5 tUSDC · Tab #73
RedirectRECEIVER_NOT_ALLOWED

What the contract enforces

  • Caps: per-charge, period and lifetime limits are checked before the token call.
  • Authorization: only the designated spender can call charge; the owner controls pause/revoke.
  • Receiver policy: a fixed allowlist rejects redirected charges. Any is required for rotating Intent deposit addresses.
  • Replay: each Tab has a monotonic next_nonce; a consumed nonce cannot be reused.
  • Rollback: if the NEP-141 transfer fails, the callback restores the ledger and counters without erasing later in-flight charges.

Reproduce the run

The runners need the funded testnet accounts, the merchant charge key and the gas-only relayer. The setup scripts create them and write secrets only to the gitignored .env.

pnpm tsx scripts/create-testnet-accounts.ts
pnpm tsx scripts/deploy-testnet.ts
pnpm tsx scripts/setup-spender-key.ts merchant
pnpm tsx scripts/setup-spender-key.ts agent
pnpm testnet:e2e
pnpm test:meta
pnpm test:relayer-usage
pnpm test:agent-attack
pnpm test:x402
The runner writes docs/evidence/testnet-e2e.json and the copy rendered on this page.
Honest scope. This evidence covers the NEAR testnet contract and test token. The 1Click cross-chain route is a live mainnet quote preview, not a settlement. Executing the cross-chain leg requires a funded NEAR mainnet vault and real USDC; the demo does not claim otherwise. The NEP-366 relayer is testnet-only in this deployment; a production relayer needs monitoring, a funded gas balance and the same scoped-key validation. The x402 card is an x402-style HTTP 402 flow with a TabWrit scheme and on-chain receipt verification, not a full x402 protocol implementation.
Open your vault Try the merchant checkout Inspect the contract
Contract tab-vault.testnet · evidence generated 2026-10-24T22:57:17.475Z