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

# Settlement

> Atomic swaps of vault assets through approved settlers: flow, locks, nonces, and approvals.

A settlement moves one asset (`asset_out`) from the protocol vault to a target and brings another (`asset_in`) back, atomically, without a withdrawal. Market makers use settlements to clear exposure from Tplus fills through onchain venues; the onchain leg behaves like a flash loan against vault funds.

Two parties: the **user**, whose Tplus balance is debited and credited, and a **settler**, an approved executor who runs the onchain transaction. Settlers are approved per-chain; the list is readable onchain via `getApprovedSettlers()`.

## Flow

1. **Request and margin check.** The request (`POST /settlement/init`) specifies asset out/in, amounts, sub-account, mode, and the settler. Validation: `asset_in` must differ from `asset_out`, and the mode (Margin or Spot) must match the sub-account type. The clearing engine simulates an initial-margin check at both oracle and mark price: the account must pass IM and the settlement, including the [rebalancing fee](/funds/rebalancing), must not decrease the IM surplus. Accounts with no borrows always pass.
2. **Lock.** The outgoing amount is moved into a settlement lock keyed by the request's chain and nonce.
3. **Approval.** The protocol signs a time-bound approval. The approval is returned by `POST /settlement/init`; outstanding user approvals can be fetched with `GET /settlement/signatures/{user_id}`.
4. **Execution.** The settler calls `executeAtomicSettlement(...)` on the vault within the validity window (10 seconds from approval). The vault verifies signature, nonce, and expiry.
5. **Confirm or expire.** A confirmed settlement event credits `asset_in` to the user. If the transaction does not land in time, or reverts, which emits no event, the lock expires, funds are restored, and the vault rejects late execution because `validUntil` has passed.

The margin check compares simulated initial-margin surplus before and after the settlement:

```text theme={null}
delta_IM_surplus = IM_surplus_after - IM_surplus_before
accepted if delta_IM_surplus >= 0
```

For a simple USD-out, ETH-in settlement:

```text theme={null}
delta_IM_surplus = ETH_received * ETH_price * im_factor
                 - USDC_sent
                 - rebalancing_fee
```

Example: an account sends out `1,000 USDC`, pays a `10 USD` rebalancing fee, and receives `0.6 ETH`. If `ETH = 2,000 USD` and `im_factor = 90%`, the incoming ETH contributes `0.6 * 2,000 USD * 90% = 1,080 USD` to IM surplus, so `delta_IM_surplus = 1,080 USD - 1,000 USD - 10 USD = +70 USD` and the settlement passes. If the account receives only `0.5 ETH`, the contribution is `900 USD`, `delta_IM_surplus = -110 USD`, and the request is rejected before any lock.

## Utilization caps

Each asset's liquidity pool has a utilization cap (`max_utilization`, a per-asset onchain risk parameter). Utilization is the share of the asset's deposited liquidity that is currently borrowed, and the cap bounds how far the pool can be drawn down. When an asset sits at its cap, the protocol will not let it leave the vault through the live single-settlement path. A settlement that would move a capped asset out is blocked until utilization falls.

Batch settlement and delta squashing are planned, but not available through the public production flow today. The vault ABI includes a squashing entrypoint for batch settlement (`executeSquashingSettlements`). In that planned flow, a settler would execute several settlements as one batch and the vault would move only the net of each token across the batch instead of every gross leg:

```text theme={null}
net(token) = (total amountIn for token across the batch)
           - (total amountOut for token across the batch)
```

* `net < 0`: the batch sends more of the token out than it brings in; the vault pushes only the difference to the settler.
* `net > 0`: the batch brings more in than it sends out; the vault pulls only the difference from the settler.
* `net = 0`: the legs cancel and the token never moves.

A token both bought and sold inside one batch would net out and never cross the vault boundary. That is the planned mechanism for settling capped assets when the batch nets to zero or a net inflow for that asset. It is not available through the public production flow today.

Squashing nets vault movements, not obligations. Each settlement is honored on its own terms. The settler must commit, per settlement, to deliver at least that settlement's `amountIn` (one user's leg cannot subsidize another's); the vault emits a separate `Settled` event per settlement with the real amounts; and solvency checks, locks, and nonces all operate on the real per-settlement amounts, not the net.

Current public availability: use single atomic settlements through `POST /settlement/init` and `executeAtomicSettlement`. Do not build an integration that depends on batch or squashing submission until that path is published.

## Integrator details

* Nonces are independent sequences per user, per chain, and per action type (deposit / withdrawal / settlement); settlement nonces are additionally scoped per sub-account. Do not assume cross-channel ordering. Onchain counters: `depositCounts(user)`, `withdrawalCounts(user)`, `settlementCounts(user, account)`.
* An explicit settlement nonce must be `>=` the onchain counter and must not collide with an in-flight lock. If omitted, the next free nonce is assigned.
* Approvals are returned by `POST /settlement/init`; users fetch outstanding settlement signatures via `GET /settlement/signatures/{user_id}`.
* Vault revert reasons: `Expired`, `SettlerNotApproved`, `NotExecutor`, `InvalidSignature`, `InvalidNonce(expected, given)`, `TransferFailed`, `TransferFromFailed`, `InsufficientAmountFromExecutor`.
* `POST /settlement/init` is rejected before any lock if the account does not pass IM, the settlement would decrease the IM surplus, a protocol open-interest or collateral cap would breach, the oracle is stale or the asset is circuit-broken, or `asset_in` equals `asset_out`.
