otcvault settles otc deals nobody has to trust
OTC today runs on trust. Trust is the attack surface.
Most token deals outside exchanges still happen in a chat: someone sends first, someone hopes. The failure modes are well known.
Fake stablecoins. A token called "USDT" with the right logo and the wrong address. By the time you check the explorer, the real tokens are gone. Who sends first? Every OTC deal has a moment where one side is fully exposed. Escrow agents solve it by adding a third party you also have to trust.
Vesting on a handshake. Discounted tokens usually come with a lock-up — enforced by a promise. Buyers dump early; sellers stop delivering. Neither side has recourse. Risk in the middleman. Centralised OTC desks and escrow services hold your funds, can freeze them, and can disappear. Several have.
OTCVault removes the trusted party instead of adding one.

Four states. One contract. No one in the middle.
Every deal is a single entry in the escrow contract and moves through four states. The state you see on a deal page is read directly from the chain.
- 01OPEN
Maker creates and deposits
The maker names the counterparty, both legs, the delivery schedule and an expiry. Their side is pulled into escrow in the same transaction.
createDeal() - 02FUNDED
Taker deposits
The named taker sees exactly what is escrowed — real address, live symbol and decimals, whitelist and registry status — and deposits their side. A 24-hour cool-off starts.
fund() - 03CONFIRMED
Both verify and confirm
Each party checks the other's deposit and types the last 8 characters of the counterparty's token address, shown in full above the input. The first confirm is recorded; the second one settles.
confirm() - 04SETTLED
Atomic delivery
Stablecoins go to the seller minus the 0.5% fee; the buyer pays nothing extra. The token goes to the buyer — immediately, or into a Sablier vesting stream that cannot be cancelled by anyone.
confirm() → _settle()
Exit. CANCELLED — maker cancels while open; mutual cancel while funded; unilateral withdrawal after the 24h cool-off; or anyone triggers a refund after expiry. Every deposit returns in full. No fee on cancelled deals.
Trust the contract you can read, not the people you can't.
- 01
Both legs are escrowed.
Nobody sends first. The contract holds both deposits and releases both — or neither.
- 02
No admin key can touch your funds.
No rescue, sweep, pause or upgrade function. The owner can only set the fee (capped at 1%) and the vesting rail for future deals.
- 03
Non-upgradeable, verified source.
Five plain contracts, no proxies, source verified on Arbiscan. What you read is what runs — forever.
- 04
One leg is always a real stablecoin.
Every deal must include USDC or USDT from the on-chain registry. A fake "USDT" cannot be the stable leg — by construction.
- 05
The token leg is whitelisted — technically.
Whitelisted = contract verified, not fee-on-transfer, no impostor symbol. OTCVault does not assess value — that is between buyer and seller. Check the address and the price yourself.
- 06
Vesting is a Sablier stream, not a promise.
Delivered as a Sablier Lockup v4 stream created with cancelable = false. The seller cannot claw it back; the buyer cannot skip the schedule.
Fee, rail and schedule are snapshotted per deal: what you confirm is what settles.

0.5%, paid by the seller. Nothing else.
Charged only on the stablecoin leg, only when a deal settles, and only to the seller — deducted from the stablecoins they receive. The buyer deposits exactly the agreed amount and pays nothing extra. Cancelled and expired deals cost nothing beyond gas.
- Buyer deposits
- exactly the stable amount — no fee
- Seller receives
- stable amount − 0.5%
- Protocol receives
- 0.5% of the stable amount, from the seller
- Charged on the token leg
- Never
- Charged on cancel / refund
- Never
- Maximum fee, ever
- 1.00% — MAX_FEE_BPS = 100, immutable
Worked example — $100,000 deal
Alice sells 250,000 XYZ to Bob for 100,000 USDC, vesting linearly over 12 months.
Bob deposits exactly 100,000 USDC — no fee on his side. Alice deposits 250,000 XYZ.
On settlement: Alice receives 99,500 USDC (100,000 − 0.5% fee). Bob receives a Sablier stream of 250,000 XYZ over 12 months. The fee vault receives 500 USDC.
If either side walks away before both confirm: Bob gets back exactly 100,000 USDC, Alice exactly 250,000 XYZ.
Listing fee. Adding a new token to the whitelist costs 1,000 USDC, paid to the fee vault when you request a review. It pays for the review; it does not guarantee approval.
Where fees go. Fees accumulate in the FeeVault contract. Planned use: buy-back-and-burn of a future protocol token. Until then, the balance is publicly visible on-chain. Arbitrum vault · Base vault · Ethereum vault · BNB Chain vault

