otcvault settles otc deals nobody has to trust

Fee
0.5%
paid by the seller · cap 1.00%
Buyer pays
0%
deposits exactly the agreed amount
Tokens whitelisted · Arbitrum
142
technical check only · not a value judgement
Contracts verified
20 / 20
4 chains · Sourcify · non-upgradeable

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.

A steel vault door standing ajar in daylight

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.

  1. 01
    OPEN

    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()
  2. 02
    FUNDED

    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()
  3. 03
    CONFIRMED

    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()
  4. 04
    SETTLED

    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.

  1. 01

    Both legs are escrowed.

    Nobody sends first. The contract holds both deposits and releases both — or neither.

  2. 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.

  3. 03

    Non-upgradeable, verified source.

    Five plain contracts, no proxies, source verified on Arbiscan. What you read is what runs — forever.

  4. 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.

  5. 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.

  6. 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.

Two hands and one paper contract across a table

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

Bob deposits
100,000 USDC
Alice receives
99,500 USDC
Fee vault
500 USDC

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

An open bound ledger with a pencil

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.

Done
  • 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.
Not yet
  • 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.
Full security page

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

  • DeOTCEscrow0x7f271629F70BC2c7ACE8ba20bd49f1Ee3602DbcB
  • TokenWhitelist0x443CC5b294054D057Fc30cAb45Fcaad0982664da
  • StableRegistry0x7c1b6dd8B4f31b09A5fbd13694395dE576Ec38B3
  • SablierRail0xF08F48FcBB1A1B2B67a0878949bf05Ada0b715a9
  • FeeVault0xFF27e5EdD20ef6254D388aA21F66222daE9CFacD

Base

  • DeOTCEscrow0x8c373dcFB227E8C00a30718a7daf0270a960F8b7
  • TokenWhitelist0x5C6bBFc72F352376339ad8B12805265f3FBaeDd4
  • StableRegistry0x245c8E201b1e65Eba35F862aeC0Ae5219715A3E9
  • SablierRail0x320911E8Cb49463e32fF123C1113eCa2760265Ee
  • FeeVault0x35CCc0a078Af070c5a4203a1aF43B7A99995D475

Ethereum

  • DeOTCEscrow0xF1B4c8A0974C969F2801f52EB0C9d1FDfc2FC4dd
  • TokenWhitelist0x77926D8BEDa9987cdD3F979BFF0B56Cc9e88419D
  • StableRegistry0x44436AF008379dce1804a46823A3f051fE54C3C2
  • SablierRail0xc94f770cf88559e18521Abac169E7Ee4aEfCB9eE
  • FeeVault0x2E239565D8516E8c743F5509186272E838b81d3B

BNB Chain

  • DeOTCEscrow0x320911E8Cb49463e32fF123C1113eCa2760265Ee
  • TokenWhitelist0x35CCc0a078Af070c5a4203a1aF43B7A99995D475
  • StableRegistry0xAe93040Cb272d9C7Aa6778297B1C05694C4D2D8f
  • SablierRail0x5C6bBFc72F352376339ad8B12805265f3FBaeDd4
  • FeeVault0x245c8E201b1e65Eba35F862aeC0Ae5219715A3E9

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