# Trusted Vaults

> Canonical: https://docs.velocity.exchange/developers/vault-managers/trusted-vaults

A normal vault is a box the manager can trade inside but cannot take assets out of. Deposits go into the vault's own Velocity account, the manager holds delegate authority to place orders with them, and the only paths out are the depositor withdrawal flow and the manager's own shares. That is what makes the redeem period and the share accounting meaningful: they are the whole of the manager's exit.

A **Trusted** vault removes that box. The manager can move assets out of the vault to an address it controls, and the program tracks the amount as a number on the vault account rather than as a position it can see. Some strategies need this, for example running part of the book on a venue Velocity has no CPI into. It is a different security model, not a feature toggle, and both the manager and the depositors should treat it that way.

> **Warning:**
>
> Trusted vaults must be approved by the Velocity team before they can be used in production. Promotion is an admin instruction; a manager cannot self-promote.

## What the class actually gates

`Vault.vault_class` is a single byte: `0` for Normal, `1` for Trusted. It gates exactly three instructions, `manager_borrow`, `manager_repay`, and `manager_update_borrow`. Calling any of them on a Normal vault fails with `InvalidVaultClass`. Nothing else in the vaults program reads the class.

> **Info:**
>
> Margin trading is **not** part of the Trusted class, despite often being enabled alongside it. `update_margin_trading_enabled` works on a Normal vault too, and is gated only on the vault not being in liquidation (`OngoingLiquidation`). See [Quickstart](/developers/vault-managers/quickstart.md) for the command.

An admin promotes a vault after it is created; there is no way to initialize one as Trusted:

```bash
bun run cli -- admin-update-vault-class \
  --vault-address <VAULT_ADDRESS> \
  --vault-class trusted
```

The instruction rejects a class equal to the current one with `InvalidVaultUpdate`, so re-running it is an error rather than a no-op.

## Borrowing

`manager_borrow` withdraws from the vault's Velocity account and forwards the tokens to a token account owned by the manager. The amount must be greater than zero (`InvalidBorrowAmount`), and the destination account is constrained to `token::authority = manager`, so it has to belong to whoever `vault.manager` is. If the manager is a multisig, pass `--manager-token-account` explicitly: see [Multisig manager](/developers/vault-managers/multisig-ops.md).

```bash
bun run cli -- manager-borrow \
  --vault-address <VAULT_ADDRESS> \
  --borrow-spot-market-index 0 \
  --borrow-amount <AMOUNT>
```

The vaults program sets no ceiling of its own. The bound is the Velocity withdrawal underneath it: the CPI runs with `reduce_only` false, so the vault's account has to end the instruction within its own margin requirement, and if margin trading is enabled the borrow can carry the account into a spot borrow rather than stopping at its deposits. A borrow that would leave the vault under-margined fails inside the Velocity program, not the vaults program.

The borrowed asset does not have to be the one the vault takes deposits in. The borrowed amount is priced into the deposit asset through both oracles at the moment of the borrow, and it is that value, not the token amount, that is recorded.

## How the borrow shows up in share price

Vault equity is the value of the vault's Velocity account **plus** `manager_borrowed_value`. Share price is equity divided by total shares, so a borrow does not move it: value leaves the account and an equal claim appears in its place. Depositors see a flat share price at the moment of the borrow, and a moving one afterwards only through whatever the manager reports.

That is the whole of the accounting, and it is worth being precise about what it does not do. The program never verifies that `manager_borrowed_value` corresponds to anything. It cannot: the assets are outside its view.

## Repaying and marking

**Repay** sends tokens back into the vault and reduces the recorded claim:

```bash
bun run cli -- manager-repay \
  --vault-address <VAULT_ADDRESS> \
  --repay-spot-market-index <INDEX> \
  --repay-amount <AMOUNT> \
  --repay-value <VALUE_IN_DEPOSIT_ASSET>
```

`--repay-amount` is the token transfer and must be greater than zero (`InvalidRepayAmount`). `--repay-value` is how much to subtract from `manager_borrowed_value`, in the deposit asset. The two are independent: the program does not check that the value claimed matches the tokens sent. Omitting `--repay-value` zeroes the entire outstanding claim no matter how small the transfer was.

**Update borrow** moves the recorded claim without moving any tokens, which is how a manager marks an outside position to market:

```bash
bun run cli -- manager-update-borrow \
  --vault-address <VAULT_ADDRESS> \
  --new-borrow-value <VALUE>
```

It sets `manager_borrowed_value` to whatever the manager passes, up or down, with no reference to anything the program can check.

Both emit a `ManagerUpdateBorrowRecord` carrying the previous and new values and the vault equity on each side, so the full history of what the manager declared is onchain and auditable after the fact. Publishing it is a reasonable thing to promise depositors.

## What a depositor is trusting

> **Warning:**
>
> In a Trusted vault the manager can withdraw depositor capital to an address of its own and then set the value of the outstanding claim to any number, including zero, with a single instruction and no proof. The redeem period and share accounting that constrain a Normal vault's manager do not constrain this path. Depositors have no onchain recourse. A Trusted vault is appropriate only where a depositor would accept an unsecured loan to the manager.

The mitigations are all offchain: who the manager is, whether the manager role sits behind a multisig, what they publish, and whether the declared borrow value can be reconciled against a venue anyone can check. See [Multisig manager](/developers/vault-managers/multisig-ops.md) for the first of those, and [Vault Managers](/developers/vault-managers.md) for the guardrails that do apply to every vault regardless of class.
