Skip to Content
How it worksTrust and limits

Trust and limits

This page is the honest part. Read it before you deposit money you care about.

Is the port faithful

Yes in design and in code, with four gaps in trust. The pool on Cardano keeps every safety rule of the pool on Base. Where Cardano forced a new mechanism, the new mechanism enforces the same rule. Three readers, the lead of the build and two independent reviewers, compared the code rule by rule against the vendored 0xbow contracts of the Base implementation and found no way to move value without a valid proof.

It is not as trustworthy as Base. Base runs audited 0xbow code with keys from a public ceremony. The Cardano circuits and validators are new code, checked by tests, live runs and three reads, with keys that one party made.

RuleBaseCardanoResult
A note is a hash of value, label and a secret partHashed by the contract at depositHashed inside the insert proof. The chain checks the value against the real depositSame rule
A note is spent onceA list of spent tags in storageOne trie root. Each spend proves that its tag is newSame rule
Only real deposits enter the treeThe contract updates the tree itselfA proof updates the tree. The chain derives every input of that proof from the deposits and the queueSame rule
A spend proves ownership, approval and the amountThe 0xbow withdraw circuitThe same checks, with a fixed depth of 32 and 64-bit amountsSame rule
Nobody can redirect a paymentThe proof is tied to the recipient and the feeThe proof is tied to every payout, the relayer and an expiry. The chain checks the outputsSame, plus expiry
Only approved deposits pay in privateThe latest approved set onlyThe latest approved set onlySame rule
The depositor can always exit in publicA map from label to depositorThe depositor’s key is part of the label, and that key must signSame rule
Who sees the note secretsThe Base implementation’s server makes the proofThe agent makes the proof. The relayer sees the proof and the payouts onlyStronger
What the admin can doThe owner can upgrade the entry contractNo upgrade. The admin can pause deposits and tune bounded settingsStronger
A second deposit with the same secretRefused by the contractNot refused on chain. The SDK prevents itWeaker
The start state of the poolFixed by the constructorWritten by the deployer, checked off chain in partWeaker
The proving keysFrom the 0xbow ceremony with many partiesMade by one partyWeaker
Outside reviewAudited by ChainSecurity and Trail of BitsNoneMissing

What you trust today

You trustFor whatIf it is dishonest
The party that ran the key setupNot keeping the randomness of the phase two contributionIt can forge proofs and drain the pool
The deployerAn honest first pool datum, config and ASP datumIt could have planted a second root, a fee balance or a negative fee rate and take deposits later. The validators of this pool check the first state only in part
The ASP operatorsApproving your depositThey can keep you out of private payments. They cannot touch your money, because ragequit needs no approval
The adminsNot pausing deposits foreverThey can pause deposits. They cannot stop payments or exits, change a key or move funds except accrued fees to the treasury
Your chain providerNot watching youIt sees your deposit wallet, your one-time addresses and your seller payments
The relayer and the indexerNothingEvery answer is checked against the chain. The worst case is a delay

The first two rows are the reason this pool must hold only the team’s own funds until a public ceremony and an on-chain start state check exist.

What the comparison found and fixed

The comparison on 2026-10-07 found five weaknesses outside the validators that could cost money. All five are fixed and were proven on Preprod in runs 5 and 6.

FindingNeeds a dishonest partyFix
With a lost store and the same seed, the SDK used a note secret again, and the new note was locked for goodNoThe SDK syncs before a deposit and skips every secret the pool has seen
A copy of a deposit’s precommitment and refund key, absorbed first, took over the SDK’s record, and the real note was lockedA third party, at its own costThe SDK follows the exact output of a deposit it sent itself
After a lost reply the relayer called a settlement failed although it could still land, and the SDK dropped the change noteNoThe relayer answers uncertain, and the SDK releases a note only on a known refusal
The SDK checked the protocol fee against a rate that the indexer reported, so an operator could take most of a noteOperatorThe SDK reads the rate from the config output with its own provider
The SDK accepted any deadline in a quote, so a relayer could keep a note reserved for hoursOperatorA quote must expire within 15 minutes of the chain tip

What is still open

GapWho it can hurtStatus
The proving keys come from one partyEvery depositorOpen. A ceremony with outside contributors before outside deposits
The start state of the pool is not enforced on chainDepositors who do not know the deployerOpen. Bind it on chain before outside deposits, which means a new pool
No outside audit of the circuits and validatorsEvery depositorOpen
A second deposit with the same precommitment is not refused on chainA depositor whose SDK is bypassedThe SDK prevents it
The agent’s chain provider sees the whole pathYour privacyOpen. Run your own node
A public exit reveals the payments of its deposit by subtractionYour privacyBy design, as on Base. Keep change in the pool
The privacy defaults of the specification are not built: no warning on matching amounts, no waiting rule, no lower limit on the approved setYour privacyOpen
After a lost store the one-time addresses repeatYour privacyOpen. It loses nothing
A repeated x402 request after an unclear answer pays twiceYour walletOpen
Funds left at a one-time address after a failed second leg are not trackedYour walletrecoverOneTimeFunds moves them by hand
The default note store is in memoryYour change notesPass a file store
An admin who updates the config every block, or a flood of Inserts, can delay an exit or a paymentYour timeOpen. It can delay, not take
No rule pins the pool’s ADA in a token pool. The crank or the relayer could lower the pool UTXO’s 6 ADA to the ledger minimum of about 5.2 ADAThe reserve, not the tokensOpen. A validator change, so a new pool
The relayer attaches 2 ADA to every payout and charges 1 tUSDM per payout. Whether that covers its ADA depends on the price of ADA, and the relayer has no price feedThe relayer’s walletOpen. The fee is a setting; mainnet needs a price

What a user feels

BaseCardano today
Time for one payment7 to 15 secondsAbout 80 seconds on Preprod
Cost on top of the priceAbout a cent of gas, paid by the Base implementation1 tUSDM per payout, no ADA
Smallest payment0.001 USDC0.000001 tUSDM in the pool; the seller output still needs about 1.1 ADA, which the relayer attaches
AssetUSDCtUSDM on Preprod, USDM on mainnet
Pool actionsMany per blockAbout one per block
ExtrasMCP server, agent spend limits, sanctions screening, note recovery from the seed, gasless depositNot built

The Base numbers come from the documents of the Base implementation. The Cardano numbers are measured on Preprod.

Before mainnet

The mainnet canary runbook describes a small pool with the team’s own funds, capped by the config. That is the only safe step today. Before anyone outside the team deposits, three things must happen, in this order.

  1. A key ceremony with outside contributors, so no single party can forge proofs.
  2. A new pool whose start state is bound on chain, for example with token names that carry the script hashes and a minting policy that checks the first datums.
  3. An outside audit of the circuits, the validators and the SDK.

The comparison with Base and the handoff document carry the full lists with file references.