Skip to main content
The Deposit Vault custodies every deposited token and is the only contract that moves user funds onchain. Deposits credit a Tplus balance, settlements swap one vault-held asset for another through an approved settler, and withdrawals release funds back to the user. All three are authorized offchain by the clearing engine and verified onchain by the vault. One deployment per chain; read addresses from GET /registry/vaults. Amounts are in each token’s native onchain decimals. The vault normalizes to the clearing engine’s 18-decimal internal units. user is the 32-byte Tplus user id (the same key as the User-Id header); account is the sub-account index.

Deposits

First-time depositors can use the overload that also registers the account’s initial multisig configuration:
Each SignerConfig registers a co-signer: key with keyType/keyPrefix identifies the key and its scheme (Ed25519, secp256k1, P-256, or WebAuthn), weight counts toward the per-action signing thresholds, and expiresAtNs/maxSigningWindowNs bound when it may sign. See signing. Deposits emit Deposited (or DepositedWithConfig) and increment depositCounts(user). The clearing engine credits the balance after the chain’s confirmation policy is met. Depositors are currently gated by an onchain allow-list. Check canDeposit(address) -> bool before depositing. The allow-list will be removed before production.

Settlement

Settlement deploys balances held in Tplus into onchain venues without a withdrawal. One asset leaves the vault (tokenOut / amountOut) and another returns (tokenIn / amountIn) in a single transaction executed by an approved settler. Clients never call the vault directly: initiate with POST /settlement/init, then the settler executes onchain. Flow, locks, and approval delivery: Settlement.
The clearing engine signs a custom flat digest, not standard EIP-712. There is no \x19\x01 envelope. For executeAtomicSettlement, the digest is keccak256(bytes.concat(...)) over SETTLEMENT_TYPEHASH() (keccak256("SettlementApprovalV2")), the vault domain separator, tokenOut, amountOut, tokenIn, amountIn, mode, user, account, nonce, validUntil, and settler. The settler executes it:
The caller must be the executor registered for settler. The vault verifies expiry, settler approval, executor authorization, nonce, and signature, then calls the executor at msg.sender. The data argument is not decoded by the vault; the executor defines its own ABI for it (router calldata, swap path, minimum-out policy). The executor must implement the callback:
The vault enforces the returned amount against amountIn, then swaps:
Revert reasons: Expired, SettlerNotApproved, NotExecutor, InvalidNonce(expected, given), InvalidSignature, TransferFailed, TransferFromFailed, InsufficientAmountFromExecutor.

Approved settlers

Only settlers registered on the vault may execute settlements; each is bound to an executor address.
Batch settlement and delta squashing are planned, but not available through the public settlement flow today. The vault ABI includes batch/squashing entrypoints (executeSquashingSettlements, pullBatchSettlements, pushBatchSettlements); use the single-settlement executeAtomicSettlement flow until batch submission is published.

Withdrawals

A withdrawal returns vault funds to the user against a quorum of clearing-engine approval signatures bound to an approval epoch. Clients initiate with POST /withdrawal/init, track with GET /withdrawal/queue/{user_id}, and cancel with POST /withdrawal/cancel. Queue, fees, and expiry: Withdrawals.
The clearing engine signs a custom flat digest using keccak256("WithdrawalApprovalV1") as its type tag; it is not standard EIP-712. signatures must meet the vault’s withdrawalQuorum, epochHash pins the approval epoch, and withdrawalCounts(user) is the per-user nonce. Revert reasons: Expired, InvalidNonce(expected, given), InvalidSignature, MissedQuorum(provided, required), TransferFailed.

Events

Nonce views