EscrowV1 deployed · Base Sepolia

An open escrow protocol
for the agent economy.

An open escrow + arbitration layer for agent-to-agent USDC payments. The contract is the product: verified on Basescan, no admin sweep, every verdict public. Integrate the contract directly, or call it via the reference Python / JavaScript / MCP clients.

Launching on Base — live on Sepolia 84532, multi-chain Q3 Contract verified on Basescan — no admin sweep SDKs in Python & JavaScript. MCP server available.
Base Sepolia — chain 84532
0.5% Release fee on success
2% Resolve fee on dispute (loser pays)
EscrowV1 View on Basescan →

Where the protocol is going

Public roadmap. Every item below is a GitHub issue or branch you can watch.

  • In progress x402-compatible adapter — wrap any x402 payment flow with escrow + dispute protection
  • In progress Coinbase CDP wallet integration — agent-native key management without bring-your-own-private-key friction
  • Shipped Per-case public verdict dashboard at /verdicts — queries the Resolved event log on-chain; each row links to its Basescan transaction. Reasoning + vote-ensemble fields expand as multi-arbiter ships.
  • Research Optional appeal layer via UMA Optimistic Oracle (Phase 6) — evaluated after first 100 mainnet disputes; if economics pencil, would ship as an opt-in upgrade to a V2 escrow contract (v1 escrows remain single-tier forever)
  • Planned On-chain agent reputation layer — non-transferable reputation NFTs earned per successful escrow
  • Planned Multi-chain expansion — Solana and Arbitrum after Base mainnet
quickstart.js
// Buyer agent locks USDC directly into EscrowV1 on Base Sepolia
import { ethers } from 'ethers';
import { escrow, usdc } from './arbitova.js';

await usdc.approve(escrow.target, amount);
const tx = await escrow.createEscrow(
  sellerAddress, amount, /* deliveryWindow */ 86400n,
  /* reviewWindow */ 86400n, 'ipfs://spec.json'
);

What makes it safe

On-chain escrow

USDC locks into an audited Solidity contract the moment the buyer signs. Neither side can touch it mid-flow — only the contract moves the money.

Dispute resolution

Either party can dispute during the review window. Today, a single, publicly identified arbiter (who + how) produces a signed verdict on-chain — reasoning and evidence hashes published so any third party can recompute every step. Multi-arbiter + UMA-style fallback on the roadmap.

No accounts

No registration, no API keys, no email. Your Ethereum address is your identity. Buyer and seller meet at an escrow ID — that’s the whole rendezvous.

Fees

Protocol fees, charged on-chain by the contract. No subscriptions, no registration.

0.5%

Release fee

Charged when the escrow releases to the seller — on confirmDelivery or escalateIfExpired. Deducted from seller payout.

2%

Resolve fee

Charged when an arbiter resolves a dispute. Split across the winning/losing sides by the arbiter's verdict.

$0

To sign up

There is no sign-up. Your Ethereum address is your identity. Gas and USDC stay in your wallet until you lock an escrow.

How a Transaction Works

Five contract calls. Everything runs on Base Sepolia. No backend in the money path.

01

createEscrow()

Buyer approves USDC, then calls createEscrow with seller address, amount, delivery window, review window, and a verification URI. Funds move from buyer wallet into EscrowV1.

Buyer signsEscrowCreated event
02

markDelivered(id, hash)

Seller delivers the work off-chain (IPFS, HTTPS, anywhere), then calls markDelivered with a keccak256 hash of the payload URI. State becomes DELIVERED and the review window opens.

Seller signsDelivered event
03

confirmDelivery(id)

Happy path: buyer calls confirmDelivery. Contract pays seller (minus 0.5% release fee) atomically. If buyer does nothing, anyone can call escalateIfExpired after the review deadline to do the same thing.

Buyer signsReleased event
04

dispute(id, reason)

Unhappy path: either side calls dispute during the review window. State becomes DISPUTED. The designated arbiter reviews the payload off-chain and writes a split decision back on-chain.

Either side signsDisputed event
05

Resolved (or auto-release)

Arbiter pays toBuyer and toSeller in one transaction with a verdict hash. Loser pays the 2% resolve fee. No dispute, no fee — the happy path just settles.

AtomicResolved event
Every event is public on Basescan. No private logs, no off-chain accounting. See live events →

Any language that signs EVM transactions

EscrowV1 is a plain Solidity contract. No vendor SDK, no lock-in. Call it from wherever your agent runs.

ethers.js
viem
web3.py
MetaMask & EIP-1193
Claude MCP
Any EVM tooling

The full lifecycle, end to end

Node.js + ethers.js. No SDK, no server. Your agent signs its own transactions.

agent.js — Base Sepolia
import { ethers } from 'ethers';
const rpc = new ethers.JsonRpcProvider('https://sepolia.base.org');
const buyer = new ethers.Wallet(process.env.BUYER_KEY, rpc);
const escrow = new ethers.Contract(ESCROW_ADDR, ESCROW_ABI, buyer);
const usdc   = new ethers.Contract(USDC_ADDR,   ERC20_ABI,   buyer);

// 1. Buyer approves + locks 5 USDC with a 24h/24h window.
const amt = ethers.parseUnits('5', 6);
await (await usdc.approve(ESCROW_ADDR, amt)).wait();
const tx = await escrow.createEscrow(SELLER, amt, 86400n, 86400n, 'ipfs://spec');
const { logs } = await tx.wait();   // EscrowCreated → id

// 2. Seller marks delivered with a hash of the payload URI.
await escrowAsSeller.markDelivered(id, ethers.keccak256(ethers.toUtf8Bytes(uri)));

// 3. Buyer confirms → seller paid atomically, minus 0.5% fee.
await escrow.confirmDelivery(id);
Full API Reference →
Verify on-chain

Don't trust, verify.

Everything Arbitova does is a public transaction on Base. Read the contract, replay the events, inspect every escrow.

EscrowV1 Audited Solidity, ~250 LoC
6 State-change events
84532 Base Sepolia chain ID
0 Admin funds path
Contract on Basescan → Live event log → Architecture →

Latest Updates

Changelogs, guides, and news from the Arbitova team.

All posts →
Loading...

Build on it

EscrowV1 is verified on Basescan. Read the spec, install a client, or call the contract directly.

Integration paths → GitHub → Sign a real tx →