> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tplus.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Deposit Vault

> The custody contract: deposit, settlement, and withdrawal interfaces, structs, events, and reverts.

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

```solidity theme={null}
function deposit(bytes32 user, address tokenAddress, uint256 amount) external;
```

First-time depositors can use the overload that also registers the account's initial multisig configuration:

```solidity theme={null}
function deposit(
    bytes32 user,
    address tokenAddress,
    uint256 amount,
    uint32 masterWeight,
    uint32 lowThreshold,
    uint32 mediumThreshold,
    uint32 highThreshold,
    SignerConfig[] memory signers,
    bytes memory masterConfigSignature
) external;

struct SignerConfig {
    bytes32 key;
    uint8   keyType;
    uint8   keyPrefix;
    uint32  weight;
    uint64  expiresAtNs;
    uint64  maxSigningWindowNs;
}
```

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](/security/trust-model#signing-and-replay-protection).

Deposits emit `Deposited` (or `DepositedWithConfig`) and increment `depositCounts(user)`. The clearing engine credits the balance after the chain's [confirmation policy](/funds/deposits#chains-and-confirmation-times) 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](/funds/settlement).

```solidity theme={null}
struct Settlement {
    address tokenOut;   // sent OUT of the vault to the settler's target
    uint256 amountOut;
    address tokenIn;    // expected back IN
    uint256 amountIn;   // enforced as a minimum
    SettlementMode mode; // 0 = Spot, 1 = Margin
    bytes32 user;
    uint64  account;
    uint64  nonce;      // per (user, account)
    uint256 validUntil; // unix seconds; rejected once block.timestamp > validUntil
}
```

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:

```solidity theme={null}
function executeAtomicSettlement(
    Settlement calldata order,
    bytes32 settler,            // settler id; must be approved on the vault
    bytes   calldata data,      // opaque; forwarded to the executor callback
    bytes   calldata signature  // clearing-engine approval signature
) external;
```

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:

```solidity theme={null}
function onAtomicSettlement(address token, uint256 amount, bytes calldata data)
    external returns (uint256); // tokenIn the executor will provide
```

The vault enforces the returned amount against `amountIn`, then swaps:

```solidity theme={null}
uint256 expectedAmountIn = IAtomicSettlementCallback(msg.sender)
    .onAtomicSettlement(order.tokenOut, order.amountOut, data);
if (expectedAmountIn < order.amountIn) {
    revert InsufficientAmountFromExecutor(expectedAmountIn, order.amountIn);
}
SafeTransferLib.safeTransferFrom(order.tokenIn, msg.sender, address(this), expectedAmountIn);
SafeTransferLib.safeTransfer(order.tokenOut, msg.sender, order.amountOut);
```

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.

```solidity theme={null}
function getApprovedSettlers() external view returns (bytes32[] memory);
function addSettlerExecutor(bytes32 settler, address executor) external;
function removeSettler(bytes32 settler) external;
```

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](/funds/withdrawals).

```solidity theme={null}
struct Withdrawal {
    address tokenAddress;
    uint256 amount;
    uint64  nonce;
}

function withdraw(
    Withdrawal memory withdrawal,
    bytes32 user,
    address target,
    uint256 validUntil,
    bytes32 epochHash,
    bytes[] memory signatures
) external;
```

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

| Event                 | Signature                                                                                                                                                                                                                                                     |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Deposited`           | `Deposited(bytes32 indexed user, uint256 indexed nonce, address indexed tokenAddress, uint256 amount)`                                                                                                                                                        |
| `DepositedWithConfig` | `DepositedWithConfig(bytes32 indexed user, uint256 indexed nonce, address indexed tokenAddress, uint256 amount, uint32 masterWeight, uint32 lowThreshold, uint32 mediumThreshold, uint32 highThreshold, SignerConfig[] signers, bytes masterConfigSignature)` |
| `Settled`             | `Settled(bytes32 indexed user, uint64 indexed account, uint256 indexed nonce, address tokenOut, uint256 amountOut, address tokenIn, uint256 amountIn, SettlementMode mode, bytes32 settler)`                                                                  |
| `Withdrew`            | `Withdrew(bytes32 indexed user, uint256 indexed nonce, address tokenAddress, uint256 amount)`                                                                                                                                                                 |

## Nonce views

| Function                                         | Returns  |
| ------------------------------------------------ | -------- |
| `depositCounts(bytes32 user)`                    | `uint64` |
| `settlementCounts(bytes32 user, uint64 account)` | `uint64` |
| `withdrawalCounts(bytes32 user)`                 | `uint64` |
