Skip to content
ยท 9 min EXPERIMENT

Brick #5: The Experiment Ran - a Three-Hop Supply Chain Settled on Arc Testnet

The final brick of the MVP wave: shipment dogfood-1794151620383 ran a real three-hop custody cycle on Arc testnet (chainId 5042002) - three ERC-8183 escrowed jobs (66/67/68), six confirmed transactions, all hops verified in 53 seconds, publicly replayable via GET /api/ledger/shipments/dogfood-1794151620383. Includes the live-discovered executor fixes and the 2-Critical audit that held under live fire.

AB
AgentBadge Team
Agency for the Agentic Web
Brick #5: The Experiment Ran - a Three-Hop Supply Chain Settled on Arc Testnet
๐Ÿค– For AI agents: Machine-readable: JSON Markdown llms.txt Agent Guide

A real three-hop supply chain executed end-to-end on Arc testnet: shipment dogfood-1794151620383 settled three ERC-8183 escrowed jobs (shipper -> agent -> device -> org, 0.01 USDC per hop) in 53 seconds - the final proof that verifiable transitions compose into a working economic loop on live rails, not just in test fixtures.

Final brick of the MVP wave - start here: The Bedrij Principle, then Brick #1: Typed Participants, Brick #2: Typed Evidence, Brick #3: Scenario Matrix and Brick #4: Verifiable Vitrine. The hypothesis under test: a complex economic system can be composed from verifiable state transitions.

Four bricks built and armored the write path: typed participants, typed evidence, a scenario matrix that survives seven named violations, and a public replay view. The anchor article ended with a promise - "The experiment has started." This article is the receipt: on 2026-11-08 a real three-hop shipment ran the full custody cycle on Arc testnet, each hop escrowed in its own ERC-8183 job, all three settled and verified in 53 seconds. Proof -> acceptance -> settlement, on real rails, with transaction hashes you can open yourself.

What exactly ran?

Short answer: shipment dogfood-1794151620383 - a cold-chain delivery with three hops, played by three different participant types from Brick #1. A shipper contracted an agent (Plant intake), the agent handed custody to a device (ColdVan unit), and the device delivered to an org (Restaurant). Each hop carried a 0.01 USDC escrow in its own ERC-8183 job on the ref proxy 0x0049e5...bf6a0, Arc testnet (chainId 5042002). Result: status completed, 3/3 hops verified, outstandingUsdc: "0".

The shipment, in one table:

hoplegjobcreate txsettle tx
0shipper -> agent (Plant intake)660x606f18...0xf15f6e...
1agent -> device (ColdVan unit)670xf9ebb8...0x35f507...
2device -> org (Restaurant)680xdc7c70...0x7798a4...

Six real transactions - three job creations, three settlements. Not a fixture, not a fork, not a replayed simulation: Arc testnet, confirmed on the public explorer.

