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.

A brass key resting on grey linen

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.

Contracts · Arbitrum One · Base · Ethereum · BNB Chain

Contract version 3.0.0 — identical source and bytecode on every chain (Arbitrum One live since 11 Sep 2026; Base, Ethereum and BNB Chain deployed 11 Sep 2026). Owner and guardian on every chain: deployer EOA 0x74a47aC2 (interim) — Safe + 48h timelock migration planned. Previous Arbitrum escrow 0xC2acBe10 (v2, deals 1–14) stays readable at /deal/v2/<id>. Deal links encode the chain: /deal/<chainId>/<id>.

Arbitrum One · chain id 42161 · stables USDC / USDT · Sablier Lockup v4 rail

  • DeOTCEscrow
    0x7f271629F70BC2c7ACE8ba20bd49f1Ee3602DbcB
    v3.0.0. Deals, fund, confirm (24h TTL, revocable), settle, cancel, pull-based claims, fee accrual, guardian pause. ReentrancyGuard, SafeERC20, Ownable2Step.
  • TokenWhitelist
    0x443CC5b294054D057Fc30cAb45Fcaad0982664da
    Allowlist of tradeable non-stable tokens; paid listing requests.
  • StableRegistry
    0x7c1b6dd8B4f31b09A5fbd13694395dE576Ec38B3
    USDC (6 dec) / USDT (6 dec) registry. 48h timelock on additions; instant removal.
  • SablierRail
    0xF08F48FcBB1A1B2B67a0878949bf05Ada0b715a9
    v3.0.0. Adapter → Sablier Lockup v4 createWithDurationsLL, cancelable = false; Sablier-parity schedule validation; maxVesting 5y (owner-tunable ≤10y).
  • FeeVault
    0xFF27e5EdD20ef6254D388aA21F66222daE9CFacD
    Holds protocol + listing fees. Owner sweep only.

Base · chain id 8453 · stables USDC / USDT · Sablier Lockup v4 rail

  • DeOTCEscrow
    0x8c373dcFB227E8C00a30718a7daf0270a960F8b7
    v3.0.0. Deals, fund, confirm (24h TTL, revocable), settle, cancel, pull-based claims, fee accrual, guardian pause. ReentrancyGuard, SafeERC20, Ownable2Step.
  • TokenWhitelist
    0x5C6bBFc72F352376339ad8B12805265f3FBaeDd4
    Allowlist of tradeable non-stable tokens; paid listing requests.
  • StableRegistry
    0x245c8E201b1e65Eba35F862aeC0Ae5219715A3E9
    USDC (6 dec) / USDT (6 dec) registry. 48h timelock on additions; instant removal.
  • SablierRail
    0x320911E8Cb49463e32fF123C1113eCa2760265Ee
    v3.0.0. Adapter → Sablier Lockup v4 createWithDurationsLL, cancelable = false; Sablier-parity schedule validation; maxVesting 5y (owner-tunable ≤10y).
  • FeeVault
    0x35CCc0a078Af070c5a4203a1aF43B7A99995D475
    Holds protocol + listing fees. Owner sweep only.

Ethereum · chain id 1 · stables USDC / USDT · Sablier Lockup v4 rail

  • DeOTCEscrow
    0xF1B4c8A0974C969F2801f52EB0C9d1FDfc2FC4dd
    v3.0.0. Deals, fund, confirm (24h TTL, revocable), settle, cancel, pull-based claims, fee accrual, guardian pause. ReentrancyGuard, SafeERC20, Ownable2Step.
  • TokenWhitelist
    0x77926D8BEDa9987cdD3F979BFF0B56Cc9e88419D
    Allowlist of tradeable non-stable tokens; paid listing requests.
  • StableRegistry
    0x44436AF008379dce1804a46823A3f051fE54C3C2
    USDC (6 dec) / USDT (6 dec) registry. 48h timelock on additions; instant removal.
  • SablierRail
    0xc94f770cf88559e18521Abac169E7Ee4aEfCB9eE
    v3.0.0. Adapter → Sablier Lockup v4 createWithDurationsLL, cancelable = false; Sablier-parity schedule validation; maxVesting 5y (owner-tunable ≤10y).
  • FeeVault
    0x2E239565D8516E8c743F5509186272E838b81d3B
    Holds protocol + listing fees. Owner sweep only.

BNB Chain · chain id 56 · stables USDT / USDC · Sablier Lockup v4 rail

  • DeOTCEscrow
    0x320911E8Cb49463e32fF123C1113eCa2760265Ee
    v3.0.0. Deals, fund, confirm (24h TTL, revocable), settle, cancel, pull-based claims, fee accrual, guardian pause. ReentrancyGuard, SafeERC20, Ownable2Step.
  • TokenWhitelist
    0x35CCc0a078Af070c5a4203a1aF43B7A99995D475
    Allowlist of tradeable non-stable tokens; paid listing requests.
  • StableRegistry
    0xAe93040Cb272d9C7Aa6778297B1C05694C4D2D8f
    USDT (18 dec) / USDC (18 dec) registry. 48h timelock on additions; instant removal.
  • SablierRail
    0x5C6bBFc72F352376339ad8B12805265f3FBaeDd4
    v3.0.0. Adapter → Sablier Lockup v4 createWithDurationsLL, cancelable = false; Sablier-parity schedule validation; maxVesting 5y (owner-tunable ≤10y).
  • FeeVault
    0x245c8E201b1e65Eba35F862aeC0Ae5219715A3E9
    Holds protocol + listing fees. Owner sweep only.

What the owner can and cannot do

Can

  • Set the fee for future deals — never above 1.00%, and never above the cap the maker pinned at creation.
  • Set the vesting rail for future deals (existing deals keep theirs; makers pin the rail they reviewed).
  • Pause / unpause creating and funding new deals (guardian); block a token for new deals.
  • Approve / revoke whitelisted tokens.
  • Propose (48h) / execute / remove registry stablecoins.
  • Sweep earned fees from the FeeVault (fees reach it via permissionless pushFees).

Cannot

  • Move or freeze any escrowed deposit — confirm, cancel, refund and claim are never pausable.
  • Change the terms, fee, rail or schedule of an existing deal.
  • Upgrade any contract — there are no proxies.
  • Cancel or redirect a Sablier stream once created.
  • Recover tokens sent directly to the escrow (by design).

Dependencies

OpenZeppelin Contracts 5 (Ownable2Step, ReentrancyGuard, SafeERC20) · Sablier Lockup v4 (non-upgradeable, audited by multiple firms since 2019). Sablier Lockup v4: Arbitrum 0xD1039C33 · Base 0xc19a7C0A · Ethereum 0x93b3BDCB · BNB Chain 0x6cd0eD22.

Found something? Email security@playmarket.xyz. A formal bug bounty follows the audit.