# Solana Vaults

Upshift Solana Vaults bring the same institutional-grade vault infrastructure to the Solana ecosystem. Built as a native Anchor program, Solana vaults offer fast, non-custodial yield generation transparently on-chain, with actively managed strategies.

|                   |                                                 |
| ----------------- | ----------------------------------------------- |
| **Program**       | `up12bytoZBmwofqsySf2uqKQ7zpfeKiAWwfvqzJjtRt`   |
| **Framework**     | Anchor (v0.1.0)                                 |
| **Deposit Asset** | Any SPL Token                                   |
| **Share Token**   | PDA-minted receipt token with on-chain metadata |
| **Redemptions**   | Instant, no lock-ups                            |

***

### Architecture & How It Works

Each Upshift Solana vault is deployed as an instance of the `august_vault` program. A vault is initialized with three roles  (**admin**, **operator**, and **fee recipient),** and is bound to a single SPL deposit token (e.g. USDC). On initialization, the program creates:

* A **VaultState** PDA that stores all vault configuration and accounting
* A **share mint** PDA used to mint receipt tokens to depositors
* A **vault token ATA** PDA that holds the vault's deposit token balance

#### Deposit Flow

1. User calls `deposit(amount)` with their SPL tokens
2. The vault transfers tokens from the user's account to the vault token ATA
3. Share tokens are minted to the user proportional to the current NAV:

```
   shares_minted = deposit_amount * total_share_supply / total_AUM
```

4. `local_aum` increases by the deposit amount
5. A `DepositEvt` is emitted with `caller`, `receiver`, `amount`, and `shares`

#### Redemption Flow

1. User calls `redeem(shares)` with the number of share tokens to burn
2. The vault calculates the underlying token amount based on current NAV:

```
   tokens_returned = shares * total_AUM / total_share_supply
```

3. If a withdrawal fee is configured, the fee portion (in bps) is routed to the `fee_recipient`
4. Share tokens are burned and underlying tokens are transferred to the user
5. `local_aum` decreases by the redeemed amount
6. A `WithdrawEvt` is emitted with `caller`, `receiver`, `owner`, `assets`, and `shares`

#### Curator Model

An appointed curator (the **operator**) manages the vault's yield strategy through three operations:

| Operation              | What It Does                                                                                                   |
| ---------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Deploy Capital**     | Withdraws tokens from the vault to a shared MPC workspace. Decreases `local_aum`, increases `deployed_aum`.    |
| **Return Capital**     | Deposits tokens back into the vault from external strategies. Increases `local_aum`, decreases `deployed_aum`. |
| **Report Performance** | Updates `deployed_aum` to reflect the current value of externally deployed capital (gains or losses).          |

The curator operates within strict bounds set by the Upshift team. A policy engine governs which protocols, contracts, and functions the curator is authorized to interact with as part of the vault's strategy. As an additional safety measure the Admin sets AUM change limits, capping how much `deployed_aum` can move per update, preventing sudden NAV manipulation.

#### Share Price Derivation

The share token price is fully derivable on-chain:

```
share_price = (local_aum + deployed_aum) / total_share_supply
```

* **`local_aum`** - tokens held directly in the vault's token ATA. Fully verifiable on-chain.
* **`deployed_aum`** - value of tokens deployed in external strategies, reported by the operator via `operator_update_aum`.
* **`total_share_supply`** - readable from the share mint account.

Any Solana program can compute the share price by reading the VaultState account and the share mint. No external oracle is required.

***

### Risk & Security Model

#### AUM Change Limits

The vault enforces asymmetric increase and decrease limits on `deployed_aum` updates. These are set by the admin in basis points via `set_aum_limits(increase_limit, decrease_limit)`.

* **Increase limit** - caps how much `deployed_aum` can grow in a single `operator_update_aum` call
* **Decrease limit -** caps how much `deployed_aum` can fall in a single update (typically set tighter than the increase limit)

This prevents sudden, large NAV swings, whether from operator error or attempted manipulation. The IDL enforces a maximum value via the `AumLimitTooHigh` error.

#### Pause Mechanism

The admin can instantly pause all vault operations via `pause()`. When paused:

* `deposit` and `redeem` calls revert with `VaultPaused`
* Operator functions continue to work (the curator can still manage deployed capital)
* The admin can unpause at any time via `unpause()`

This provides a circuit breaker in case of an exploit, market event, or strategy issue.

#### Admin Transfer Safety

Admin role transfers use a two-step nomination process:

1. Current admin calls `nominate_admin(new_admin)` . This creates a `NominatedAdmin` PDA with the nominee and an expiry timestamp
2. Nominated admin calls `accept_admin_nomination()` . Must be called before expiry

This prevents accidental or malicious ownership changes. If the nomination expires, it must be re-issued. The `NominatedAdmin` PDA is closed upon acceptance.

#### Audit History

Built on the same architecture as Upshift's EVM vaults that secure $400M+ in TVL. Audited 3x in the past 12 months. A separate audit has been conducted for the Solana contracts and can be found [here](https://docs.upshift.finance/vault-architecture/smart-contract-audits)

***