Built for both sides of the table.
For sellers — you hold the token
- Get paid in real USDC or USDT — the registry, not a logo, decides what counts.
- Set the vesting terms yourself: liquid, cliff, or linear with cliff and daily/weekly unlocks.
- Your tokens never leave escrow until the buyer's stablecoins are in escrow too.
- Walk away any time before both confirmations — full refund after the 24h cool-off.
- You receive the stable leg the instant the deal settles, minus the 0.5% protocol fee — the only fee in the deal.
For buyers — you hold the stablecoins
- See the exact token contract before you commit: full address, live metadata, whitelist status, and bytecode notes such as proxy or pausable. The whitelist checks the contract, not the price — that part is yours.
- Vested tokens arrive as a Sablier NFT — the seller cannot cancel or alter the stream.
- Claim as tokens unlock at app.sablier.com, with no dependency on OTCVault.
- If the seller never confirms, withdraw your stablecoins after 24 hours.
- Pay no protocol fee. You deposit exactly the agreed amount; the 0.5% fee comes out of the seller's side.
Where we are, honestly.
Pre-audit · contracts v3.0.0 · Use with amounts you can afford to lose
OTCVault is live on Arbitrum One, Base, Ethereum and BNB Chain with real funds and has not yet been audited by an external firm. We would rather say that plainly than imply otherwise.
- 197 Foundry tests. 175 local + 22 Arbitrum fork tests (real USDC blacklister, real Sablier Lockup v4), 10 invariants. Core invariant: escrow balance == escrowed deposits + claimable balances + accrued fees; settled deals deliver exactly stable − fee and exactly the asset amount. 98.5% line coverage.
- Internal audit remediated (v3). Pull-based refunds (a blacklisted counterparty can no longer hold your deposit hostage), fees accrue in the escrow instead of being pushed, confirms are binding for 24h and revocable, makers pin the rail and the fee they reviewed, guardian pause blocks only new deals and funding.
- Slither static analysis. 0 High. 1 Medium (strict-equality sentinel in the registry) triaged as false positive; 1 Low reentrancy note accepted — state is SETTLED before any external call and confirm is nonReentrant.
- Verified source. All five contracts verified on Arbiscan. No proxies.
- Minimal admin surface. Owner can set the fee (≤1%), the rail for future deals, manage whitelist and registry (48h timelock on additions), sweep earned fees. Cannot move escrowed deposits.
- Written listing policy. Whitelisted means: source verified, not fee-on-transfer, no symbol that collides with a registry stable or another listed token, no stable-sounding name unless it is USDC/USDT. Nothing about price, liquidity depth or the team. Tokens are revoked when they stop meeting the policy.
- Deposit measurement. Every deposit is measured balanceAfter − balanceBefore and reverts on shortfall, so fee-on-transfer tokens fail loudly.
- External audit. Scheduled before the per-deal cap is lifted. Until then, treat the protocol as beta.
- Multisig + timelock ownership. Owner: deployer EOA (interim) — Safe + 48h timelock migration planned. The v3 deploy scripts already wire a TimelockController; the live owner will be migrated once the Safe is set up.
- Bug bounty. To follow the audit.
Questions people actually ask.
Once a deal is FUNDED, a 24-hour cool-off starts. If both parties have not confirmed by then, either party can call Cancel and both deposits are refunded in full. Before the cool-off ends, a cancel request is recorded; if the other party also requests cancel, refunds happen immediately (mutual cancel).
What's next.
- Now
- Arbitrum One · Base · Ethereum · BNB Chain · named-counterparty deals · Sablier Lockup v4 rail · USDC/USDT · per-chain token whitelist
- Next
- External audit → per-deal cap lifted · ownership to multisig · Base deployment
- Then
- Ethereum mainnet · BNB Chain · open offers · Hedgey TokenLockupPlans as an alternative rail
- Later
- Protocol token + buy-back-and-burn from FeeVault · governance over fee, registry and whitelist · Hebrew interface
Five contracts per chain. Verify them yourself.
Verify the contracts yourself
Arbitrum One
Base
Ethereum
BNB Chain
Same bytecode on every chain, verified on Sourcify. Full detail on /security. Arbitrum One is the default network.
ready when both of you are.
Create a deal