
Reckn
Agent-payment escrow where a disputed delivery is re-executed, not judged. Reproduce, or refund.
Demo
About
When one AI agent pays another, the hard question is not which chain to deploy on. It is: when the payment is disputed, who decides — and does that decider belong to a chain? Every answer on offer is a party with a key: an operator inside a TEE, a bonded resolver, a quorum of voters. Each of those is per-chain — you redeploy the judge and re-earn the reputation on every chain your agent touches. Reckn's answer is that the decider should not be a party at all. A disputed delivery is re-executed: the pre-state is pinned, the disputed work is replayed against it, and the predicate the deal was funded against is evaluated. Reproduce, or refund. Because re-execution is deterministic anyone can redo it and reach the same verdict, and because it is a computation rather than an authority, it does not live on a chain. IT IS RUNNING. On Arc testnet, one escrow has settled four times in real USDC — and TWO OF THE FOUR WERE DECIDED BY PROOFS ABOUT WORK PERFORMED ON SOLANA, one releasing the seller and one refunding the buyer. The asset never left the chain it was funded on. Only the proof crossed, and there was no bridge and no light client anywhere on the path that chose the payout. Your own browser can read those four settlements off Arc at psyto.github.io/reckn without installing anything and without a wallet. WHAT EXISTED BEFORE THE EVENT (built July–August 2026; the disclosure below is exact) The disputed work is re-executed inside an SP1 zkVM and a real Groth16 proof settles the escrow directly. RecknZkEscrow has no owner, admin, resolver, pause or upgrade path, and settleWithProof is permissionless: the right to move money comes from a proof verifying and nothing else. That is enforced as a build condition — scripts/no-keys.sh fails the build if a privileged role, an unlisted state-changing function, or a msg.sender gate appears. The same re-execution runs on two deliberately dissimilar runtimes. On EVM, every account and storage slot is MPT-verified against the committed state root before real revm executes the seller's committed CALL in-guest. On Solana, the block bank_hash is recomputed with the SIMD-0215 lattice hash, the real transaction is signature-verified, and its transfer is re-executed. Two state models with nothing in common, and one generic on-chain verifier accepts both proofs. WHAT WAS BUILT DURING ETHONLINE (Continuity Track) — all of the following has LANDED 1. VERDICT DOMAIN SOUNDNESS. On day one we found a soundness bug in our own proof: the guest judged the balance delta on the low 64 bits while the off-chain engine used the full U256, so a DECREASE — pre = 2^64, post = 2^64 - 1 — proved as a maximal credit and released to the seller. A false release, found by writing the specification rather than by a test failing. Verdict values are uint256 on both sides now, the guest runs under a committed hardfork and block environment whose fields are bound into dealBinding, and every vector is decided twice — replayed off-chain and executed in-guest — and required to agree. 2. CROSS-VM SETTLEMENT — the headline, and it is done. One escrow settles an EVM proof and a Solana proof. The adjudicating program is named by the FUNDER, per deal, and pinned by its codehash; settleWithProof has no parameter with which a settler could name an adjudicator, and the dispatch is view-typed, so funder-chosen code runs under STATICCALL and cannot write state. The escrow lost its constructor, so any deployment of the same source is behaviourally identical. No resolver, no bridge, no light client on the path that decides who gets paid. 3. ARC / USDC — and it went to a public chain. The contract needed no change to settle in Circle's USDC, because a deal names its payment token at funding; what it needed was evidence in USDC's own units and semantics — six decimals, revert rather than a false return, and a blacklisting token. Then it was deployed to Arc testnet, where four settlements moved real testnet USDC: a proof released the seller, a proof of a decrease refunded the buyer, and TWO OF THE FOUR WERE DECIDED BY PROOFS ABOUT WORK PERFORMED ON SOLANA. 4. A KEYLESS TIMEOUT. Before it, a funded deal whose prover never appeared stayed funded forever. refundAfterDeadline returns it to the buyer after 30 days, permissionless — anyone may call it, and calling it gives the caller nothing. The waiting period is fixed in the protocol, chosen by no deployer and no funder. 5. THE BUILD CONDITION GREW. The script enforcing "no key can move a funded escrow" now reads two files rather than one, because the verifier the escrow calls carries the same authority. Its entry-point check became a CLOSURE rather than a list of forbidden names — a fallback() draining any funded deal passed all four of the old checks. WHAT WE DID NOT PLAN, AND KEPT. The first live settlement reverted with "Blocked address": Circle's USDC blacklists well-known compromised keys and the first deal had named one as its seller. That deal still holds 1.000000 USDC and can never release, because the seller is fixed at funding — and it is not lost, because the keyless timeout returns it. It is on the live page and in the repository rather than quietly redeployed around. WHAT IT REMOVES IS NOT A FEE — IT IS THE PERSON In a machine economy the binding constraint is human attention, not cost. An escrow that a person approves is a serialisation point: agents run continuously and in parallel, and every release queues behind somebody reading something. x402 has processed 165 million payments across 69,000 active agents. At the dispute rate card payments actually run at — about 0.5% — that is 825,000 decisions, or 14 to 34 person-years of reading depending on whether you allow two minutes each or five. That figure is DERIVED: the transaction count and the dispute rate are cited, the minutes-per-decision is an assumption, and it is stated so you can move it. Halve it and the shape is unchanged, because transaction count is the thing that grows and human attention is the thing that does not. Reckn's release condition is fixed BEFORE the work begins and evaluated by a computation both parties can run. Nobody reads anything, nobody approves anything, and nothing queues behind anybody. That is the point; the money below is what it costs to do it. A decided payment dispute costs a merchant $110 to $128 all-in today against a $20-50 processor fee — the rest is people reading conflicting stories. That cost exists because somebody has to decide. Settling a dispute here costs 0.0070-0.0077 USDC — measured on Arc against our four live settlements at the real gas price. Verifying a Groth16 proof and paying out is under a cent, and it does not grow with the size of the dispute. The number that constrains us is the other one: the average x402 payment is $0.52, and you cannot re-execute a fifty-cent API call under a zkVM and come out ahead. And it does not prevent disputes — it makes them not matter. The seller can insist, the buyer can deny, both can write at length, and the money moves the same way regardless. There is also no approval step: if anyone approved after seeing the re-execution, that approver would be a key. The proof's public values carry the outcome and the contract sends the money where the outcome says. Nothing decides in between. What counts as "reproduced" is fixed at funding, before the seller starts work, so the discretion is never created rather than being taken away from a judge. There is no dispute process here to invoke, either. The escrow has three states — None, Funded, Settled — and no Disputed one, because re-execution is not a remedy that a dispute triggers: it is how settlement works, every time. Money reaches the seller through exactly one function and that function requires a proof. There is no cheap happy path and there cannot be one, because "the buyer voluntarily releases" is a key moving a funded escrow, which is the thing this whole design exists to make impossible. So the comparison set is not every agent payment. It is the payments that would otherwise need an escrow at all — and nobody escrows a $0.52 API call either. Those payments are priced as a PERCENTAGE today — Upwork takes 20% falling to 5%, effectively 10-12%, plus 3-5% from the client; Fiverr a flat 20% from the seller and 5.5% from the buyer. Fiverr also charges a $2.50 surcharge under $75, which is an incumbent conceding that below a threshold a percentage does not cover the cost of standing behind the trade. Reckn charges a FIXED cost instead: one proof plus $0.007. Fixed and percentage cross at roughly a $10 delivery if a proof costs $1, or $50 if it costs $5. Above the crossover a $1,000 job pays $100-200 to a platform today at those rates, or a proof plus two thirds of a cent here — and what neither fee table prices is the operator: an arbiter who can be lobbied, subpoenaed, acquired or simply wrong, and who has to be re-established on every chain. What we deliberately do not quote is a dollar cost per proof. Succinct's network prices proofs by reverse auction and we have never bought one — we prove locally, 335 seconds for a fixture. That figure is unknown rather than estimated, and it is the one an adopter has to price. (And Solana holding 49% of x402 volume is why cross-VM settlement is not a stunt: for half of this market the money and the work are already on different chains.) WHAT CROSSES, AND WHAT DOES NOT The common misreading is that Arc verifies Solana, or that something is bridged. Neither is true. The work happens on Solana; the JUDGING happens inside an SP1 zkVM, which verifies the signatures, recomputes the block bank_hash and re-executes the transfer; and what reaches Arc is a Groth16 proof and nothing else. No bridge is needed because no asset moves — the USDC is on Arc at the start and on Arc at the end, and Arc never runs a Solana VM; it checks that one program executed correctly over public inputs. No light client is needed because Arc is never asked what Solana's state IS; it is asked whether a computation over a committed state is valid. What this does today: settle USDC on Arc conditionally on the re-executed result of work performed on Solana, with no bridge, no light client and no adjudicator anywhere on the path that decides the payout. What it does not do today: prove the committed inputs came from Solana mainnet. The guest recomputes a bank_hash over the account set THE DEAL NAMED — internal consistency, not provenance. A fabricated account set hashes just as well, and a test asserts exactly that. Closing it needs a light client, or an oracle with its trust model written down. Both halves or neither: without them a reader cannot tell this apart from a bridge, a light client, or an oracle, and the boundary is the interesting part rather than the hidden one. WHAT IS NOT TRUE YET STILL OPEN, AND NAMED, so you do not have to go looking: the adversarial key gauntlet is stopped at a hard stop; the live adversarial-input feature has a round-3 specification and no implementation; the real ERC-20 workload is not started. None of those three is load-bearing for anything claimed above, and all three are in the README rather than in a footnote. A proof carries the verdict's authority. It does not by itself prove the committed pre-state was the chain's real state: on EVM that anchoring lives in an off-chain layer, and on Solana the provenance of the committed bank_hash is not proven on-chain — a fabricated account set hashes just as well, and there is a test that says so. "No bridge, no light client" is true of the ADJUDICATION and not yet of the anchoring. Cross-VM settlement also created a new risk for the seller: a buyer can name a verifier that always returns Failed, and on-chain that is indistinguishable from an honest failure, so sellers must read the deal's verifier before working. Our open gaps are in the README, not in a footnote. HOW YOU WOULD USE IT, AND WHERE THAT STOPS Two calls. fund opens a deal; settleWithProof closes it. The second is permissionless — the key that pays the gas has no bearing on where the money goes — so there is no integration step where you hand us authority, because there is nothing to hand. Built during this event, for the half that had no tooling at all: a TypeScript package and a starter. createDeal opens a deal. sellerPreflight answers "what am I about to work on?" before you do the work, and it exists because a buyer can name a verifier that always fails. submitProof settles. verifySettlement decodes what happened from the chain rather than from our report of it, and it distinguishes a payout a proof authorised from the 30-day timeout refund, which the escrow emits as a separate event precisely so nobody has to infer which kind it was. reckn terms turns YOUR transaction into deal terms with one read-only call and no key — the step that previously meant reading a Rust crate and assembling an anchor, a plan and a predicate by hand. It refuses five kinds of terms that open a deal cleanly and then never settle, including a predicate satisfied by doing nothing, which pays the seller in full for no work. reckn terms needs an endpoint that answers eth_createAccessList and eth_getProof, and Arc's public testnet RPC answers neither — measured 2026-09-09. So on Arc you can compute a binding and fund against it, which needs one block header; what you cannot do from that endpoint is simulate the call or capture the witness. We would rather say this here than have you find it. WHERE IT STOPS, SAID PLAINLY. Settlement is complete and permissionless. Proving is not self-serve: a proof needs the SP1 toolchain and minutes of CPU — measured on one laptop, 335 s for the shipped fixture and 497 s for a real mainnet Uniswap v3 swap, which is 32x the cycles for 1.49x the time. So using Reckn on YOUR OWN job today means proving it with that toolchain; what you can do without it is fund and settle against a workload already proved. Nobody outside this project has used any of this, and nothing here claims otherwise. HOW TO CHECK ANY OF THIS WITHOUT TRUSTING US. Open https://psyto.github.io/reckn/ — your browser reads Arc directly and compares the deployed bytecode against the source in this repository. RecknZkEscrow has no constructor, so the same source always produces the same deployment, which is what makes that comparison mean anything. SUBMITTING FOR: Arc — Launch on Arc Testnet & Push to Mainnet (primary), and Arc — Best DeFi or Agentic Application. Arc mainnet is not deployed and the reason is not ours: Circle had not published Arc mainnet contract addresses as of 2026-09-06, so the bounty's "deployed OR deployment-ready" is met on the second branch, and the same script deploys there unchanged once that address list exists. ============================================================================== PRE-EXISTING WORK DISCLOSURE — reproduced in full, as ETHGlobal's rules require ============================================================================== Pre-existing work disclosure — Reckn (ETHOnline 2026, Continuity: Ship a Feature) Project: Reckn — escrow for agent-to-agent payments where the dispute adjudicator is deterministic re-execution, not a trusted judge. Repository: github.com/psyto/reckn Track: Continuity — Ship a Feature Team: Hiroyuki Saito (solo) 0. AMENDMENTS This document is reproduced in full in the submission description, so a reader is entitled to know where it has changed since it was first written and why. Nothing is removed; the superseded wording is quoted here. 2026-09-04 — §1 — "the repository is still private" — It was made public that day, ahead of submission, so the application could be reviewed against the actual source. 2026-09-05 — §3 — five items — Tasks 008 (verdict domain soundness) and 009 (cross-VM settlement) did not exist when this was written and became the event's two headline items. Declaring them late is worse only than not declaring them. 2026-09-05 — §5 — "c-kzg and ecrecover are disabled in-guest" — False, and inherited from the same false sentence in zk-verdict/README.md. The true limitation is narrower and is stated in §5. 2026-09-07 — §3 item 5 — "Sponsor integrations (new): World AgentKit gating who may open a dispute. (Integrations against Arc/USDC and Hedera/x402 … will be attempted only if those sponsors are confirmed for this event.)" — World AgentKit was never built and is out of scope by ruling, while Arc was built, deployed to testnet, and settled four times. The old wording named the thing that does not exist and left the strongest thing that does in a conditional parenthetical — for a track judged on the event's diff, exactly backwards. 2026-09-07 — §3 item 3 — "…so any observer can attempt to persuade the LLM judge, and watch re-execution disagree." — Task 004's specification made its headline claim judge-independent by founder ruling, and forbids citing a judge we wrote ourselves as evidence of persuasion. The disclosure was promising the thing the specification deliberately removed. The two 2026-09-07 amendments were made before submission, not after, and the superseded text is quoted above rather than deleted. 1. THIS PROJECT HAS NEVER BEEN SUBMITTED TO ANY HACKATHON Reckn was built in July–August 2026 and was never submitted anywhere — not to an ETHGlobal event, not elsewhere. A submission kit (SUBMISSION.md) was drafted but its pre-flight items "Repo public" and "Submission form" were never completed. The repository was private until 2026-09-04, when it was made public so that this application could be reviewed against the actual source. It has received no prize, no judging, and no public showcase. 2. WHAT EXISTS BEFORE THE EVENT (BUILT 2026-07-26 → 2026-08-02) 93 commits on master plus ~20 feature branches, all authored before ETHOnline begins. Full history is preserved in the repository and is available for inspection. Pre-existing components: - contracts/ — RecknEscrow (optimistic settlement: bonded resolver, challenge window, resolver quorum, slashing, seller data-availability bond). 57 tests. - reexec-evm/, reexec-svm/ — deterministic re-execution engines with four predicate forms. 16 + 30 tests. - zk-verdict/ — the keyless path. Three SP1 zkVM guests (program/, program-revm/, program-svm/) committing identical public values to one on-chain verifier; RecknZkEscrow, which settles escrow on a verified Groth16 proof with no resolver. 12 tests, including a real Groth16 proof settling to the seller on-chain. - keeper/, reckn-svm-keeper/, binder/, escrow-svm/, dashboard/ — keepers, the LLM-judge-vs-replay money-shot dashboard, and a 35-second demo video. - ERC-8004 reputation projection and x402 / EIP-3009 payment plumbing. Total: ~140 tests. All of the above is pre-existing and is not offered as work done during ETHOnline. Also pre-existing (added 2026-09-03, before the event begins): an autonomous development harness (AGENTS.md, CLAUDE.md, .claude/agents/, scripts/no-keys.sh) and the planning documents in docs/ethonline-2026/. These are tooling and planning, not product features, and none of the five items in section 3 is implemented by them. They are disclosed here so that the repository history before 2026-09-04 is fully accounted for. 3. WHAT WILL BE BUILT DURING THE EVENT (2026-09-04 → SUBMISSION) 1. Keyless timeout for RecknZkEscrow. The keyless escrow currently has no deadline: if no proof is ever produced, funds lock permanently. A permissionless, deadline-based refund closes this without reintroducing any privileged key. 2. Adversarial key gauntlet. A test suite and UI that publish every participant's private key and demonstrate that no key can move a funded escrow. 3. Live adversarial dispute input. (Amended 2026-09-07 — see Amendments.) Open the seller's delivery claim to free-form input, so any observer can write whatever they like about what was delivered — and watch it change nothing. The claim is that prose does not move re-execution, and it is stated without reference to any judge, because a judge we wrote ourselves being "persuaded" would be evidence of nothing. 4. Real ERC-20 workload. Extend the in-guest re-execution from the current single-slot SSTORE fixture to a real token-credit predicate, with measured cycle counts. 5. Sponsor integration: Arc. (Amended 2026-09-07 — see Amendments.) Reckn's keyless escrow settles in Circle's USDC on Arc with no change to the contract — a deal names its payment token at funding, so a chain whose money is USDC needs evidence rather than adaptation. Built during the event and deployed to Arc testnet, where four settlements moved real testnet USDC: a proof released the seller, a proof of a wrong execution refunded the buyer, and two of the four were decided by proofs about work performed on Solana — one escrow, two virtual machines, no bridge and no resolver in the path that chose the payout. A fifth deal is frozen at 1.00 USDC because Circle's USDC blacklists its recipient; it is refundable by the keyless deadline and by nothing else, and it is recorded rather than hidden. (At application time Arc and Hedera were both listed as conditional, because the full prize list was not yet published. Arc is the only sponsor integration attempted; Hedera and World AgentKit were dropped by ruling on 2026-09-06.) 6. Verdict domain soundness. The zkVM guest takes its balance delta on limb 0 of a U256, so a decrease from 2^64 to 2^64−1 is accepted as the largest possible credit — a false release. The guest also sets only chain_id, leaving the spec and block environment out of sync with the off-chain re-execution, which uses the full U256. Both are closed, with tests. 7. Cross-VM settlement. A proof of work performed on Solana settles an escrow funded on Ethereum. Today the SVM verdict is verified on-chain by the same general verifier, but only EVM proofs reach settleWithProof. This closes that gap with no resolver, no bridge, and no light client in the adjudication path. 4. HOW THE BOUNDARY IS ENFORCED - All event work lands in commits dated within the event window, pushed continuously — no single squashed commit. - Event work is confined to identifiable paths and is summarized in a CHANGELOG entry that names the pre-event baseline commit. - All new parts remain open source, permanently. 5. HONEST LIMITS OF THE PRE-EXISTING ENGINE Carried from zk-verdict/README.md so nothing is overstated: verdict values map to u64 (closed by item 6 above); the guest proves one CALL plus one delta check (a full block or arbitrary contract set is more cycles, same architecture); and the state_root-to-block-header binding remains an off-chain layer. On precompiles, this document said until 2026-09-04 that c-kzg and ecrecover are disabled in-guest. That is false, and it was inherited from the same sentence in zk-verdict/README.md. revm-precompile falls back to pure-Rust backends when the native features are off — k256 for ecrecover (secp256k1.rs:1-8, preference order secp256k1 → k256) and arkworks for KZG (kzg_point_evaluation.rs:87-101). Nothing is missing in-guest. The true limitation is narrower and worse to state loosely: the guest and the off-chain engine run different implementations of the same precompiles, and equivalence has never been checked. Corrected here rather than left standing, because a disclosure that carries a false sentence is not a disclosure.
How it's made
The re-execution engines are Rust. On EVM, reexec-evm drives revm 38 and verifies each account and storage slot against the committed state root with alloy-trie before replay; on Solana, reexec-svm replays a committed signed transaction against a committed account snapshot under LiteSVM. Both emit the identical VM-neutral ReplayRecordV1 through one shared codec, which is what makes the trace hashes comparable across VMs at all, and a cross-VM router replays either kind through a single interface. The keyless path runs that same re-execution inside an SP1 zkVM. The EVM guest MPT-verifies the prestate in-guest with alloy-trie and then runs real revm over the seller's committed CALL (406,715 cycles, measured); the Solana guest recomputes the block bank_hash from the committed accounts with solana-lattice-hash, signature-verifies the real transaction, and re-executes its transfer (986,097 cycles). Both commit the same public values, and one generic verifier contract checks either Groth16 proof against SP1's canonical verifier. Settlement contracts are Foundry/Solidity; the Solana escrow half is Pinocchio. ARC IS THE PARTNER TECHNOLOGY, AND IT IS DEPLOYED. On Arc, USDC is the native gas token and Circle predeploys an ERC-20 face over the same balance at six decimals. Reckn's escrow settles against that face with no contract change at all, because a deal names its payment token when it is funded — which is the whole reason a chain whose money is USDC needed evidence from us rather than adaptation. Adding a payable path would have been the easy move and was refused: the function surface is part of the central claim, and widening it to chase a chain's ergonomics would have cost the thing the project is for. The escrow is live on Arc testnet with four settlements behind it. The part worth calling out is not a library. Our whole claim is "no key can judge", and a claim like that decays the moment someone adds one privileged field — so it is a build condition rather than a promise. scripts/no-keys.sh fails the build if a privileged role appears, if the state-changing surface grows beyond the enumerated functions, if any msg.sender gate is introduced, or if any deployment-time configuration exists at all — and it is itself tested against negative controls. During the event it grew from a denylist of forbidden names into a property: every call-shaped token in the audited files must belong to a closed allowlist, and the verifier contract is pinned to a 43-token vocabulary and a fixed twenty-piece skeleton — so approve, permit, low-level calls and inline assembly are each rejected by a rule that never mentions them. The old check said "the constructor does not store msg.sender"; after the constructor was removed entirely that sentence would have matched an empty range and passed vacuously, so it was replaced. An observer that watches nothing is not an observer. Development runs through a harness that writes a spec with mechanically checkable acceptance criteria, has a second independent model review it adversarially, and only then implements. Every spec and every review verdict is committed, including the ones that failed. That process is why the soundness bug above was found on day one rather than after shipping, and why we know things like: both test runners exit 0 on a filter matching nothing, so criteria that only check exit status pass with no tests written; our one-command demo discarded its suite's exit status; and regenerating one Groth16 fixture takes 335 seconds, not the 34 the repo advertised for a different guest. The gates repaid the effort in a way worth reporting, because it is the opposite of a success story. Three full acceptance runs were red before one was green, for three different reasons, and two of them were the same defect wearing different clothes: a correct sentence in a specification sitting on top of code that enumerated names. One specification said its mutation witness covered a narrow glob; the gate globbed wider and swept in a sibling task's files. Another said a sandbox holds "this task's scripts only"; the script implemented "only" as a list of two filenames. Both were invisible while exactly one sibling gate existed — landing a second one exposed both in a single run. The second is the one worth reading twice: the mutant that exists to prove a discovery rule is a closure was itself defeated by one new name.