The participants are real keys with real labels (Brick #1's typed roles, live):

roleaddresstype
client (shipper)0xcdd23d104AA4C10DE65F4DD0571eDfeC0458699dorg
hop 0 provider - Plant intake0xb21fa9D9CE930FAf52545318169569007c027005agent
hop 1 provider - ColdVan unit0x67d43A4065Dd69165061062B3128EDA50f1F7C96device
hop 2 provider - Restaurant0x8B9FC021430c4fAD90389DcbdE4B1140012Cd98Dorg
evaluator0xc9fA59e889c25b7f0b9494ed5c6bC62fe7EcCC56signer

What did each hop actually execute on-chain?

Short answer: the full ERC-8183 lifecycle, not just an event log entry. Per hop the executor drives four stages of contract state: the provider signs setBudget, the client approves and funds the escrow, the provider submits the deliverable, and the evaluator completes the job - releasing escrow only after the accept.

Flowchart of the live shipment: the shipper hands custody through three ERC-8183 jobs - hop 0 job 66 shipper to agent, hop 1 job 67 agent to device, hop 2 job 68 device to org - each hop runs the same four-stage lifecycle, provider setBudget then client approve and fund then provider submit then evaluator complete; the append-only ledger records 13 events in 53 seconds with 0 USDC outstanding and the whole run is replayable at GET /api/ledger/shipments/dogfood-1794151620383, with a flagged honesty note that pay and txHash fields are ledger-asserted and the explorer links are the independent check
The live run end to end: three hops, one lifecycle per hop, six transactions into the ledger - and the public replay anyone can curl. Dashed edge: the honesty flag that ships with the response itself.

That ordering is the Bedrij primitive running on contract state instead of test fixtures. Hop i+1 cannot hand off before hop i is paid - the same ShipmentOrderError guard the scenario matrix breaks against, now re-deriving state from a log whose pay/verify events were produced by real settlement transactions. The economic loop the anchor drew as proof -> acceptance -> settlement fired three times in 53 seconds of wall clock (15:27:41Z - 15:28:34Z).

And because the run wrote to the production Postgres ledger (SC_DOGFOOD_DB=1), the whole timeline is publicly replayable - Brick #4's vitrine, pointed at a real shipment:

curl https://agentbadge.xyz/api/ledger/shipments/dogfood-1794151620383
{ "shipmentId": "dogfood-1794151620383", "status": "completed", "timeline": [ "13 events, 15:27:41Z - 15:28:34Z" ], "hops": [ "3 hops, all verified, jobs 66/67/68" ], "aggregate": { "completedPct": 100, "outstandingUsdc": "0" } }

(Truncated for print - the verbatim response is at the URL above and in the evidence pack.)

A three-car conveyor train on glowing rails moving through a testnet landscape: three crates marked agent, device and org each carry a 0.01 USDC escrow capsule; below each car a small green checkmark and a transaction hash; a timestamp ribbon reads 53 seconds
The custody cycle on real rails: three hops, three escrowed jobs, six confirmed transactions, 53 seconds of wall clock.

What did running it live actually find?

Short answer: four executor bugs that no test caught, because the in-memory chain lets any key call any method. The ref contract does not. Running against real signatures exposed the write path's hidden assumptions - which is exactly why a live dogfood is the last brick, not the first.

  • Provider-signed setBudget. The ERC-8183 ref variant restricts setBudget to the provider account. The executor used to send it as the client - on a real contract that is a revert, in a test it is silent. Fix: spec.providerKey plus a sendAsAccount path that signs locally and broadcasts the raw transaction.
  • Provider-signed submit before complete. complete requires the job to be in Submitted status - the provider must declare the deliverable first. The earlier order tried to complete directly after funding.
  • ClientCannotBeProvider. Hop 2's receiver is the restaurant - but the client wallet cannot also act as a provider. The run needed a dedicated restaurant key (SC_DOGFOOD_RESTAURANT_KEY) or the contract refused the hop.
  • Resume, don't orphan. A failed live run leaves funded-but-unfinished jobs on-chain. SC_DOGFOOD_RESUME_JOBS reuses them instead of orphaning escrow - the same C-1 orphan-escrow finding the audit flagged before we ever went live.

Two earlier attempts informed this one. An in-memory run (dogfood-1794150937615, jobs 63/64/65) exercised the resume path on reused jobs; the DB-backed run above is canonical because it is the one the public replay serves.

Did the audit hold up under live fire?

Short answer: yes - the two Critical findings were exactly the class of bug that kills a live run, and both were fixed before the first testnet transaction. Audit first, live second: the gate was load-bearing.

Brick #5 had its own external adversarial review before going live. Verdict: REQUEST CHANGES - 2 Critical, 4 High confirmed. C-1 was the orphan-escrow hole: if createShipment succeeded on-chain but the ledger write failed, escrow sat funded with no record. C-2 was a fail-open budget path - a null/zero-amount job could slip past as a plan of "0". Both were fixed and re-verified, the pack went from 87/87 to 99/99 green with 12 new regression tests, and only then did the executor see a real network. The findings that would have lost testnet escrow were found by an auditor, not by a revert.

A glass audit shield standing in front of a blockchain rail line: inside the shield a clipboard lists C-1 orphan escrow and C-2 fail-open budget both stamped fixed; behind the shield a small train passes safely; badge reads REQUEST CHANGES resolved 99/99
The gate that held: two Critical findings - orphan escrow and fail-open budget - fixed and re-verified before the first live transaction.

What does this prove - and what does it still not prove?

Short answer: the transition contract executes on real rails. It does not yet prove automated verification, non-linear chains, or real money at scale - and the article says so in the same breath as the result.

claimstatus 2026-11-08
Verifiable transitions compose into a chainproven - 3 hops, ordered, verified
Per-hop escrow on a real contractproven - ERC-8183, 6 confirmed txs
Ordering enforced from an append-only logproven - same guard as Brick #3
Public replay of a real shipmentproven - endpoint live now
Automated evidence evaluationstill manual - a delegated evaluator gates each settle
Evidence authenticityadvisory - typed refs, self-declared
Non-linear / branching chainslinear hops only
Real-value settlement0.01 USDC per hop, testnet gas

Three honesty notes matter for anyone replaying the shipment. The pay/txHash fields in the replay response are ledger-asserted - written by our executor, not independently chain-verified (the tx hashes above are the independent check; open them). Settlement was ops-settled - the evaluator signer is a delegated operations key, not the logical evaluator in the plan. And the amounts are deliberately tiny: a dogfood run proves the rail, not the revenue.

The experiment ran

The anchor article asked whether a complex economic system could be composed from verifiable state transitions, and promised five bricks of measurement. The bricks are laid:

roles      - who acted          (Brick #1)
evidence   - what they claim    (Brick #2)
matrix     - how it breaks      (Brick #3)
vitrine    - how you check      (Brick #4)
live       - did it run         (Brick #5 - this)

What shipped in one number: 53 seconds, 3 hops, 6 transactions, 13 log events, 0 USDC outstanding - a custody cycle that a stranger can re-derive from a public endpoint, with the transaction hashes in the explorer one click away. The transition contract did not just type-check against a fixture. It settled.

That is the whole answer to the hypothesis. Not "we believe it works" - here is the shipment, replay it.


For AI Agents

  • What this proves: proof -> acceptance -> settlement executed on real rails - a three-hop ERC-8183 custody cycle settled on Arc testnet (chainId 5042002), publicly replayable via GET /api/ledger/shipments/dogfood-1794151620383.
  • Live surface: GET https://agentbadge.xyz/api/ledger/shipments/dogfood-1794151620383 - canonical ShipmentReplayResponse, no auth; ref proxy 0x0049e5362736c933055e502b3cf3ba90cc0bf6a0, jobs 66/67/68.
  • Lifecycle per hop: provider setBudget -> client approve+fund -> provider submit -> evaluator complete.
  • Honesty flags: pay/txHash fields are ledger-asserted; evidence is advisory; settlement is ops-evaluator-gated; linear hops only; 0.01 USDC per hop.
  • Series: The Bedrij Principle -> Brick #1 -> Brick #2 -> Brick #3 -> Brick #4 -> this.

Building agent-native supply chains? The ledger package is @agentbadge/econ-events on npm, and the anchor hypothesis this brick closes is in The Bedrij Principle.

Don't certify. Measure.