# What is Lagoon?

An on-chain fund infrastructure protocol that enables asset managers to launch, operate, and distribute tokenized investment strategies.

{% hint style="info" %}
**Lagoon** offers institutional grade fund infrastructure protocol that enables asset managers to launch, operate, and distribute any investment strategies. Provides institutional grade controls, transparent reporting, and a standardised smart contract framework that integrates across protocols and chains.
{% endhint %}

Lagoon is an ERC-7540 based on-chain vault protocol designed for professional, chains, protocols, funds and any other enteties that need to pool digital assets at scale. It provides the full stack needed to launch tokenized funds: smart contract vault deployment, NAV computation, access control via Safe/MPC, fee management, and investor-facing reporting. Lagoon is non-custodial, audited, and chain-agnostic.

Lagoon serves as the distribution layer that connects vault operators with investors through shared on-chain infrastructure.

***

### For Institutional Asset Managers & Vault Operators

**Lagoon** is a a non-custodial, open-access vault infrastructure for managers to deploy and distribute strategies across DeFi, RWAs, and off-chain mandates.

Lagoon offers additional institutional grade tooling to support any asset and strategy.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Independent NAV Computation</strong></mark></td><td>Share prices calculated by a third-party service independent from the manager. Ensures objective, tamper-proof valuation mirroring regulated fund administration standards.</td></tr><tr><td><mark style="color:$primary;"><strong>Role-Based Access Control</strong></mark></td><td>Assign scoped permissions per team member at the smart contract level. Institutional-grade segregation of duties enforced natively on-chain.</td></tr><tr><td><mark style="color:$primary;"><strong>Audit-Ready Reporting</strong></mark></td><td>Every deposit, withdrawal, NAV update, and fee event is immutably recorded on-chain and exportable. Designed to match regulatory requirements of each operator's jurisdiction.<br>On-demand feature where Lagoon either audits or calculates your vault's share price.</td></tr><tr><td><mark style="color:$primary;"><strong>Compatible With Any Custody Solution</strong></mark></td><td>Operations secured via Multi-Party Computation or Safe multisig. No single person holds a complete private key. Every execution requires coordinated multi-party approval.</td></tr></tbody></table>

***

### For Investors & Depositors

Lagoon enables investors to discover, evaluate, and allocate to curated investment strategies across DeFi, RWAs, and off-chain mandates.

The platform provides transparent reporting including:

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Real-time Position Monitoring</strong></mark></td><td>Investors can track the current value of their vault shares, underlying asset allocation and NAV evolution at any time, providing full visibility into how their capital is being deployed on-chain.</td></tr><tr><td><mark style="color:$primary;"><strong>Historical Performance Data</strong></mark></td><td>Each vault exposes a complete, immutable record of its past performance, NAV history and strategy activity, giving investors the auditable track record needed to evaluate a manager before and after committing capital.</td></tr><tr><td><mark style="color:$primary;"><strong>Clear Fee Disclosure</strong></mark></td><td>All fee structures (management, performance, entry and exit fees) are encoded directly in the vault's smart contract and visible to any investor prior to deposit, eliminating information asymmetry between managers and their depositors.</td></tr></tbody></table>

***

### Deploy a vault! <a href="#why-lagoon" id="why-lagoon"></a>

{% hint style="success" %}
As a manager, builder, protocol, chain, or asset issuer, you can deploy a vault today.

👉 [**Deploy here**](https://app.lagoon.finance/deploy)
{% endhint %}

***

📩 **Need help?** Contact our team by filling in [**this form**](https://tally.so/r/nGBGyz)**.**


# Lagoon Vault Architecture

Provides an overview of our system’s design.

A typical Lagoon vault architecture is made of an ERC7540 vault and a curating solution. Lagoon is un-opinionated on the curating solution to use.

Here you can see two cases, one made of a Safe with a Zodiac Role Modifier and one with a MPC solution.

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fv5xPJgVfb8BzRcXOW5QB%2Farchi-safe.png?alt=media&amp;token=5d27763f-cf2a-4e90-870c-d846e19cfed5" alt=""><figcaption><p>Lagoon infrastructure with Safe and a Zodiac Role Modifier</p></figcaption></figure>

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FnnIIaZtMHoHLNIdAgrJJ%2Farchi-mpc.png?alt=media&amp;token=983a4a15-e0f8-4c00-a70c-61ed3233a354" alt=""><figcaption><p>Lagoon infrastructure with MPC</p></figcaption></figure>


# FAQ

Find below the answer(s) you are looking for.

## General questions

<details>

<summary><strong>What is a Lagoon vault?</strong></summary>

A Lagoon vault is made of:

* 1 vault's (ERC-7540) smart contract;
* 1 silo contract which contains pending deposits and withdrawals.
* A curation solution, such as a Safe.

</details>

<details>

<summary>What do users get when they deposit in a vault?</summary>

Users receive ERC20 tokens, representing a share of the vault, in exchange for their assets.

</details>

<details>

<summary>Is the share of the vault compatible with the rest of DeFi ?</summary>

Yes all shares are ERC20 token.

</details>

<details>

<summary><strong>How many chains are supported?</strong></summary>

Chains list is available at [Networks & Addresses](/resources/networks-and-addresses)

</details>

<details>

<summary><strong>Can the curating solution/address be updated? (safe variable in the smart contract)</strong></summary>

This feature is not currently available but will be included in a future update.

</details>

<details>

<summary><strong>What types of strategy can be set up?</strong></summary>

It varies depending on the chosen curation solution and its adaptability.

</details>

<details>

<summary>Does the protocol charge fees ?</summary>

Yes. Lagoon takes a protocol fee of **10%** on the fees collected by the curator (management and performance fees) — not on user deposits or on the vault's assets. The on-chain limit is 30%.

*Example: a curator generates 1000 shares of fees through management and performance fees. With a 10% protocol fee rate, Lagoon receives 100 shares and the fee receiver 900 shares.*

See [Fees](/vault/fees) for the full fee breakdown.

</details>

<details>

<summary>Can a vault do cross-chain strategies ?</summary>

The strategies a curator can execute are exclusively limited by the curation solution he used.

For example, a vault curator using a Safe can bridge funds across EVM chains, non-EVM chains, and even CEXs.

</details>

## Security

<details>

<summary><strong>How decentralized is the protocol?</strong></summary>

Lagoon is the only entity capable of deploying vault upgrades; however, enforcement of these upgrades is exclusive to each vault's "Upgrade Authority."

</details>

<details>

<summary><strong>Is the protocol open-source?</strong></summary>

Yes all contracts are verified on Etherscan.

</details>

<details>

<summary><strong>Has Lagoon been audited?</strong></summary>

At Lagoon, we prioritize security and focus on delivering high-quality code with thorough tests and audits. The several iterations of the vaults have been audited by Nethermind. Discover more [here](/resources/audits).

</details>


# Terminology

Learn about Lagoon's technical terms

## Vaults

**Vaults are smart contracts responsible for tokenizing the ownership of a strategy in exchange of an underlying asset.** Vaults manage deposits, withdrawals, and accounting for the underlying asset.

## ERC-7540

ERC-7540 vaults introduce **asynchronous deposits and withdrawals**, allowing vault entry and exit to be processed in a 2 steps fashion, one for the request and one for the claim. It is also used for share tokenization in ERC20. Lagoon vaults are based on this standard.

## Multisig Wallet

An 'Externally Owned Account' (EOA) is controlled by a single private key. While a multisig wallet is built on top of a smart contract and requires several 'EOA' acting as signers for each transaction.

A multisig wallet emphasizes security and programmability. This solution is suitable when multiple parties need to coordinate.

{% hint style="success" %}
In this field, [Safe](https://app.safe.global/) is the most prominent and battle-tested multisig wallet provider.
{% endhint %}

## Valuation Provider

The vault is expecting to receive updates of the total value in the strategy in order to settle requests. The valuation provider is responsible for computing this value and propose it. For this value to be enforced in the vault and used to settle requests the curator address has to approve it.

## Underlying token

The **underlying token** refers to the asset in which users will deposit and withdraw.

The valuation provider will propose the new total asset in this unit of account.

## Shares

**Shares** represents a claim on assets deposited within the vault.

They are distributed in exchange of a given underlying token, at a price determined by the valuation Provider, at settlement.

While the **price per share** reflects a given vault's performance and its evolution over time denominated in the vault underlying token.

## **Vault** Settlement

**Settlement** describe the action by which a curator validate the previous valuation Provider proposal. A settlement will honor all deposits requests. Withdrawal requests will be honored if the curation address has enough assets available.


# Architecture Overview

Lagoon is a full stack vault management infrastructure designed to run investment products with asynchronous subscriptions and redemptions, **powered by ERC 7540**. They are designed to support NAV-based settlement, role-based permissions, and configurable fee logic. This request-then-settle workflow mirrors subscription and redemption cycles used in traditional asset management. When required, Lagoon can also operate in a synchronous mode.

{% hint style="success" %}
Lagoon vaults are built in Solidity, deployed on EVM-compatible chains, and have been audited by three independent auditor firms. You can find the audits [<mark style="color:$primary;">**here**</mark>](/resources/audits).
{% endhint %}

## Key Concepts

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Asynchronous Request</strong></mark></td><td>Deposits and redemptions are requested first, then settled later at a defined valuation point. Vaults can also be configured as async-only, permanently disabling synchronous operations.</td><td><a href="/vault/deposit-and-withdraw-flows">Deposit and Redemption flows</a></td></tr><tr><td><mark style="color:$primary;"><strong>Valuation</strong></mark></td><td>NAV inputs are used to price shares at the moment of settlement, not at the moment of request.</td><td></td></tr><tr><td><mark style="color:$primary;"><strong>Settlement</strong></mark></td><td>The curator processes pending requests at a chosen valuation point, ensuring consistent pricing within a cycle.</td><td></td></tr><tr><td><mark style="color:$primary;"><strong>Roles</strong></mark></td><td>Responsibilities are separated between the curator, valuation provider, vault admin, security council, and access manager.</td><td></td></tr><tr><td><mark style="color:$primary;"><strong>Guardrails</strong></mark></td><td>On-chain price-per-share bounds that constrain how much the valuation can change between updates, managed by the Security Council.</td><td><a href="/vault/roles-and-capacities/security-council">Security Council</a></td></tr><tr><td><mark style="color:$primary;"><strong>Access Control</strong></mark></td><td>Vaults support whitelist mode, blacklist mode, and external sanctions list integration for flexible, on-chain participation controls.</td><td><a href="/vault/roles-and-capacities/whitelist-manager">Access Manager</a></td></tr></tbody></table>

## How It Works <a href="#how" id="how"></a>

Users submit deposit or redemption requests. The curator settles the requests at a defined valuation point. Users claim the resulting assets or shares. This batching ensures consistent pricing within a settlement cycle and reduces operational complexity.

{% stepper %}
{% step %} <mark style="color:$primary;">**Request**</mark>

User submits a deposit or redemption request. The request is queued and does not execute immediately.
{% endstep %}

{% step %} <mark style="color:$primary;">**Valuation**</mark>

The valuation provider submits a new NAV to the vault. The curator reviews and approves it before it can be applied to any pending requests, ensuring no settlement occurs on an unverified valuation.
{% endstep %}

{% step %} <mark style="color:$primary;">**Settle**</mark>

The curator processes all pending requests at a defined NAV valuation point, ensuring consistent pricing within the settlement cycle.
{% endstep %}

{% step %} <mark style="color:$primary;">**Claim**</mark>

User claims their resulting shares (on deposit) or assets (on redemption) after settlement is complete.
{% endstep %}
{% endstepper %}

## Lagoon Vault v0.6.0 - Architecture

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FUkXLmAH7ALyE1IDBi5mc%2FLagoon%20vault%20Archi.jpg?alt=media&amp;token=72652672-ba9d-4750-a78e-4b92a41bcfef" alt=""><figcaption></figcaption></figure>


# Deposit and Redemption flows

Lagoon vaults' deposit and withdrawal flows are based on an asynchronous mechanism.

Asynchronous deposits and withdrawals follow a four step flow. Requests are grouped and settled at a single valuation point, ensuring consistent pricing within each settlement cycle.

{% hint style="info" icon="lightbulb" %}
Why Asynchronous Matters

Asynchronous flows reduce fragmented execution and allow settlement to align with valuation, strategy constraints, and operational processes.
{% endhint %}

{% hint style="info" %}
Vaults can be configured as **async-only**, permanently disabling synchronous deposits and redeems.
{% endhint %}

### Deposit flow:

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fz2eqfkgpDX30LTQl8qAq%2FScreenshot%202025-05-01%20at%2016.20.53.png?alt=media&amp;token=bd816cea-0a35-4d33-a09d-03e4d889c7c9" alt=""><figcaption><p>Deposit workflow</p></figcaption></figure>

{% stepper %}
{% step %} <mark style="color:$primary;">**Request**</mark>

<sup>**User signals intent to deposit**</sup>

Users call `requestDeposit` to signal their intent to enter the vault. Assets are transferred to the pending silo, a utility contract deployed at vault creation to hold assets awaiting settlement.
{% endstep %}

{% step %} <mark style="color:$primary;">**Valuation and Settlement**</mark>

<sup>**Curator batches and processes requests at a valuation point**</sup>

Settling requires a fair valuation of the vault's positions. The valuation provider submits a NAV to the vault. The curator reviews and approves it by calling `settleDeposit`, ensuring no settlement occurs on an unverified valuation.

All queued deposit requests are then processed at this single valuation point. The corresponding shares are minted.

{% hint style="info" %}
This is a two-step procedure: the valuation provider *proposes* the NAV first, then the curator *accepts and settles*. This separation adds an extra layer of verification.
{% endhint %}
{% endstep %}

{% step %} <mark style="color:$primary;">**Claim**</mark>

<sup>**User receives shares after settlement**</sup>

After settlement, users start earning directly. Ownership of the vault is represented by an ERC-20 share token. Shares are held inside the vault and can be claimed at any time on the vault page.

{% hint style="success" %}
The curator can claim shares on behalf of users and transfer them directly to their address. See [How to claim shares on behalf of users.](https://docs.lagoon.finance/~/revisions/phXXVbw4mv6W4TT1F2GY/vault/how-to/claim-shares-on-behalf-of-users)
{% endhint %}
{% endstep %}
{% endstepper %}

### Redemption flow

In the redemption process, unlike the deposit process, users cannot cancel their withdrawal requests. This measure prevents users from making curators unwind positions without a valid reason.<br>

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FePtUUcCLCon6JbwXe0bo%2FScreenshot%202025-05-01%20at%2016.21.12.png?alt=media&amp;token=4cb7c8a4-0515-40d7-a5e3-d8b1b0a1a498" alt=""><figcaption><p>Redemption workflow</p></figcaption></figure>

{% stepper %}
{% step %} <mark style="color:$primary;">**Request**</mark>

<sup>**User signals intent to withdraw**</sup>

Users call `requestRedeem` to signal their intent to exit the vault. Shares are transferred to the pending silo. Unlike deposits, redemption requests **cannot be cancelled** once submitted.
{% endstep %}

{% step %} <mark style="color:$primary;">**Settlement**</mark>

<sup>**Curator batches and processes requests at a valuation point**</sup>

The valuation provider submits a NAV. The curator reviews, approves, and calls `settleRedeem`. All queued redemption requests are processed at this single valuation point. The corresponding assets are unlocked.
{% endstep %}

{% step %} <mark style="color:$primary;">**Claim**</mark>

<sup>**User receives assets after settlement**</sup>

After settlement, assets are available for the user to claim on the vault page. The curator **cannot** claim on behalf of users for redemptions. Each user must trigger their own claim transaction.

{% hint style="success" %}
The curator can claim assets on behalf of users and transfer them directly to their address.
{% endhint %}
{% endstep %}
{% endstepper %}

### Lagoon Epoch workflow

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fkxyl5KR5jXKhhtLfj48K%2Fredeem_flow%20(1).jpg?alt=media&amp;token=635ddf6e-d645-4f60-ad89-063c11f20b82" alt=""><figcaption></figcaption></figure>


# Vault valuation

Vault valuation defines the **NAV (Net Asset Value)** and price per share used during settlement. It is proposed by a **valuation provider** and then applied when the curator settles deposit and withdrawal batches.

{% hint style="info" %}
In Lagoon, the valuation provider propose the vault’s valuation on-chain. Accuracy is critical because it sets the price per share used for settlement, which determines how many shares users receive, how much they redeem, and how fees are applied.
{% endhint %}

### What valuation determines <a href="#determines" id="determines"></a>

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Shares on deposit</strong></mark></td><td>The number of shares minted for a user when their deposit request is settled</td></tr><tr><td><mark style="color:$primary;"><strong>Assets on redemption</strong></mark></td><td>The amount of assets returned to a user when their redemption request is settled.</td></tr><tr><td><mark style="color:$primary;"><strong>Fee calculation</strong></mark></td><td>Management and performance fees are computed based on the vault's NAV at each valuation update.</td></tr></tbody></table>

### How to compute a valuation ?

A valuation must exclusively reflect the **positions held by the curating address**. Valuation excludes pending deposits, which sit in silos until they are settled. **They are not yet part of the vault's managed assets.**

Please see the following example:

| Value               | Amount                                           |
| ------------------- | ------------------------------------------------ |
| Curating balance    | <mark style="color:$primary;">**10 USDC**</mark> |
| Deposit Requests    | 5 USDC                                           |
| Redemption Requests | 2 USDC                                           |
| Valuation expected  | <mark style="color:$primary;">**10 USDC**</mark> |

In practice, the 10 USDC will be spread around different yield generating positions. It is the responsibility of the Valuation Provider to value the positions in the underlying asset of the vault, in the above example in USDC.

{% hint style="warning" %}
**First valuation**

At deployment, the vault starts with no priced assets, no positions have been opened yet. The initial valuation is therefore set to <mark style="color:$primary;">**0**</mark> until the first NAV update is provided by the valuation provider.
{% endhint %}

{% hint style="info" %}
Valuation can be computed **off-chain** (e.g. by a external or internal valuation provider ) or derived **on-chain** via a smart contract that fetches position data directly. The vault accepts both approaches.
{% endhint %}

### A 2-steps procedure

For greater security, applying a valuation requires two separate actions. Neither the valuation provider nor the curator can act alone.

{% stepper %}
{% step %} <mark style="color:$primary;">**Valuation provider proposes a NAV**</mark>

The valuation provider submits a new NAV to the vault contract. This value is stored but not yet applied. No settlement can occur at this stage.
{% endstep %}

{% step %} <mark style="color:$primary;">**Curator reviews and accepts**</mark>

The curator verifies the proposed NAV and, if correct, calls `settleDeposit` or `settleRedeem` to apply it. Pending requests are then settled at this valuation point.
{% endstep %}
{% endstepper %}

<details>

<summary>Why 2-steps ?</summary>

Valuation is a critical factor in ensuring the vault's correct operation. To support this, it’s essential to give vault administrators flexibility in their valuation process.

This 2-steps approach offers several benefits:

* <mark style="color:$primary;">**Flexible valuation source:**</mark> The valuation provider can be any address: an off-chain backend service, an on-chain smart contract, or a trusted third party. Admins choose the most appropriate setup for their strategy.
* <mark style="color:$primary;">**Curator cannot act unilaterally:**</mark> The curator approves but cannot push a valuation themselves, preventing any single actor from manipulating settlement pricing.

</details>

{% hint style="info" %}
See [<mark style="color:$primary;">**How to update the vault valuation and settle requests**</mark>](/vault/how-to/update-the-vault-valuation-and-settle-requests) for a step-by-step guide.
{% endhint %}


# Fees

Set up your fee system

Lagoon vaults support four types of fees: <mark style="color:$primary;">**management**</mark>, <mark style="color:$primary;">**performance**</mark>, <mark style="color:$primary;">**entry/exit**</mark> and <mark style="color:$primary;">**protocol**</mark>. All fee parameters are encoded directly in the vault's smart contract, visible to any investor before deposit. Fees are collected at each settlement and distributed as shares to the designated feeReceiver address.

| Fee type       | Charged on                              | When collected     |
| -------------- | --------------------------------------- | ------------------ |
| Management     | Total AUM                               | At each settlement |
| Performance    | New profits above high-water mark       | At each settlement |
| Entry and Exit | New deposit and withdrawal requests     | At each settlement |
| Haircut        | Instant redemptions, after the exit fee | At redemption      |
| Protocol       | Vault fees collected                    | At each settlement |

## **Management Fees**

A periodic charge on the total assets under management. It accumulates continuously over time and is collected at each settlement, based on the vault's current valuation.

$$
\text{managementFee} = \left( \frac{\text{assets} \times \text{rate}}{\text{BPS}} \right) \times \frac{\text{timeElapsed}}{\text{1 year}}
$$

* **assets** is the total assets being managed.
* **rate** is the fee rate for 1 year in BPS.
* **BPS** is a constant representing "Basis Points", 10 000 for percentage conversions (e.g., 1% = 100 BPS).
* **timeElapsed** is the time period for which the fee is calculated.

{% hint style="info" %}
The management fee grows **linearly over time.** The longer the period between settlements, the more fees accumulated. The fee is proportional to the vault's AUM and the annual rate.
{% endhint %}

## **Performance Fees**

Applied exclusively to new profits, calculated against the **high-water mark,** the highest price per share the vault has ever reached. This ensures managers are only rewarded for genuine new gains, never for recovering previous losses.

$$
\begin{align\*}
\text{If } \text{pricePerShare} > \text{highWaterMark}: \\
\text{profit} &= (\text{pricePerShare} - \text{highWaterMark}) \times \text{totalSupply} \\\[1em]
\text{performanceFee} &= \frac{\text{profit} \times \text{rate}}{\text{BPS}}
\end{align\*}
$$

* **pricePerShare** is the current price per share.
* **highWaterMark** is the highest price per share reached.
* **totalSupply** is the total number of shares.
* **rate** is the performance fee rate (in basis points).
* **BPS** is a constant representing basis points (10 000).

{% hint style="info" %}
The performance fee is directly tied to profits and managers are rewarded only for returns exceeding the high-water mark.
{% endhint %}

## **Entry and Exit Fees**

Flat-percentage fees applied on every deposit and every redemption. Entry fees are deducted from the shares minted to the depositor; exit fees are deducted from the shares used to compute the assets returned to the redeemer. Both are taken in **shares** and sent to the `feeReceiver` at settlement, with the protocol cut split off as for any other fee.

$$
\text{entryFeeShares} = \frac{\text{grossShares} \times \text{entryRate}}{\text{BPS}}
$$

$$
\text{exitFeeShares} = \frac{\text{shares} \times \text{exitRate}}{\text{BPS}}
$$

* **grossShares** is the shares amount before deducting the entry fee.
* **shares** is the amount of shares being redeemed.
* **entryRate / exitRate** are the fee rates in BPS.
* **BPS** is a constant representing basis points (10 000).

Both fees apply to **both async and sync flows** (`requestDeposit` / `syncDeposit` for entry, `requestRedeem` / `syncRedeem` for exit). For async flows the rate in effect at the moment of **settlement** is what applies — not the rate at the time the request was submitted — and that rate is frozen on-chain in the settlement data, so users can verify after the fact exactly what fee they paid.

{% hint style="info" %}
After vault initialization, `entryRate` and `exitRate` **can only be lowered, never raised**. Combined with the 2% hard cap, this means the maximum fee a user can ever pay on entry or exit is fixed when they first interact with the vault.
{% endhint %}

## Haircut (Instant Exit Fee)

An additional fee charged **only on instant redemptions** (`syncRedeem`), on top of the base exit fee. Where the exit fee remunerates the vault operator, the haircut compensates the holders who stay for serving an immediate exit priced off a valuation that is not refreshed at that instant.

### When it applies

`syncRedeem` — and therefore the haircut — is only reachable when **all** of the following hold:

| Condition                                                                                                                                   | Controlled by                            | If not met                         |
| ------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ---------------------------------- |
| `syncMode` is `SyncRedeem` or `Both`                                                                                                        | Curator, via `setSyncMode`               | Async redemption remains available |
| The valuation is still valid: less than `totalAssetsLifespan` seconds have elapsed since the last valuation update (`isTotalAssetsValid()`) | Curator, via `updateTotalAssetsLifespan` | Async redemption remains available |
| The vault is `Open` (not `Closing` or `Closed`) and not paused                                                                              | Vault admin / Security Council           | Both flows blocked                 |
| Caller and receiver pass the access check                                                                                                   | Access Manager                           | Both flows blocked                 |

Only the first two conditions are specific to instant exits: when `syncMode` excludes sync redeems or the valuation has expired, `syncRedeem` reverts and the user redeems through the asynchronous flow (`requestRedeem`), **which never charges a haircut** — only the exit fee. The last two gate `requestRedeem` just the same, so they leave no fallback. Integrators can probe availability with `previewSyncRedeem(shares)`, which returns 0 when instant redemption is unavailable.

### How it is computed

The haircut is applied **after** the base exit fee, on the shares remaining once that fee has been deducted — not on the original redeemed amount.

$$
\begin{align\*}
\text{exitFeeShares} &= \frac{\text{shares} \times \text{exitRate}}{\text{BPS}} \\\[1em]
\text{haircutShares} &= \frac{(\text{shares} - \text{exitFeeShares}) \times \text{haircutRate}}{\text{BPS}} \\\[1em]
\text{assets} &= \text{convertToAssets}(\text{shares} - \text{exitFeeShares} - \text{haircutShares})
\end{align\*}
$$

Because the two are applied in sequence rather than summed, the combined charge is slightly below their addition: 2% exit and 20% haircut cost 21.6% in total, not 22%.

Redeeming 1 000 shares with `exitRate` = 100 BPS (1%) and `haircutRate` = 500 BPS (5%):

* **exitFeeShares** = 1 000 x 1% = 10 shares, minted to the `feeReceiver` (with the protocol cut split off).
* **haircutShares** = (1 000 - 10) x 5% = 49.5 shares, burned.
* The redeemer receives the asset value of the remaining 940.5 shares.

### Where it goes

Unlike every other fee, the haircut is **not paid to the `feeReceiver`** and carries **no protocol cut**. The shares are burned while the matching assets stay in the vault, so the value accrues to the remaining holders. Each instant redemption emits a `HaircutTaken` event with the shares taken and the rate applied.

{% hint style="info" %}
The redemption itself leaves the price per share **unchanged**: the vault deducts the full pre-haircut asset value from `totalAssets`, as if the haircut had never been taken. The retained value therefore only becomes visible — as a higher price per share for remaining holders — at the **next `totalAssets` update**, when the valuation is refreshed and requests are settled.
{% endhint %}

{% hint style="warning" %}
Unlike `entryRate` and `exitRate`, which can only be lowered after initialization, `haircutRate` can be raised or lowered at any time within its 20% cap. Read the current rate — or call `previewSyncRedeem` — before an instant redemption.
{% endhint %}

## Protocol fees

Lagoon earns a percentage of the fees collected by the vault. For example, if the vault computes 200 shares for performance and management fees, and the protocol fee rate is 10%, Lagoon receives 10% of the 200 shares, equating to 20 shares.

## Maximum Fee Limits

Protocol-enforced caps protect depositors from excessive fees. These limits are hardcoded in the smart contract and cannot be overridden by vault operators.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td><h4><mark style="color:$primary;"><strong>Management Fee Cap</strong></mark></h4></td><td><h4><strong>10%</strong></h4></td><td><sup>per year, maximum configurable by curator</sup></td></tr><tr><td><h4><mark style="color:$primary;"><strong>Performace Fee Cap</strong></mark></h4></td><td><h4><strong>50%</strong></h4></td><td><sup>on profits above high-water mark</sup></td></tr><tr><td><h4><mark style="color:$primary;"><strong>Entry and Exit Fee Cap</strong></mark></h4></td><td><h4><strong>2%</strong></h4></td><td><sup>on new deposit and withdrawal requests. Rates can only decrease, never increase.</sup></td></tr><tr><td><h4><mark style="color:$primary;"><strong>Haircut Fee Cap</strong></mark></h4></td><td><h4><strong>20%</strong></h4></td><td><sup>on instant redemptions, applied after the exit fee</sup></td></tr><tr><td><h4><mark style="color:$primary;"><strong>Protocol</strong></mark></h4></td><td><h4>10%</h4></td><td><sup><strong>fix protocol fee.</strong> On-chain limitation set to 30%</sup></td></tr></tbody></table>

## **Fee Distribution**

At every settlement, the vault mints new shares to represent the fees owed. These shares are sent directly to the `feeReceiver` address configured at vault creation.

{% hint style="info" %}
Fees are distributed as **shares, not assets**. This means the fee receiver participates in the vault's performance from the moment fees are collected, without triggering any asset movement.
{% endhint %}


# Upgradability & Opt-in Proxy

Lagoon vaults use a [Transparent Upgradable Proxy](https://rareskills.io/post/transparent-upgradeable-proxy). This allows the vault admin to upgrade the vault logic when needed.

Lagoon uses extended versions of the [OpenZeppelin Transparent Upgradeable Proxy](https://docs.openzeppelin.com/contracts/5.x/api/proxy#TransparentUpgradeableProxy) and [ProxyAdmin](https://docs.openzeppelin.com/contracts/5.x/api/proxy#ProxyAdmin), adding two features: an Opt-in system and a Delay mechanism.

## Opt-in system

The owner of [ProxyAdmin](https://docs.openzeppelin.com/contracts/5.x/api/proxy#ProxyAdmin) can upgrade its vault to any implementation that has been reviewed and whitelisted by Lagoon. He can also roll back to a previous version at any time.

## Delay mechanism

Every upgrade is subject to a mandatory waiting period before it takes effect. This gives investors time to evaluate the incoming change and exit the vault if needed.

The delay window is **configurable by the vault admin**, within the protocol bounds of 24 hours (minimum) to 30 days (maximum). Changing the delay itself is also subject to the same delay mechanism.

## Design

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FzUjLgA79h9WrUyGnO1Hi%2FScreenshot%202025-08-04%20at%2015.28.46.png?alt=media&amp;token=aa2a6cad-ccdb-4203-bd6c-10be492056c9" alt=""><figcaption></figcaption></figure>

### Opt-in Proxy

The Opt-in Proxy is what you will usually consider as the vault. This contract is a TransparentUpgradbleProxy by OpenZeppelin with two differences. First it doesn't deploy a ProxyAdmin but DelayProxyAdmin. Second, before each implementation update, it will asked the authorization to the ProtocolRegistry, by calling `canUseLogic(address oldLogic, address newLogic).`

### ProtocolRegistry

A protocol level smart-contract that contains a whitelist of authorized implementations.

| Function                                                            | Description                                                                                            |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `canUseLogic(address oldLogic, address newLogic) returns (boolean)` | This function checks if newLogic is an authorized Lagoon vault version, in this case, it returns true. |

### DelayProxyAdmin

A Proxy Admin is a smart-contract deployed by an Opt-inProxy at its creation. This contract is the only address that can upgrade the Opt-inProxy.

The DelayProxyAdmin has an editable owner that is the only one capable of doing the following calls:

| Function                                                                                                                                                  | Description                                                                                                                      |
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `submitImplementation(address _implementation) onlyOwner`                                                                                                 | Submit an address in the DelayProxyAdmin contract. When the delay is passed, the owner can upgrade the contract to this address. |
| <p><code>upgradeAndCall(</code><br><code>address proxy,</code><br><code>address,</code><br><code>bytes memory data</code><br><code>) onlyOwner</code></p> | Upgrade the target proxy using the implementation previously stored via submitImplementation.                                    |
| <p><code>submitDelay(</code><br><code>uint256 \_delay</code><br><code>) onlyOwner</code></p>                                                              | Submit a new delay. When the current delay is passed, the new delay can be applied.                                              |
| `function updateDelay() onlyOwner`                                                                                                                        | Update the value of the delay to be the one previously submitted via submitDelay.                                                |
| `renounceOwnership() onlyOwner`                                                                                                                           | Renounce the ownership of the DelayAdminProxy making it unusable.                                                                |
| `function transferOwnership(address newOwner)`                                                                                                            | Transfer the ownership and thus the vault upgradability management to another address.                                           |

### Q\&A

<details>

<summary>Can I make my vault immutable ?</summary>

Yes, a vault can become immutable if the owner of DelayProxyAdmin gives up his ownership.

</details>

<details>

<summary>Can I rollback a vault upgrade ?</summary>

Any form of downgrades are authorized for now. Note that a downgrade won't reinitialize the state of your vault, which means that if you downgrade to the previous version, you will get back the previous state.

</details>

<details>

<summary>How can I be informed of new vault versions releases ?</summary>

Stay updated on Lagoon developments [here](https://t.me/+mvB7YsN80P5jNTVk).

</details>

<details>

<summary>Are the vault owner (admin) and the DelayProxyAdmin owner the same ?</summary>

No, those are two different variables present in two different contracts.\
The vault owner, that we usually call the admin if defined [here](/vault/roles-and-capacities/vault-admin). His scope is exclusively over the vault roles and operations. On the other hand, the owner of the DelayProxyAdmin can only do operations related to the upgradability of the proxy.\
They can have the same value but changing one won't change the other.

</details>


# Cross-chain vaults

Give investors on several chains access to a single strategy, using a main vault and sub-vaults.

A Lagoon vault lives on one chain. The same vault cannot be deployed across several chains and kept in sync.

When a strategy must be reachable from several chains, the pattern is a **vault of vaults**: one **main vault** on the chain where the strategy is executed, and one **sub-vault** per chain where investors are. Each sub-vault has a single allocation: the main vault.

{% hint style="info" %}
This is a custom setup. The [deployer interface](/vault/deploy-your-vault) deploys standalone vaults, the main/sub-vault wiring is done manually after deployment. Reach out [here](https://tally.so/r/nGBGyz) if you want support setting it up.
{% endhint %}

## Architecture

Assets are held in one place, the main vault on the hub chain. Every sub-vault is a **virtual vault**: its only asset is the main vault shares held by its own curator address on the hub chain. It exists to abstract the bridging away from investors, who deposit and redeem on their own chain, in their own asset, and never leave it.

An investor ends up holding sub-vault shares, main vault shares, or both, depending on where they deposited.

{% hint style="info" %}
**One curator, one address per vault and per chain**

The same entity curates every vault of the structure, but it operates through a distinct address for each vault on each chain:

* the **sub-vault address on the spoke chain** settles the sub-vault and sends the assets over the bridge,
* the **sub-vault address on the hub chain** receives them, deposits into the main vault, and holds the main vault shares,
* the **main vault address** receives the main vault assets and deploys them into the strategies.

Keeping them separate is what makes the accounting readable: the sub-vault position is exactly what its own address holds on the hub chain, and nothing else.
{% endhint %}

## Deposit flow

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fgit-blob-5a1faa3ba83b3b96c4bcd70f7a056af8efe5a87c%2Fcross-chain-deposit-flow.svg?alt=media" alt="Cross-chain deposit and allocation flow"><figcaption></figcaption></figure>

1. **Deposit in the sub-vault** — the investor submits a standard [async deposit request](/developer-hub/integration/async-deposit-flow) on their own chain.
2. **Settle: assets to the sub-vault address** — the curator settles the sub-vault batch, the assets land on the curator sub-vault address on the spoke chain.
3. **Bridge to the hub chain** — the assets are bridged to the curator sub-vault address on the hub chain.
4. **Deposit in the main vault** — that same address submits a deposit request on the main vault.
5. **Main shares to the sub-vault address** — once the main vault settles, that address claims the shares. They are the sub-vault's only asset.
6. **Assets to the main vault address** — the main vault sends the settled assets to its own curator address.
7. **Allocate to the strategies** — the main vault address deploys them, exactly as for a single-chain vault.
8. **Sub-vault shares to the investors** — after the sub-vault NAV is updated and the batch settled, investors claim their shares.

Investors already on the hub chain skip all of it:

9. **Direct deposit in the main vault** — a standard deposit request on the main vault.
10. **Shares to the direct investors** — claimed once the main vault settles, at the same price per share as the sub-vault address.

Two settlement cycles plus a bridge sit between a sub-vault request and the shares. Set the sub-vault settlement cadence accordingly.

## Redemption flow

Redemption runs the same path backwards.

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fgit-blob-238017252ec601546b9c77b49e579b5ebbe18a74%2Fcross-chain-redemption-flow.svg?alt=media" alt="Cross-chain redemption flow"><figcaption></figcaption></figure>

1. **Request a redemption** — the investor submits a redemption request on the sub-vault.
2. **Redeem from the main vault** — the curator sub-vault address on the hub chain requests a redemption on the main vault for the corresponding amount.
3. **Unwind the strategies** — the main vault address frees the liquidity needed to settle the batch.
4. **Assets back to the main vault** — the main vault address returns them so the batch can settle.
5. **Assets to the sub-vault address** — the sub-vault address claims its share of the settled assets.
6. **Bridge back to the spoke chain** — the assets are bridged to the sub-vault address on the spoke chain.
7. **Settle the redemption batch** — the sub-vault NAV is updated, then the batch is settled.
8. **Return the assets to the investors** — investors claim on their own chain.

And for the investors on the hub chain:

9. **Direct redemption request** — submitted on the main vault.
10. **Assets to the direct investors** — claimed once the main vault settles, without bridge.

Liquidity on a sub-vault is bounded by the main vault redemption cycle: a sub-vault can never settle faster than the main vault it depends on.

## Valuation

**Each vault keeps its own NAV and its own price per share. Updating one does not propagate to the others.**

### Sub-vault

The sub-vault holds no strategy position. Its NAV is what its curator address holds on both chains, plus its position in the main vault:

```
subVaultNAV = underlying held by the curator sub-vault address on the spoke chain
            + underlying held by the curator sub-vault address on the hub chain
            + mainVaultShares × mainVaultPricePerShare
```

The first two lines cover the assets in transit: settled on the spoke chain but not yet bridged, or bridged but not yet deposited in the main vault. Omitting them under-reports the sub-vault price per share.

The sub-vault valuation provider reads the main vault price per share on the hub chain and pushes the resulting NAV to the sub-vault. See [Vault valuation](/vault/vault-valuation) for the update and settlement procedure.

### Main vault

The main vault is valued like any single-chain Lagoon vault:

```
mainVaultNAV = underlying held by the curator main vault address
             + value of the strategy positions
```

{% hint style="warning" %}
**These are theoretical NAVs**

Both formulas describe the standard setup. A specific configuration, several sub-vaults sharing an address, a different underlying on each chain, positions held outside the curator addresses, or fees charged at the sub-vault level, changes what has to be counted. Validate the computation against your own setup before running it in production.
{% endhint %}

## TVL

Assets deposited through a sub-vault increase the main vault `totalAssets`, and therefore the TVL of the hub chain. Aggregating the main vault TVL and the sub-vault TVLs would double count them.

## Trade-offs

* Investors never leave their chain, and the strategy is executed once, in one place.
* Deploying several vaults adds no cost to a Lagoon setup.
* Latency: a deposit crosses two settlement cycles and a bridge before it is invested. Same for a redemption.
* Operational load: one NAV update process per sub-vault, plus the bridging.


# Roles and capacities

Navigate between the different roles to discover their associated capacities.

Lagoon vaults use role-based permissions to separate governance, execution, valuation, and access control. This structure reduces operational risk and makes responsibilities explicit. It is designed to mirror traditional asset management and compliance standards, where duties are split across independent functions and controls. Each role has a defined scope and can be assigned to different entities or custody setups.

Below is a summary of what each role can do:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Vault Admin</strong></mark></td><td>Governs configuration and safety controls. It does not run the strategy, but it can change critical parameters.</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/SCQMI0F4if57hlw2ce8s/role_administrator.png">role_administrator.png</a></td><td><a href="/vault/roles-and-capacities/vault-admin">Vault admin</a></td></tr><tr><td><mark style="color:$primary;"><strong>Vault Curator</strong></mark></td><td>Manages strategy allocation and executes settlements. It validates the valuation proposal and decides when to process deposit and withdrawal batches.</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/nUJZggHxHaniwJYm9o4N/role_asset_manager.png">role_asset_manager.png</a></td><td><a href="/vault/roles-and-capacities/curator">Curator</a></td></tr><tr><td><mark style="color:$primary;"><strong>Valuation Provider</strong></mark></td><td>Proposes the valuation inputs used to set the settlement price per share. Accuracy matters because it drives how many shares are minted, how much users redeem, and how fees are applied.</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F2j12Jlpy9K7zGR1Ebqy0%2Fphoto_2026-03-11_15-55-21.jpg?alt=media&amp;token=b0242923-2b29-42ab-af30-713f557191b8">photo_2026-03-11_15-55-21.jpg</a></td><td><a href="/vault/roles-and-capacities/valuation-oracle">Valuation Provider</a></td></tr><tr><td><mark style="color:$primary;"><strong>Access Manager </strong></mark><sup><mark style="color:$primary;"><strong>(former Whitelist Manager)</strong></mark></sup></td><td>Controls which addresses can interact with the vault, using whitelist mode, blacklist mode, or external sanctions list integration.</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/yF2rr4qTffDC4KKNcFLe/role_whitelist_manager.png">role_whitelist_manager.png</a></td><td><a href="/vault/roles-and-capacities/whitelist-manager">Access Manager</a></td></tr><tr><td><mark style="color:$primary;"><strong>Super Operator</strong></mark></td><td>A compliance role. It bypasses access list restrictions and can act on the shares of a holder who is no longer authorized to participate.</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FjQRHKexaJSEVKvs67Roe%2Fsuperoperator.jpg?alt=media&amp;token=9ad47ce2-b7d5-43bf-95af-e125f439730f">superoperator.jpg</a></td><td><a href="/vault/roles-and-capacities/super-operator">Super Operator</a></td></tr><tr><td><mark style="color:$primary;"><strong>Security Council</strong></mark></td><td>Manages price-per-share guardrails to protect depositors against abnormal valuation movements. An independent governance oversight role.</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fb6QWZYQLg6l3y7gkZbxO%2Fseucrity-council.jpg?alt=media&amp;token=c4daa03f-cb14-4c89-9069-3ea831bf09aa">seucrity-council.jpg</a></td><td><a href="/vault/roles-and-capacities/security-council">Security Council</a></td></tr></tbody></table>


# Vault admin

An overview of the Vault Admin role.

The Vault Admin is the governance and safety role of a Lagoon vault. It controls critical configuration and defines who holds key permissions. This role does not run the strategy. It sets the rules and the control surface.

Because the Vault Admin can change sensitive parameters, it should be held by a robust custody setup such as a Safe multisig or an institutional MPC, with clear internal controls and clear disclosure to users.

{% hint style="warning" %}
The Vault Admin can update core addresses, pause the vault, and initiate closure. Treat this role as a high privilege role and secure it accordingly.
{% endhint %}

### Responsibilities

The Vault Admin is responsible for:

* Assigning and updating key roles and addresses
* Managing emergency controls
* Managing fee configuration
* Managing the vault lifecycle state
* Maintaining public facing vault metadata used by front ends, when applicable

### What the Vault Admin can do

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Goverance</strong></mark></td><td><ul><li>Transfer ownership using a two step process where the new admin must accept ownership</li><li>Renounce ownership, permanently removing admin authority</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Security and Access control</strong></mark></td><td><ul><li>Pause and unpause the vault. cf: <a href="/vault/how-to/pause-a-vault">Pause Vault</a></li><li>Switch between black and whitelist</li><li>Enable async-only mode, permanently disabling synchronous deposits and redeems</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Fees and Parameters</strong></mark></td><td><ul><li>Update management and performance fee rates, when enabled</li><li>Apply cooldown rules for fee changes, when configured</li><li>Configure entry and exit fees, when enabled</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Front end information</strong></mark></td><td><ul><li>Update vault metadata used by front ends, such as name, description, logo, links, and tags, when supported by the chosen interface</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Lifecycle management</strong></mark></td><td><ul><li>Initiate vault closing by changing the vault status from Open to Closing</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Operational configuration</strong></mark></td><td><ul><li>Update the Valuation Provider address</li><li>Update the Fee Receiver address</li></ul></td></tr></tbody></table>

### Recommended custody setup

For most teams, the Vault Admin should be held by:

* A Safe multisig with a clear signer policy
* An institutional MPC setup

### What this means for users

Users can always verify the current Vault Admin address and role assignments on-chain. Vault curators are responsible for accurately presenting their product and disclosing all relevant permissions and controls to users, who can independently verify these settings on-chain.


# Valuation Provider

An overview of the Valuation Provider role.

The Valuation Provider publishes the vault valuation used to price the next settlement cycle. This value determines the price per share applied at settlement, which drives how many shares are minted for deposits, how much users redeem, and how fees are calculated. Learn more about [vault valuation](/vault/vault-valuation).

The valuation can be produced off-chain by a valuation engine, or computed on-chain via a pricing contract, depending on the product’s design. **In all cases, accuracy and operational discipline are critical.**

{% hint style="warning" %}
The Valuation Provider sets the valuation inputs used for settlement. Treat this role as sensitive and document the methodology, sources, and update cadence.
{% endhint %}

### Responsibilities

The Valuation Provider is responsible for

* Producing the valuation inputs used for settlement pricing
* Updating the vault valuation on-chain according to the chosen cadence
* Maintaining a consistent methodology and clear disclosure to LPs

{% hint style="info" %}
NAV updates must always be verified and settled by the Vault Curator.
{% endhint %}

### The Valuation Provider is responsible for :

* Producing the valuation inputs used for settlement pricing
* Updating the vault valuation on-chain according to the chosen cadence
* Maintaining a consistent methodology and clear disclosure

{% hint style="warning" %}
The valuation update frequency must be aligned with the curator’s settlement frequency.
{% endhint %}

### Typical setups

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Off-chain valuation engine</strong></mark></td><td>An operator computes NAV from the vault’s positions and price sources, then updates the vault valuation on-chain. This is common for multi-protocol strategies, discretionary portfolios, or products requiring custom pricing logic.</td></tr><tr><td><mark style="color:$primary;"><strong>On-chain valuation contract</strong></mark></td><td>A smart contract computes valuation from on-chain inputs such as oracle feeds and vault positions. This is common when valuation rules can be fully expressed on-chain and verified programmatically.</td></tr></tbody></table>

### What this means for users

Users can verify valuation updates and settlement pricing on-chain. Vault curators remain responsible for disclosing the valuation methodology, update cadence, and the entities involved.


# Curator

Allocates funds

The Curator is the strategy operator of a Lagoon vault. This role manages capital allocation, decides how the vault is deployed across strategies, and controls when settlement cycles are executed. It is the role where investment discretion sits.

The Curator also validates the valuation proposed by the Valuation Provider before processing deposit and withdrawal requests. This ensures settlement remains aligned with the vault’s strategy, operating constraints, and valuation process.

{% hint style="warning" %}
The Curator manages allocation and settlement. This role should be held by the entity or system responsible for strategy execution, with clear operational procedures and disclosure to users.
{% endhint %}

### Responsibilities

The Curator is responsible for:

* Allocating vault assets according to the chosen strategy
* Validating the valuation proposed for settlement
* Deciding when deposit and withdrawal batches are settled
* Managing day to day strategy execution within the vault’s operating framework

### What the Curator can do

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Strategy allocation</strong></mark></td><td><ul><li>Deploy capital into the selected investment strategy</li><li>Rebalance positions over time</li><li>Adjust exposure based on market conditions and portfolio objectives</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Settlement execution</strong></mark></td><td><ul><li>Decide when to process deposit and withdrawal batches</li><li>Execute settlement cycles using the current valuation</li><li>Ensure settlement timing remains consistent with the vault’s operating model</li><li>Entry and exit fees are applied during settlement based on the configured rates</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Performance fee management</strong></mark></td><td><ul><li>Reset the high-water mark to the current price per share, when this capability was enabled at vault creation</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Operational controls</strong></mark></td><td><ul><li>Toggle synchronous redemptions on or off</li><li>Set a maximum cap on total vault assets</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Coordination with valuation</strong></mark></td><td><ul><li>Review and validate the valuation proposed by the Valuation Provider before settlement</li><li>Ensure valuation frequency is appropriate for the settlement cadence</li></ul></td></tr></tbody></table>

### Typical setups

<table data-card-size="large" data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Safe and Zodiac Roles Modifier</strong></mark></td><td>A multisig based setup where strategy execution is controlled through predefined permissions and signer policies.</td><td><a href="/curation-solutions/safe-and-zodiac-roles-modifier">Safe &amp; Zodiac Roles Modifier</a></td></tr><tr><td><mark style="color:$primary;"><strong>MPC wallet</strong></mark></td><td>A multi party computation setup used when the curator requires stronger operational security or institutional signing workflows.</td><td><a href="/curation-solutions/mpc-multi-party-computation-wallet">MPC (Multi-Party Computation) wallet</a></td></tr></tbody></table>

#### What this means for users

The Curator is the role that decides how capital is deployed and when requests are settled. Users should understand who holds this role, how discretionary decisions are made, and how often settlement is expected to occur.


# Access Manager

Control who can access the vault.

The Access Manager controls which addresses are authorized to interact with the vault. Access rules are enforced on-chain, ensuring that participation restrictions are transparent and verifiable.

Lagoon vaults support two access modes, configurable at creation:

* **Whitelist mode** — Only approved addresses can participate. All others are blocked.
* **Blacklist mode** — All addresses can participate, except those explicitly blocked.

### Responsibilities

The Access Manager is responsible for:

* Adding or removing addresses from the whitelist or blacklist, depending on the active mode
* Keeping the access list aligned with the vault's onboarding, compliance, and access policy
* Coordinating with external compliance systems when sanctions list integration is enabled

### What the Access Manager can do

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Whitelist mode</strong></mark></td><td><ul><li>Add approved addresses to the allowlist</li><li>Remove addresses when access should no longer be permitted</li><li>Restrict participation to approved wallets only</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Blacklist mode</strong></mark></td><td><ul><li>Block specific addresses from interacting with the vault</li><li>Revoke addresses from the blocklist to restore access</li><li>Allow open participation by default, with targeted exclusions</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>External sanctions list</strong></mark></td><td><ul><li>Integrate with a third-party on-chain sanctions list for automated compliance checks</li><li>Sanctioned addresses are blocked regardless of the active access mode</li><li>The sanctions list contract is configured at vault initialization</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Typical use cases</strong></mark></td><td><ul><li>KYC or KYB gated vaults (whitelist mode)</li><li>Open vaults with compliance exclusions (blacklist mode)</li><li>Jurisdiction-based access restrictions</li><li>Regulatory-compliant products with sanctions screening</li></ul></td></tr></tbody></table>

### What this means for users

Users can verify the active access mode and their own access status on-chain. Vault operators remain responsible for accurately disclosing the vault's access policy, onboarding requirements, and any permissioning rules applied to participants.


# Super Operator

An overview of the Super Operator role.

The Super Operator is a compliance and security role. It is a single privileged address that can act on any holder's shares without their approval, and that always bypasses access list restrictions, regardless of the active access mode.

It exists to solve a specific problem: access control alone cannot remove a user who already holds shares. If a holder is blacklisted, fails a KYC review, is added to a sanctions list, or is removed from the whitelist, the access list stops them from making new requests but their existing position stays where it is. The Super Operator is the mechanism that lets the vault operator act on that position: it can transfer the holder's shares to another address, and it can request a redemption of those shares on the holder's behalf. Neither requires the holder's approval.

{% hint style="warning" %}
The Super Operator can transfer and redeem any holder's shares without their consent, and chooses the receiving address. Only set it when your product genuinely requires it, hold it in a robust custody setup, and disclose it to users.
{% endhint %}

### Responsibilities

The Super Operator is responsible for:

* Enforcing the vault's compliance policy on holders who are no longer authorized to participate
* Acting on positions that access control alone cannot reach
* Operating within a documented mandate agreed with the vault operator, and only in the cases that mandate covers

### What the Super Operator can do

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Act on held shares</strong></mark></td><td><ul><li>Transfer a holder's shares to another address (<code>transferFrom</code>), without any prior token approval</li><li>Request a redemption of a holder's shares on their behalf (<code>requestRedeem</code>)</li><li>Move a position that would otherwise be frozen in place by the access list</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Act on pending and settled requests</strong></mark></td><td><ul><li>Claim settled shares for a user (<code>deposit</code>, <code>mint</code>)</li><li>Claim settled assets for a user (<code>redeem</code>, <code>withdraw</code>)</li><li>Cancel a user's pending deposit or redeem request</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Bypass access control</strong></mark></td><td><ul><li>Operate regardless of the active access mode, in whitelist and blacklist mode alike</li><li>Complete or unwind operations for users who are no longer on the access list</li><li>The Super Operator address itself is always treated as allowed</li></ul></td></tr></tbody></table>

{% hint style="info" %}
The Super Operator cannot enter the vault for someone: requesting a deposit and depositing synchronously are the only user operations it cannot perform on behalf of a holder.
{% endhint %}

### Typical use cases

* Removing a sanctioned or blacklisted holder from the vault's cap table
* Force-exiting a holder who fails an ongoing KYC or KYB review
* Responding to a legal or regulatory order affecting a specific holder
* Recovering positions during a vault closure or a migration into a new Lagoon vault

{% hint style="info" %}
Routine operations do not need the Super Operator. Claiming settled shares for users in the normal course of business is done by the [Vault Curator](/vault/roles-and-capacities/curator) — see [Claim shares on behalf of users](/vault/how-to/claim-shares-on-behalf-of-users).
{% endhint %}

### Setting, disabling and locking the role

The Super Operator address is set by the [Vault Admin](/vault/roles-and-capacities/vault-admin). A vault can run without one: setting the address to the zero address disables the role entirely, and vaults with no compliance requirement should do exactly that.

The Vault Admin can also permanently lock the Super Operator address. Once locked, the address can never be changed again. This lets an operator commit publicly and irreversibly to a fixed Super Operator, or to no Super Operator at all.

See [`updateSuperOperator`](/developer-hub/smart-contract-reference#updatesuperoperator) and [`lockSuperOperator`](/developer-hub/smart-contract-reference#locksuperoperator) in the smart contract reference.

### Recommended custody setup

Given its scope, the Super Operator should be held by:

* A Safe multisig with a clear signer policy, ideally requiring compliance sign-off
* An institutional MPC setup
* A contract encoding a narrow, auditable mandate

### What this means for users

Users can verify on-chain whether a vault has a Super Operator, which address holds it, and whether it has been locked or disabled. Where one is set, holders should understand that the operator can move or redeem their position without their consent, and should treat this as part of the vault's compliance terms.


# Security Council

An overview of the Security Council role.

The Security Council is a governance oversight role introduced to protect depositors against abnormal valuation movements. It manages the price-per-share guardrails, a set of on-chain bounds that constrain how much the vault valuation can change between updates.

This role exists to add an independent safety layer on top of the standard valuation flow, without interfering with day-to-day operations.

{% hint style="warning" %}
The Security Council can update guardrail parameters without restrictions. This role should be held by a trusted governance body, separate from the Curator and Vault Admin, to maintain effective segregation of duties.
{% endhint %}

### Responsibilities

The Security Council is responsible for:

* Configuring the upper and lower rate bounds that constrain price-per-share movements
* Activating or deactivating guardrail enforcement
* Monitoring valuation patterns and adjusting bounds when market conditions require it

### What the Security Council can do

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Guardrails management</strong></mark></td><td><ul><li>Set the upper annual rate bound, limiting maximum price-per-share appreciation</li><li>Set the lower annual rate bound, limiting maximum price-per-share depreciation</li><li>Activate or deactivate guardrail enforcement on the vault</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Valuation safety</strong></mark></td><td><ul><li>Prevent abnormal valuation updates from being applied at settlement</li><li>Provide an independent check on the valuation flow, separate from the Curator and Valuation Provider</li></ul></td></tr><tr><td><mark style="color:$primary;"><strong>Valuation override</strong></mark></td><td><ul><li>Propose a valuation that bypasses guardrail enforcement, used to exceptionally submit a legitimate valuation that falls outside the configured bounds</li></ul></td></tr></tbody></table>

### How guardrails work

Guardrails define an acceptable range for price-per-share changes between two valuation updates. The bounds are expressed as annual rates and scale proportionally based on the time elapsed since the last update.

At each valuation update, the protocol checks whether the proposed price per share falls within the allowed range. If the variation exceeds the configured bounds, the update is rejected.

{% hint style="info" %}
Guardrails are time-scaled. A vault with a 20% upper annual bound and daily valuations would allow roughly 0.05% appreciation per day. The same bound with weekly valuations would allow roughly 0.38% per week.
{% endhint %}

### Benefits for vault operators

Guardrails provide an extra layer of security on top of the standard valuation flow. Operators gain an independent on-chain check that limits the impact of erroneous or manipulated valuations, with parameters that remain visible and verifiable by depositors.


# Deploy your vault

Lagoon allows curators to deploy and manage vaults permissionlessly. Vaults can be created directly through the Lagoon interface.

{% hint style="info" %}
Before deploying a vault, curators should understand how asynchronous deposits and withdrawals work, how valuation is provided, and how roles are assigned. These choices define how the vault will operate in practice and should be considered before launch.
{% endhint %}

### Before you deploy

Before deploying a vault, make sure you have defined:

* the chain where the vault will be deployed. You can fin the list [here](/resources/networks-and-addresses).
* the vault admin, curator, valuation provider, and other required roles
* the valuation method and settlement frequence
* the access model, including whether whitelisting is required
* the custody and execution setup that will manage the strategy

### Deployment options

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Lagoon interface</strong></mark></td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FgtDCo9mwWMTD17qS71qN%2Fphoto_2026-03-12_16-34-34.jpg?alt=media&amp;token=af1116a3-7816-4fa9-8817-9d3c0950b6a9">photo_2026-03-12_16-34-34.jpg</a></td><td><a href="https://app.lagoon.finance/deploy">https://app.lagoon.finance/deploy</a></td></tr></tbody></table>

### Vault parameters

These are the parameters the vault takes at initialization, as of v0.6.0. The interface asks for them at deployment.

#### Underlying and shares

**`underlying`** (address) – The ERC-20 users deposit, and the unit of account of every valuation. Immutable.

{% hint style="danger" %}
This token can not be a rebasing token such as stETH or an Aave debt token. In the case of stETH you would use its non-rebasing equivalent, wstETH.
{% endhint %}

**`name`** (string) – Name of the ERC-20 shares. Updatable by the Vault Admin.

**`symbol`** (string) – Symbol of the ERC-20 shares. Updatable by the Vault Admin.

***

#### Roles and governance

**`safe`** (address) – Curator address holding the vault assets. Any custody solution works: Safe multisig, MPC wallet or EOA. Updatable by the Vault Admin.

**`admin`** (address) – [Vault Admin](/vault/roles-and-capacities/vault-admin), owner of the vault and of the governance structure.

**`valuationManager`** (address) – [Valuation Provider](/vault/roles-and-capacities/valuation-oracle) pushing the total assets of the vault. Can be a multisig or a contract.

**`whitelistManager`** (address) – [Access Manager](/vault/roles-and-capacities/whitelist-manager), manages the whitelist or the blacklist and the sanctions list.

**`securityCouncil`** (address) – [Security Council](/vault/roles-and-capacities/security-council), manages the price per share guardrails.

**`superOperator`** (address) – [Super Operator](/vault/roles-and-capacities/super-operator), acts on behalf of users and bypasses the access checks. Put the zero address to disable it.

***

#### Access control

**`accessMode`** (enum) – `0` for whitelist mode, `1` for blacklist mode. The two modes are mutually exclusive, see the [Access Manager](/vault/roles-and-capacities/whitelist-manager) page. The Vault Admin can switch mode later.

**`externalSanctionsList`** (address) – Optional on-chain sanctions list (Chainalysis-compatible) queried on every access check. Put the zero address to disable it.

***

#### Fees

**`feeReceiver`** (address) – Address receiving the fee shares at each settlement.

**`managementRate`** (uint16) – Management fee, in bps per year. Capped at `1000` (10%).

**`performanceRate`** (uint16) – Performance fee on gains above the high water mark, in bps. Capped at `5000` (50%).

**`entryRate`** (uint16) – Fee on deposits, in bps. Capped at `200` (2%) and can only be decreased afterwards.

**`exitRate`** (uint16) – Fee on redemptions, in bps. Capped at `200` (2%) and can only be decreased afterwards.

**`haircutRate`** (uint16) – Fee on synchronous redemptions, in bps. Capped at `2000` (20%).

**`allowHighWaterMarkReset`** (bool) – Whether the curator address can reset the performance fee baseline down to the current price per share. Set once at deployment, it can never be enabled later.

{% hint style="info" %}
💡 Fee rates are expressed in **basis points (bps)**

* `0.5%` = `50 bps`
* `2%` = `200 bps`
* `15%` = `1500 bps`
  {% endhint %}

***

#### Migration

**`initialTotalAssets`** (uint256) – Starting total assets of the vault, named **Initial NAV** in the interface. The interface takes the amount in the underlying, the parameter itself takes the raw amount with the decimals of the underlying. Put `0` for a normal vault. A non-zero value pre-mints the matching shares to the curator address without transferring any asset, see [Migrate an existing vault](/vault/how-to/migrate-an-existing-vault-into-a-new-lagoon-vault). Set once at deployment.

***

#### Upgradability

**`initialOwner`** (address) – Owner of the ProxyAdmin, the address able to upgrade the vault logic. Renouncing this ownership makes the vault immutable, which is irreversible.

**`initialDelay`** (uint256) – Delay to wait before an upgrade takes effect, in seconds. Between `86400` (24 hours) and `2592000` (1 month). Editable, after waiting the delay itself.

See [Upgradability and opt-in proxy](/vault/upgradability-and-opt-in-proxy) for the upgrade mechanism.

{% hint style="warning" %}
Coming from a pre-v0.6.0 deployment integration: `enableWhitelist` is replaced by `accessMode` and `rateUpdateCooldown` is gone, rate updates now apply immediately. The full list is in the [version history](/resources/version-history).
{% endhint %}

{% hint style="danger" %}
You must complete the [post-deployment operations](/vault/deploy-your-vault/vault-post-deployment-operations) to finalize your vault setup.
{% endhint %}

### Recommended reading

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Deposit and Withdraw flows</strong></mark></td><td><a href="/vault/deposit-and-withdraw-flows">Deposit and Redemption flows</a></td></tr><tr><td><mark style="color:$primary;"><strong>Vault valuation</strong></mark></td><td><a href="/vault/vault-valuation">Vault valuation</a></td></tr><tr><td><mark style="color:$primary;"><strong>Roles and capacities</strong></mark></td><td><a href="/vault/roles-and-capacities">Roles and capacities</a></td></tr><tr><td><mark style="color:$primary;"><strong>Fees</strong></mark></td><td><a href="/vault/fees">Fees</a></td></tr></tbody></table>


# Vault post-deployment operations

A few essential steps must be performed to enable proper funds flows.

## Underlying asset approval

To enable user withdrawals, the custodial wallet (`safe` parameter) must infinite approve the vault address to spend `underlying`. For example, if the underlying is USDC, then as the safe you should approve the Vault to spend your USDC.

Call the following function on the underlying asset contract:

```solidity
approve(address spender, uint256 value)
```

* **`spender (address)`:**\
  The deployed **vault address**. This is the address that will be allowed to move the tokens from the curation address.
* **`value (uint256)`:**\
  The approval amount. To avoid repeated approvals, you can do an infinite allowance. Use the following constant value:

  ```
  115792089237316195423570985008687907853269984665640564039457584007913129639935
  ```

{% hint style="danger" %}
Without this approval, the vault will not be able to process user withdrawals.
{% endhint %}

***

## Verify your vault on Etherscan

### Identify your vault as a proxy

Before interacting with your vault, you must confirm that it is a proxy contract.

#### Steps to verify the proxy

1. **Access Your Vault Contract**
   * Open your Vault’s contract page on the relevant block explorer (e.g., Etherscan, Arbiscan, etc..).
2. **Navigate to the Contract Tab**
   * Click on the **`Contract`** tab.
3. **Click “Is this a proxy?”**

   * Scroll to the top right of section, click on the **“Is this a proxy?”** button and then on the "**Verify**" button.

   <figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FRry46R7QsHndCyjfsS5G%2FVerify_proxy_vault_1.PNG?alt=media&amp;token=052efc6a-13a2-4f5a-9319-3ea804daca0d" alt=""><figcaption></figcaption></figure>

   <figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FFWX8m1QHWTXUlvpj7E5A%2FVerify_proxy_vault_2.PNG?alt=media&amp;token=428f8512-5ad1-49c7-a9b8-2470bc4a4c9f" alt=""><figcaption></figcaption></figure>

   <figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F0QTgq6RcU1feWPMSPBzH%2FVerify_proxy_vault_3.PNG?alt=media&amp;token=a1263c5e-4f42-451b-b640-8d24b4adde52" alt=""><figcaption></figcaption></figure>
4. **Confirm Proxy Verification**
   * If verified, the explorer will display the interaction with the proxy logic.

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Ft2rgwo5nuiDVVkA9vNIh%2FVerify_proxy_vault_4_alt.PNG?alt=media&amp;token=563a22f1-1780-4078-9044-27e5ed9c62bc" alt=""><figcaption></figcaption></figure>

Once your vault is confirmed as a proxy, you will be able to access the **Read** and **Write** functions of the deployed vault contract.


# Access your vault on Lagoon

Access and manage your vault directly on the Lagoon app.

## Manage your Vault

On your vault page, if you are connected as the Admin, Valuation Provider or Curator you will see a blue button on the right side of the header with written Manage. Click on it to be redirected to the management page.

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FKjPXojG5MXyV9sIawH92%2FScreenshot%202025-04-25%20at%2019.08.32.png?alt=media&amp;token=08df8fd2-4b7f-4270-9cc2-52eb4c27e4f5" alt=""><figcaption></figcaption></figure>

You can also reach it by going to:

`https://app.lagoon.finance/manage/<chainId>/<vaultAddress>`

This interface allows you to:

* Submit new NAV proposals (as [Valuation Provider](/vault/roles-and-capacities/valuation-oracle))
* Execute [settlements](/overview/terminology#vault-settlement) (as [Curator](/vault/roles-and-capacities/curator)).


# Lagoon Solutions

Scale your vault operations faster with dedicated valuation and technical support.

Lagoon Solutions is designed for institutional and professional clients who need more than vault infrastructure alone. It combines Lagoon’s on-chain vault rails with dedicated operational and technical support across the full lifecycle of a product.

Lagoon provides the infrastructure. Lagoon Solutions helps you put it into production with the right operating model, valuation setup, permissions, and user experience.

{% hint style="info" %}
Lagoon Solutions does not replace the curator. The curator keeps control over governance, strategy, execution, and custody. Lagoon Solutions provides the support layer needed to launch and operate a vault with institutional standards.
{% endhint %}

### What Lagoon Solutions is for

Lagoon Solutions is built for teams that want to launch and scale vaults with stronger operational support, including:

* institutional asset managers
* professional curators
* tokenized asset issuers
* protocols launching white label products
* teams with valuation, reporting, or compliance requirements
* venture capital funds

### What Lagoon Solutions covers

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Wallet onboarding and custody alignment</strong></mark></td><td>Set up the right wallet and custody architecture for their vault operations, whether through EOAs, multisigs, MPCs, or other institutional setups.</td></tr><tr><td><mark style="color:$primary;"><strong>Permissions and governance setup</strong></mark></td><td>Supports the configuration of roles, permissions, and governance processes so the vault matches the client’s operating model and internal controls.</td></tr><tr><td><mark style="color:$primary;"><strong>NAV updates and valuation logic</strong></mark></td><td>Supports valuation workflows, including share price calculation logic and NAV update processes. This is especially important for products that require custom valuation methods or off-chain inputs.</td></tr><tr><td><mark style="color:$primary;"><strong>Reporting and operational workflows</strong></mark></td><td>Reporting solutions produced for internal and external needs based on internal, jurisdictional or investor requirements.</td></tr><tr><td><mark style="color:$primary;"><strong>White label deployment</strong></mark></td><td>Custom branded interfaces and white label deployments, so clients can distribute products under their own brand.</td></tr></tbody></table>

{% hint style="info" %}
**Interested in Lagoon Solutions?**

Fill out [**this form**](https://tally.so/r/nGBGyz) by selecting "Lagoon Solutions" to learn how we can support your journey.
{% endhint %}

### How it fits with Lagoon

Lagoon vaults are flexible by design. Each curator defines their own:

* governance model, centralized or distributed
* strategy, across any asset, protocol, chain, or even CEX
* execution method, manual, algorithmic, or AI driven
* valuation approach, on-chain or off-chain, automated or discretionary

Lagoon Solutions exists to help clients implement these choices cleanly and operate them at scale.

#### Why it matters

Accurate valuation, stable operations, and clear permissions are not optional for institutional products. They are part of the product itself. Lagoon Solutions gives curators and institutions the support they need to launch faster, reduce operational burden, and keep their focus on strategy and growth.

#### What this means for clients

With Lagoon Solutions, clients can focus on running and growing their vault, while Lagoon helps with the technical and operational plumbing needed to support a professional product.


# How to?

This section provides step-by-step guides to help you operate your Lagoon Vaults.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:$primary;"><strong>Update the vault valuation &#x26; settle requests</strong></mark></td><td><a href="/vault/how-to/update-the-vault-valuation-and-settle-requests">Update the vault valuation &amp; settle requests</a></td></tr><tr><td><mark style="color:$primary;"><strong>Activate and manage a synchronous vault</strong></mark></td><td><a href="/vault/how-to/activate-and-manage-a-synchronous-vault">Activate and manage a synchronous vault</a></td></tr><tr><td><mark style="color:$primary;"><strong>Migrate an existing vault into a new Lagoon vault</strong></mark></td><td><a href="/vault/how-to/migrate-an-existing-vault-into-a-new-lagoon-vault">Migrate an existing vault into a new Lagoon vault</a></td></tr><tr><td><mark style="color:$primary;"><strong>Claim shares on behalf of users</strong></mark></td><td><a href="/vault/how-to/claim-shares-on-behalf-of-users">Claim shares on behalf of users</a></td></tr><tr><td><mark style="color:$primary;"><strong>Close a vault</strong></mark></td><td><a href="/vault/how-to/close-a-vault">Close a vault</a></td></tr><tr><td><mark style="color:$primary;"><strong>Pause a vault</strong></mark></td><td><a href="/vault/how-to/pause-a-vault">Pause a vault</a></td></tr><tr><td><mark style="color:$primary;"><strong>Request a listing on Lagoon Frontend</strong></mark></td><td><a href="/vault/how-to/request-a-listing-on-lagoon-frontend">Request a listing on Lagoon Frontend</a></td></tr></tbody></table>


# Update the vault valuation & settle requests

## The first valuation update

{% hint style="danger" %}
Before updating the valuation of a vault, please read how it works [here](/vault/vault-valuation).
{% endhint %}

If it is your first valuation update, the input value will be 0, regardless of the fact that there are pending deposit requests. If you don't understand why, please check the documentation on how the [vault valuation works](/vault/vault-valuation).

## Update the vault valuation

In Lagoon, the valuation of the vault is injected into the smart contract by the [Valuation Provider](/vault/roles-and-capacities/valuation-oracle).

For more security, it is a two-step procedure:

* First, the Valuation Provider will store a valuation proposal in the vault.
* Then, the curator can accept this valuation by calling either `settleDeposit/settleRedeem`. Note that they are not exactly equivalent; you can learn more [here](#settledeposit-vs-settleredeem).

To access the management page, please check this [tutorial](/vault/deploy-your-vault/access-your-vault-on-lagoon).

{% hint style="danger" %}
The first valuation injected must be 0. Please read how the valuation works [here](/vault/vault-valuation).
{% endhint %}

### Current vault state

On this page, you can see the current state of your vault.

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fh7cbOF7b4Hk4wyISVESW%2FScreenshot%202025-04-25%20at%2019.18.14.png?alt=media&amp;token=f62111af-7c92-40f9-802b-9e9dfc67fe4c" alt=""><figcaption><p>Current vault state</p></figcaption></figure>

#### Simulation mode & propose valuation

By touching the input bar, you will enter the simulation mode. It will display in green the new vault state if the valuation was settled.

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FNQkUAwemSdeep22oJ1aF%2FScreenshot%202025-04-25%20at%2019.23.42.png?alt=media&amp;token=d4edeef9-def4-4ccc-9157-78f4580b1ffa" alt=""><figcaption><p>Vault state with a new valuation</p></figcaption></figure>

Click `Propose new valuation` button to initiate the transaction.

### Approve valuation & settle

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FnITpvGkyXYPEEIkXZwM8%2FScreenshot%202025-04-28%20at%2014.40.03.png?alt=media&amp;token=99d6f2b3-073e-456d-9ea9-9e5cb561afb2" alt=""><figcaption><p>A vault ready to be settled by the curator</p></figcaption></figure>

After the Valuation Provider proposed the new valuation, the Curator can validate it.

Let's have a look at the information displayed.

* **Total assets and new total assets -** here we can see a valuation update from \~2,508,115 USD0++ to \~2,508,330 USD0++.
* **Calculated Fees -** Since the new valuation is lower than *Asset at the high-water mark*, no performance fees will be taken, and the high-water mark will remain unchanged. On the other hand, management fees are taken.
* **Requests** - There are \~30,460 USD0++ ready to be deposited and \~624.94 ustUSR++ (vault shares) ready to be redeemed. To redeem the shares, the vault will use the assets being deposited and those present in the curator's address. It is the case because we are going to call `settleDeposit` , it would not be the case if we called `settleRedeem` .That's why the section *Underlying to Unwind* is empty; there are enough pending deposits to settle the redemptions.
* **Settle with deposits** button - See next section.

#### SettleDeposit vs SettleRedeem

Approving the valuation passes by two possible functions: `settleDeposit` and `settleRedeem`. Here is a table enumerating each function behavior:

| Behavior                                       | settleDeposit | settleRedeem |
| ---------------------------------------------- | ------------- | ------------ |
| check for consistency in the valuation updated | ✅             | ✅            |
| take fees                                      | ✅             | ✅            |
| settle deposit requests                        | ✅             | ❌            |
| try to settle redemption requests              | ✅             | ✅            |

{% hint style="info" %}
Why does the *settleDeposit* operation try to settle redemption requests?

That is because the best moment to honor redemption requests is when there is a maximum of underlying in the curator address, it is the case after a settlement of deposits.
{% endhint %}

{% hint style="info" %}
Why do the settlement calls only **try** to settle redemptions?

In order to improve the curator's flexibility, the settlement of redemptions will only happen if there are enough assets in the curator's address. It is the curator's job to make sure it is the case.
{% endhint %}

{% hint style="info" %}
Can I update the valuation if there are no deposit/redeem requests?

Yes, you can, everything will work the same.
{% endhint %}


# Activate and manage a synchronous vault

This page will guide you through activating synchronous deposits.

{% hint style="danger" %}
Synchronicity is an **advanced feature.** Please read this page entirely before activating synchronous deposits on your vaults.
{% endhint %}

{% hint style="warning" %}
This feature is not available on Mantle.
{% endhint %}

## How do synchronous deposits work?

By giving a `lifespan` to your vault valuation, you allow the vault to process deposits.\
The amount of shares received is computed using the price per share at the last valuation update. When `syncDeposit()` is available, the `requestDeposit()` function is disabled. Redemptions continue to be processed asynchronously.

## Arbitrage and the danger of synchronous deposits

Most Lagoon Vaults rely on offchain oracles to know their valuation. Since this value is not continuously assessed, it might differ from reality with time.

For example 2 days after a valuation update, the fair valuation might have increase while it's registered value in the vault is still the same, such situation would create an arbitrage opportunity at the expense of shares holders.

We advice vault curator and administrators to be **extremely careful with this feature**.

## How to activate synchronous deposits ?

First give your totalAssets variable a lifespan. This value, expressed in seconds, determines for how long users will be able to call syncDeposits. To update it, call as the `safe` role:

```solidity
function updateTotalAssetsLifespan(uint128 lifespan) onlySafe;
```

| Variable | Definition                                                               |
| -------- | ------------------------------------------------------------------------ |
| lifespan | Duration in seconds during which the valuation will be considered valid. |

{% hint style="danger" %}
The lifespan value can't be too close to uint128.max because it might cause an overflow. If you want to allow sync deposits for an "unlimited" amount of time, you can put: `31536000000` seconds, roughly \~1000 years.
{% endhint %}

Now [update the valuation of your vault](/vault/how-to/update-the-vault-valuation-and-settle-requests) as usual. After the call to settleDeposit or settleRedeem, users will be able to do synchronous deposits.

## How to update the valuation while totalAssets is valid and how to go back to asynchronous mode ?

It is not possible to propose a new valuation while the current one is considered valid (see point above).\
To update the valuation, the `safe` role first has to call:

```solidity
function expireTotalAssets() onlySafe;
```

After this call, `isTotalAssetsValid` will return false and the `Valuation Provider` and the `safe` can follow the standard [Update the vault valuation & settle requests](/vault/how-to/update-the-vault-valuation-and-settle-requests) procedure.


# Migrate an existing vault into a new Lagoon vault

This tutorial will explain how to migrate an existing vault or fund into a Lagoon vault without needing an action from your shareholders.

Since v0.6.0, a vault can be deployed with a non-zero **Initial NAV**: the vault starts already valued at the NAV of your deprecated vault, and the matching shares are pre-minted to the curator address. The migration becomes a bookkeeping operation, there is no deposit request and no valuation trick involved.

Prerequisites:

* having the capacity to move the assets of the deprecated vault to the curator address of the future Lagoon vault.
* the deprecated vault shares should not be used in DeFi.

## Step 1: Pause the deprecated vault and take a snapshot of its shares repartition

We advise to pause the vault or at least freeze movement of shares to avoid loss of funds from your users.

In our case, here is the result of our snapshot:

<table><thead><tr><th width="249">address</th><th>amount of shares</th><th>% of the vault</th></tr></thead><tbody><tr><td>0x123</td><td>4</td><td>40%</td></tr><tr><td>0x456</td><td>6</td><td>60%</td></tr><tr><td>TOTAL</td><td>10</td><td>100%</td></tr></tbody></table>

*Concretely, the address 0x123 owns 4 shares out of the 10 total shares, which is equivalent to 40%.*

## Step 2: Compute the NAV of the deprecated vault

This is the value you will enter as the Initial NAV of the new vault, expressed in the underlying.

In our case, the deprecated vault is worth 100 USDC, so the value is `100`.

{% hint style="info" %}
The interface takes the amount as you would write it, `100` for 100 USDC. If you deploy programmatically, the `initialTotalAssets` parameter takes the raw amount instead, `100000000` for 100 USDC.
{% endhint %}

## Step 3: Create the Lagoon vault with an Initial NAV

[Follow this guide](/vault/deploy-your-vault) and set the **Initial NAV** field to the value computed at step 2. In our case, the vault address is 0xabc.

At initialization the vault sets its `totalAssets` to that value and mints the matching shares to the **curator address**, at a price per share of 1.

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fgit-blob-dca792ee8d5f56553944dcd1098e9454decf0d47%2Finitial-nav-deploy.png?alt=media" alt=""><figcaption><p>The Initial NAV field of the deployment form</p></figcaption></figure>

{% hint style="danger" %}
The Initial NAV is trusted as is: the price per share guardrails and the valuation checks only apply to the later updates. A wrong value permanently misprices every share of the vault.
{% endhint %}

{% hint style="warning" %}
No asset is transferred by this operation. The vault underlying balance stays at 0 and the curator address is expected to hold the assets, which is what step 4 is about.
{% endhint %}

## Step 4: Move the assets to the curator address

Transfer the assets of the deprecated vault to the curator address of the new vault.

They do not have to be in the underlying: the curator address can receive the positions in kind, as long as their value matches the NAV you seeded at step 3. Once the migration is done, your Valuation Provider [updates the valuation](/vault/how-to/update-the-vault-valuation-and-settle-requests) as it would for any other vault.

## Step 5: Distribute the shares to the shareholders of the previous vault

The shares are already on the curator address, you only have to distribute them. Be careful, frontend could be compromised, review the transactions carefully. We are going to use the [disperse.app](https://disperse.app) but if you are more comfortable using blockchain explorers you can enter `disperse.app` in Etherscan to find directly the smart contract to interact with.

The address of the token you want to distribute is the address of the shares which is the address of the vault. In our case, 0xabc.

We will now distribute the 100 shares held by the curator address: 40 to the address 0x123 and 60 to the address 0x456. In disperse.app frontend it will be something like this:

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FO2Z447eBreGWFM3WejsM%2FScreenshot%202025-05-19%20at%2012.21.06.png?alt=media&amp;token=c24ba835-b53f-416d-8594-609337c79ce1" alt="" width="375"><figcaption></figcaption></figure>

You can now submit and execute the transaction.

## Final notes:

* the Lagoon Vault performance metrics will start from a price per share of 1 at deployment, meaning that you will have to reconcile the deprecated vault and the vault history to have the full picture of your performance.
* the deprecated vault shares will be worth 0, meaning that you should not do a migration on a vault whose shares are used in DeFi.


# Claim shares on behalf of users

## Overview

After deposits settlements, Vault curators can claim on behalf of users the available shares in the vault.

## 2-steps procedure

### Identify the addresses concerned

You can obtain the list of addresses with a claimable deposit request using the [find-claimable-controllers](https://github.com/hopperlabsxyz/vault-computation-cli?tab=readme-ov-file#find-claimable-controllers-fcc) command in the [vault-cli-computation](https://github.com/hopperlabsxyz/vault-computation-cli) tool.

### Call claimSharesOnBehalf as curator

```solidity
function claimSharesOnBehalf(address[] memory controllers) external onlySafe;
```

To claim shares on behalf of others using the Curator role, execute the `claimSharesOnBehalf` function on Etherscan. Format the addresses as an array of strings like this:

```
["0x44ab...cb7e", "0x878e...b641"]
```


# Close a vault

### Overview

Closing a vault permanently shuts down its operations and allows users to withdraw their assets at a fixed price. The process requires coordination between the vault admin and the safe contract.

### 3-Step Closure Process

#### Step 1: Initiate Closure (Admin)

The vault admin starts the closure process:

```solidity
vault.initiateClosing();
```

**What happens:**

* Vault state changes to `Closing`
* New deposit settlements are blocked
* Users can still request deposits but they won't be processed

#### Step 2: Update NAV (Valuation Provider)

Update the vault's value before final closure:

<pre class="language-solidity"><code class="lang-solidity"><strong>vault.updateNewTotalAssets(1000000); // Current market value
</strong></code></pre>

#### Step 3: Complete Closure (Curator)

The curator address finalizes the closure:

```solidity
vault.close(1000000); // Must match the NAV from step 2
```

**What happens:**

* Updates final asset value
* Settles all pending requests
* Takes final fees
* Transfers all assets to vault contract
* Vault state changes to `Closed`
* Share price becomes fixed

### After Closure

Users can only:

* Withdraw their assets using `withdraw()` or `redeem()`
* Claim any pending settled requests
* Transfer shares

### Important Notes

⚠️ **Permanent action** - Cannot be reversed

⚠️ **NAV matching** - The value in step 3 must match step 2

⚠️ **Asset requirements** - The curator address must have enough assets for all withdrawals

### Role Requirements

| Step | Who Can Execute   | Function                 |
| ---- | ----------------- | ------------------------ |
| 1    | Vault Admin       | `initiateClosing()`      |
| 2    | Valuation Manager | `updateNewTotalAssets()` |
| 3    | Curator           | `close()`                |

### Events Emitted

```solidity
event StateUpdated(State.Closing);    // Step 1
event NewTotalAssetsUpdated(uint256); // Step 2
event TotalAssetsUpdated(uint256);    // Step 3
event StateUpdated(State.Closed);     // Step 3
```


# Pause a vault

## Overview

The `pause()` function halts all core operations of the vault and can only be executed by the vault `admin`. This is a critical administrative function used for emergency situations or maintenance periods.

## Function signature

```solidity
function pause() public onlyOwner
```

## Operations affected

The following core operations are halted when the vault is paused:

* **All request types** - Any pending or new requests are blocked, including:
  * `requestDeposit()`
  * `requestRedeem()`
  * `syncDeposit()`
  * `claimSharesAndRequestRedeem()`
  * `cancelRequestDeposit()`
  * `withdraw()`
  * `redeem()`
  * `deposit()`
  * `mint()`
* **Settlement operations** - Both deposit and redeem settlements are halted as well as closing operations, including:
  * `settleDeposit()`
  * `settleRedeem()`
  * `initiateClosing()`
  * `close()`
* **NAV proposals** - The NAV update proposal functionality is disabled, including:
  * `updateNewTotalAssets()`
* **Share transfers** - The `_update()` function is paused resulting in all transfers of shares being blocked
* **Operator operations** - The `setOperator()` function is disabled

## Usage example

```solidity
// Only the owner can call this function
vault.pause();
```

You can also call pause from etherscan or any other Ethereum client that allows contract interaction

## Events

This function emits a `Paused` event:

```solidity
event Paused(address account);
```

## Security considerations

* ⚠️ **Emergency use**: Should only be used in emergency situations or planned maintenance
* ⚠️ **User impact**: All user operations will be blocked until `unpause()` is called

## Related functions

* `unpause()` - Resumes vault operations
* `paused()` - Checks if the vault is currently paused

## Error conditions

* Reverts if called by any address other than the owner


# Request a listing on Lagoon Frontend

To request the listing of your vault on Lagoon’s front end, simply complete the following form:

[Lagoon Vault Listing Request](https://tally.so/r/n9e6yE)

Ensure the information provided is accurate and detailed to help our team review your application efficiently.

After submitting, the Lagoon team will review your request. We reserve the right to approve or deny any listing at our discretion to uphold the quality and security of our ecosystem.

Our decision will be sent to you via Telegram following the review process.


# Safe & Zodiac Roles Modifier

A [Safe {Wallet}](https://safe.global/) is a smart wallet based on a multi-signature technology.

The [Zodiac Roles Modifier](https://docs.roles.gnosisguild.org/) is an on-chain permissions module for [Safe {Wallet}](https://safe.global/). It allows customizable roles to have specific permissions.

Permissions concern the capacity of interacting with a smart contract address, functions and which arguments can be put in the call.

<table data-view="cards"><thead><tr><th></th></tr></thead><tbody><tr><td><a data-mention href="/curation-solutions/how-to/renounce-safe-and-zodiac-role-modifier-ownership">Renounce Safe &amp; Zodiac role modifier ownership</a></td></tr></tbody></table>


# MPC (Multi-Party Computation) wallet

An **MPC (Multi-Party Computation) wallet** is a technology where a **private key is split into multiple shares** distributed among different parties. Instead of a single private key controlling an **Externally Owned Account (EOA)**, the key is generated and managed through **secure multi-party computation protocols**.

* **Threshold Signing (n/m):**
  * The wallet can require **n out of m** key shares to collaboratively sign a transaction (e.g., 2-of-3).
  * No single party ever has full access to the complete private key.
* **Off-Chain Governance (vs. Smart Contract Wallets):**
  * Unlike **smart contract wallets** (like Safe, Argent), which enforce rules (e.g., multi-sig) **on-chain**, MPC wallets handle key management **off-chain** via cryptographic protocols.
  * Governance (e.g., changing signers, threshold) is managed through the MPC protocol rather than blockchain transactions.


# How to?

This section provides step-by-step guides to help you configure your Lagoon Vaults.


# Renounce Safe & Zodiac role modifier ownership

Since your Zodiac role modifier's owner is most likely your Safe, we would advise to start renouncing the Zodiac role modifier first.

## Zodiac role modifier

The Zodiac role modifier is based on [Openzeppelin' Ownable contract](https://docs.openzeppelin.com/contracts/5.x/access-control#ownership-and-ownable). Thus you can give-up its ownership by calling `renounceOwnership` as the owner. For now we would advise to do it on etherscan at the address of the Role Modifier.

{% hint style="info" %}
You can easily connect as a Safe in Rabby by adding an address as an *Institutional Wallet.*
{% endhint %}

## Safe

Safe doesn't natively allows to renounce ownership. It is still possible to do it by:

* putting the threshold to 1 out of m signers.
* adding a signer whose address is obviously not under your control. For easily look up and audit, we advice to use: `0xdEADBEeF00000000000000000000000000000000`
* Remove all owners except the `0xdEADBEeF` address, leading to a 1 out 1 configuration.

{% hint style="warning" %}
Renouncing ownership is effective only if external auditors can easily assess it. That's why we advise to use the `0xdEADBEeF` address.
{% endhint %}


# How to setup Safe & Zodiac Roles Modifier

## **Safe**

You can deploy a Safe using the [Safe{Wallet}](https://app.safe.global/) user interface. This is the most straightforward approach to setting up new custody for your vault.

Another option is to deploy new Safe wallets using the [Safe CLI](https://docs.safe.global/advanced/cli-demos), which is useful if you plan to automate your vault deployment pipeline.

{% embed url="<https://vimeo.com/1083954125/c4e40e9ce3>" %}

{% embed url="<https://vimeo.com/1083954155/c71b069a63>" %}

## Zodiac Roles Modifier

The [Zodiac Roles Modifier](https://docs.roles.gnosisguild.org/) is an on-chain permissions module for [Safe {Wallet}](https://safe.global/). It enables customizable roles with specific permissions. These permissions define the ability to interact with specific smart contract addresses, functions, and allowed arguments. For example, a permission could specify that the Roles Modifier is only allowed to execute a transfer of up to 50 gwei of an ERC-20 token to a specific address.

The most straightforward way to add a Roles Modifier module to your Safe is through the "Apps" section of the Safe web app. Using this method, the default owner of the Roles Modifier will be the Safe itself. The owner is responsible for managing permissions and assigning role members. If you require a more complex setup, you can transfer ownership to another address.

{% embed url="<https://vimeo.com/1083954183/aa5e19e1ab>" %}

{% embed url="<https://vimeo.com/1083954209/2881b88dcb>" %}

## Sending Transactions

There are two main ways a Safe wallet can send transaction to the outside world.

\
First, through the configured multi-sig. It's an N-out-of-M signature scheme that only allows a transaction to be sent if the predefined threshold is reached.

The other way is through a [Safe module](https://docs.safe.global/advanced/smart-account-concepts) (such as the Zodiac Roles Modifier).

Both methods are natively supported in the official Safe web app. Depending on the signer you are connected with, it will automatically suggest the appropriate route.\
\
Another, more scalable, approach is to use [Zodiac Pilot](https://www.zodiac.wiki/documentation/pilot-extension):

> Zodiac Pilot is a browser-based tool for Safe accounts that lets owners and trusted delegates build and execute multi-step transactions across multiple dapps. It combines modular batching, [programmable permissions](https://www.zodiac.wiki/documentation/roles-modifier), and a built-in sandbox environment to simulate transactions before they’re sent onchain.

## DeFi-Kit Support

The [Karpatkey's DeFi-Kit](https://github.com/karpatkey/defi-kit), is a collection of permissions build for specific protocol. It can helps you getting quickly started for supported protocols.


# Key Data Structures and Epoch mechanism

## EpochData

```solidity
/// @dev Holds data for a specific epoch.
/// @param settleId Unique identifier for the related settlement data.
/// @param depositRequest Records deposit requests by address.
/// @param redeemRequest Records redeem requests by address.
struct EpochData {
    uint40 settleId;
    mapping(address => uint256) depositRequest;
    mapping(address => uint256) redeemRequest;
}
```

## SettleData

```solidity
/// @dev Holds settlement data for the vault.
/// @param totalSupply Total number of shares for this settlement.
/// @param totalAssets Total value of assets managed by the vault for this settlement.
struct SettleData {
    uint256 totalSupply;
    uint256 totalAssets;
}
```

```solidity
mapping(uint40 epochId => EpochData) epochs;
mapping(uint40 settleId => SettleData) settles;
```

## Guide to Epoch Data and Settlement in Vaults

How **EpochData** and **SettleData** are managed within a vault, particularly during the valuation and total asset update processes.

### **Overview of Epoch Data and Settle Data**

Each **Epoch Data** corresponds to a proposed **total assets** update, which is made by the **valuation manager**. Every time a new valuation is proposed for the vault, a new **Epoch Data** is created. This data holds details about all users' deposits and redemption requests and includes a reference to **Settle Data**.

The S**ettle Data** is updated by the **asset manager** of the vault, who is responsible for finalizing the total assets of the vault after the valuation process.

**Example: Understanding Epochs and Settlement**

To clarify how this process works, let's examine the following scenario:

* We have **two Epoch Data instances**: Epoch 1 and Epoch 3.
* Both are pointing to **Settle Data 1**, which is not yet finalized (or "settled"). Therefore, the total assets in **Settle Data 1** are still undefined and await confirmation from the asset manager.
* The **current epoch** is Epoch 5, which has not yet been associated with any settle data. This is the epoch where users are actively depositing.

<figure><img src="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/fYeZKqS8H1oEokjxyiTB/After(2).png" alt=""><figcaption></figcaption></figure>

### **Where should Epoch Data 5 point?**

The challenge is determining when and to which settle data the current Epoch Data (Epoch 5) should point. The decision hinges on the next settlement event or total assets update. There are two potential scenarios:

<figure><img src="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/Fm00oPi0nPy0Ac1zISt6/Before(1).png" alt=""><figcaption></figcaption></figure>

### Scenario 1: Settlement Occurs Before a New Total Assets Update

In this scenario, the vault is settled before a new total assets valuation is proposed.

* Once the settlement is completed, Epoch 5 can point to **Settle Data 3** (instead of Settle Data 1), ensuring fairness.
* This is crucial because we don't want users depositing in Epoch 5 to benefit from the same valuation as those in Epoch 1 and Epoch 3, who are already aware of the valuation they will be settled at.
* After the settlement, **Settle Data 1** is finalized at the last proposed valuation, which, for this example, was **100 assets for 100 shares**.

***

<figure><img src="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/x9izIZMD5zDkMcJKYgMm/After(1).png" alt=""><figcaption></figcaption></figure>

### Scenario 2: Settlement Occurs After a New Total Assets Update

In this alternative scenario, a new valuation is proposed before the vault is settled.

* In this case, Epoch 5 can point to **Settle Data 1**, just as the previous epochs (Epoch 1 and Epoch 3) did.
* Afterward, the asset manager proceeds to settle the vault, enforcing the newly proposed valuation. For this example, the valuation is set at **90 assets for 100 shares**.


# Smart Contract Reference

Every external/public entry point on the v0.6.0 vault implementation, grouped by caller.

Full ABI reference for the v0.6.0 vault implementation, grouped by who can call each function. Inherited OpenZeppelin ERC20 functions (`balanceOf`, `totalSupply`, `approve`, `allowance`, `name`, `symbol`) are not repeated unless the vault overrides their behaviour. `transfer` and `transferFrom` are listed because v0.6.0 adds extra access checks on both sides.

The raw ABI JSON for every implementation version is on the [Vault ABIs](/developer-hub/vault-abis) page.

## Jump to a role

* [Anyone (user-facing)](#anyone-user-facing) — deposit / redeem / sync flows, operators, views, ERC20 overrides.
* [Curator](#curator) — settlement, claim-on-behalf, sync mode, HWM, close.
* [Valuation Manager](#valuation-manager) — propose new total assets (gated by guardrails).
* [Security Council](#security-council) — emergency valuation, guardrails policy.
* [Access Manager](#access-manager-former-whitelist-manager) — whitelist / blacklist / external sanctions list.
* [Owner (Admin)](#owner-admin) — lifecycle, roles, access mode, fees, metadata.
* [Super Operator](#super-operator) — global operator that bypasses whitelist / blacklist.
* [GuardRailsManager](#guardrailsmanager-read) — compliance check used by the vault.
* [Silo](#silo-separate-contract) — pending-funds helper contract.

***

## Anyone (user-facing)

### Deposit flow (async)

#### requestDeposit

```solidity
function requestDeposit(
    uint256 assets,
    address controller,
    address owner
) public payable returns (uint256 requestId);
```

Submit assets to the pending silo, queued for the next settlement. Auto-claims any previously claimable amount for `controller`. The caller must be the `owner` or an approved operator of `owner`.

**Parameters:**

| Name         | Type      | Description                                                                                       |
| ------------ | --------- | ------------------------------------------------------------------------------------------------- |
| `assets`     | `uint256` | Amount of underlying assets to deposit.                                                           |
| `controller` | `address` | Address that will own the request and claim the resulting shares.                                 |
| `owner`      | `address` | Address whose assets are pulled. Must equal `msg.sender` or have approved the caller as operator. |

**Return values:**

| Name        | Type      | Description                     |
| ----------- | --------- | ------------------------------- |
| `requestId` | `uint256` | Epoch-based request identifier. |

***

#### requestDeposit (with referral)

```solidity
function requestDeposit(
    uint256 assets,
    address controller,
    address owner,
    address referral
) public payable returns (uint256 requestId);
```

Same as `requestDeposit` above, but emits a `Referral` event tagging `referral`.

**Parameters:**

| Name         | Type      | Description                                                       |
| ------------ | --------- | ----------------------------------------------------------------- |
| `assets`     | `uint256` | Amount of underlying assets to deposit.                           |
| `controller` | `address` | Address that will own the request and claim the resulting shares. |
| `owner`      | `address` | Address whose assets are pulled.                                  |
| `referral`   | `address` | Address logged as the referrer.                                   |

**Return values:**

| Name        | Type      | Description                     |
| ----------- | --------- | ------------------------------- |
| `requestId` | `uint256` | Epoch-based request identifier. |

***

#### cancelRequestDeposit

```solidity
function cancelRequestDeposit() external;
```

Pull pending assets back from the silo. Only valid in the same epoch as the request. Cancels the caller's own pending deposit.

***

#### cancelRequestDeposit (on behalf)

```solidity
function cancelRequestDeposit(address controller) external;
```

Cancel a pending deposit on behalf of another controller. The caller must be an operator or super operator of `controller`. *(Operator variant new in v0.6.0.)*

**Parameters:**

| Name         | Type      | Description                                          |
| ------------ | --------- | ---------------------------------------------------- |
| `controller` | `address` | Controller whose pending deposit is being cancelled. |

***

#### deposit

```solidity
function deposit(
    uint256 assets,
    address receiver
) public returns (uint256 shares);
```

Claim shares after settlement. Uses `msg.sender` as the request controller.

**Parameters:**

| Name       | Type      | Description                               |
| ---------- | --------- | ----------------------------------------- |
| `assets`   | `uint256` | Amount of assets to claim shares against. |
| `receiver` | `address` | Address receiving the shares.             |

**Return values:**

| Name     | Type      | Description                  |
| -------- | --------- | ---------------------------- |
| `shares` | `uint256` | Shares minted to `receiver`. |

***

#### deposit (with controller)

```solidity
function deposit(
    uint256 assets,
    address receiver,
    address controller
) external returns (uint256 shares);
```

Claim shares from a settled request owned by `controller`. The caller must be an operator or super operator of `controller`.

**Parameters:**

| Name         | Type      | Description                               |
| ------------ | --------- | ----------------------------------------- |
| `assets`     | `uint256` | Amount of assets to claim shares against. |
| `receiver`   | `address` | Address receiving the shares.             |
| `controller` | `address` | Controller that owns the deposit request. |

**Return values:**

| Name     | Type      | Description                  |
| -------- | --------- | ---------------------------- |
| `shares` | `uint256` | Shares minted to `receiver`. |

***

#### mint

```solidity
function mint(
    uint256 shares,
    address receiver
) public returns (uint256 assets);
```

Same as `deposit` but the caller specifies the share amount instead of the asset amount.

**Parameters:**

| Name       | Type      | Description                   |
| ---------- | --------- | ----------------------------- |
| `shares`   | `uint256` | Shares to claim.              |
| `receiver` | `address` | Address receiving the shares. |

**Return values:**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `assets` | `uint256` | Assets consumed from the claimable balance. |

***

#### mint (with controller)

```solidity
function mint(
    uint256 shares,
    address receiver,
    address controller
) external returns (uint256 assets);
```

Same as `mint` above, on behalf of `controller`. The caller must be an operator or super operator of `controller`.

**Parameters:**

| Name         | Type      | Description                               |
| ------------ | --------- | ----------------------------------------- |
| `shares`     | `uint256` | Shares to claim.                          |
| `receiver`   | `address` | Address receiving the shares.             |
| `controller` | `address` | Controller that owns the deposit request. |

**Return values:**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `assets` | `uint256` | Assets consumed from the claimable balance. |

***

### Deposit flow (sync, when `SyncMode` allows)

#### syncDeposit

```solidity
function syncDeposit(
    uint256 assets,
    address receiver,
    address referral
) public payable returns (uint256 shares);
```

Atomic deposit — mints shares immediately at the current price per share. Reverts if the vault is async-only or if sync deposits are disabled by the current `SyncMode`.

**Parameters:**

| Name       | Type      | Description                                                 |
| ---------- | --------- | ----------------------------------------------------------- |
| `assets`   | `uint256` | Amount of underlying assets to deposit.                     |
| `receiver` | `address` | Address receiving the shares.                               |
| `referral` | `address` | Address logged as the referrer (use `address(0)` for none). |

**Return values:**

| Name     | Type      | Description                                                |
| -------- | --------- | ---------------------------------------------------------- |
| `shares` | `uint256` | Shares minted at the current valuation, net of entry fees. |

***

### Redeem flow (async)

#### requestRedeem

```solidity
function requestRedeem(
    uint256 shares,
    address controller,
    address owner
) public returns (uint256 requestId);
```

Transfer shares to the pending silo, queued for the next redeem settlement.

**Parameters:**

| Name         | Type      | Description                                                                                       |
| ------------ | --------- | ------------------------------------------------------------------------------------------------- |
| `shares`     | `uint256` | Number of shares to redeem.                                                                       |
| `controller` | `address` | Address that will own the request and claim the resulting assets.                                 |
| `owner`      | `address` | Address whose shares are pulled. Must equal `msg.sender` or have approved the caller as operator. |

**Return values:**

| Name        | Type      | Description                     |
| ----------- | --------- | ------------------------------- |
| `requestId` | `uint256` | Epoch-based request identifier. |

***

#### cancelRequestRedeem

```solidity
function cancelRequestRedeem(address controller) external;
```

Pull pending shares back from the silo. The caller must be an operator or super operator of `controller`. *(New in v0.6.0.)*

**Parameters:**

| Name         | Type      | Description                                         |
| ------------ | --------- | --------------------------------------------------- |
| `controller` | `address` | Controller whose pending redeem is being cancelled. |

***

#### claimSharesAndRequestRedeem

```solidity
function claimSharesAndRequestRedeem(
    uint256 sharesToRedeem
) public returns (uint40 requestId);
```

UX bundle: claim any pending deposit shares first, then immediately request a redeem for them. If there is nothing claimable, behaves like `requestRedeem`.

**Parameters:**

| Name             | Type      | Description                                |
| ---------------- | --------- | ------------------------------------------ |
| `sharesToRedeem` | `uint256` | Number of shares to redeem after claiming. |

**Return values:**

| Name        | Type     | Description                                               |
| ----------- | -------- | --------------------------------------------------------- |
| `requestId` | `uint40` | Epoch-based request identifier of the new redeem request. |

***

#### redeem

```solidity
function redeem(
    uint256 shares,
    address receiver,
    address controller
) public returns (uint256 assets);
```

Claim assets after redeem settlement (or in sync if the vault is closed). When called by an operator or super operator of `controller`, the operator check is bypassed appropriately.

**Parameters:**

| Name         | Type      | Description                                                                     |
| ------------ | --------- | ------------------------------------------------------------------------------- |
| `shares`     | `uint256` | Shares to convert into assets.                                                  |
| `receiver`   | `address` | Address receiving the assets.                                                   |
| `controller` | `address` | Controller that owns the redeem request (or share balance, if vault is closed). |

**Return values:**

| Name     | Type      | Description                       |
| -------- | --------- | --------------------------------- |
| `assets` | `uint256` | Assets transferred to `receiver`. |

***

#### withdraw

```solidity
function withdraw(
    uint256 assets,
    address receiver,
    address controller
) public returns (uint256 shares);
```

Same as `redeem` but specified by asset amount.

**Parameters:**

| Name         | Type      | Description                                                                     |
| ------------ | --------- | ------------------------------------------------------------------------------- |
| `assets`     | `uint256` | Amount of assets to withdraw.                                                   |
| `receiver`   | `address` | Address receiving the assets.                                                   |
| `controller` | `address` | Controller that owns the redeem request (or share balance, if vault is closed). |

**Return values:**

| Name     | Type      | Description    |
| -------- | --------- | -------------- |
| `shares` | `uint256` | Shares burned. |

***

### Redeem flow (sync, when `SyncMode` allows)

#### syncRedeem

```solidity
function syncRedeem(
    uint256 shares,
    address receiver,
    uint256 minimumAssets
) public returns (uint256 assets);
```

Atomic redeem with slippage protection. Burns shares immediately and pays assets directly from the Curator address.

**Parameters:**

| Name            | Type      | Description                                                                                |
| --------------- | --------- | ------------------------------------------------------------------------------------------ |
| `shares`        | `uint256` | Shares to redeem.                                                                          |
| `receiver`      | `address` | Address receiving the assets.                                                              |
| `minimumAssets` | `uint256` | Minimum assets expected after exit fee and haircut. Reverts if the actual output is lower. |

**Return values:**

| Name     | Type      | Description                                                    |
| -------- | --------- | -------------------------------------------------------------- |
| `assets` | `uint256` | Assets transferred to `receiver`, net of exit fee and haircut. |

***

### Operators

#### setOperator

```solidity
function setOperator(
    address operator,
    bool approved
) external returns (bool success);
```

Authorize or revoke an operator that can request and claim on the caller's behalf.

**Parameters:**

| Name       | Type      | Description                           |
| ---------- | --------- | ------------------------------------- |
| `operator` | `address` | Operator address.                     |
| `approved` | `bool`    | `true` to approve, `false` to revoke. |

**Return values:**

| Name      | Type   | Description    |
| --------- | ------ | -------------- |
| `success` | `bool` | Always `true`. |

***

### ERC20 (with extra access checks)

In v0.6.0 the vault overrides `transfer` and `transferFrom` to enforce the `isAllowed` check on both sender and recipient.

#### transfer

```solidity
function transfer(
    address to,
    uint256 value
) public returns (bool);
```

Standard ERC20 transfer, plus an `isAllowed(msg.sender)` and `isAllowed(to)` check.

**Parameters:**

| Name    | Type      | Description                       |
| ------- | --------- | --------------------------------- |
| `to`    | `address` | Recipient. Must pass `isAllowed`. |
| `value` | `uint256` | Amount of shares to transfer.     |

**Return values:**

| Name      | Type   | Description               |
| --------- | ------ | ------------------------- |
| (unnamed) | `bool` | Always `true` on success. |

***

#### transferFrom

```solidity
function transferFrom(
    address from,
    address to,
    uint256 value
) public returns (bool);
```

Standard ERC20 `transferFrom`, plus an `isAllowed(from)` and `isAllowed(to)` check.

**Parameters:**

| Name    | Type      | Description                       |
| ------- | --------- | --------------------------------- |
| `from`  | `address` | Sender. Must pass `isAllowed`.    |
| `to`    | `address` | Recipient. Must pass `isAllowed`. |
| `value` | `uint256` | Amount of shares to transfer.     |

**Return values:**

| Name      | Type   | Description               |
| --------- | ------ | ------------------------- |
| (unnamed) | `bool` | Always `true` on success. |

***

### Views

#### totalAssets

```solidity
function totalAssets() public view returns (uint256);
```

Total assets currently managed by the vault, as last committed by the Curator at settlement.

**Return values:**

| Name      | Type      | Description                       |
| --------- | --------- | --------------------------------- |
| (unnamed) | `uint256` | Total assets in underlying units. |

***

#### decimals

```solidity
function decimals() public view returns (uint8);
```

ERC20 decimals — matches the underlying asset's decimals plus the vault's decimal offset.

**Return values:**

| Name      | Type    | Description                        |
| --------- | ------- | ---------------------------------- |
| (unnamed) | `uint8` | Decimals of the vault share token. |

***

#### version

```solidity
function version() public pure returns (string memory);
```

Implementation version string.

**Return values:**

| Name      | Type     | Description |
| --------- | -------- | ----------- |
| (unnamed) | `string` | `"v0.6.0"`. |

***

#### safe

```solidity
function safe() public view returns (address);
```

Address bound to the Curator role — vault assets flow into this address at settlement, and out of it on redeems. Named `safe` in the source code by convention; can be any address.

**Return values:**

| Name      | Type      | Description          |
| --------- | --------- | -------------------- |
| (unnamed) | `address` | The Curator address. |

***

#### share

```solidity
function share() external view returns (address);
```

ERC-7575 share token address — always returns `address(this)` for this vault.

**Return values:**

| Name      | Type      | Description                         |
| --------- | --------- | ----------------------------------- |
| (unnamed) | `address` | The share token (the vault itself). |

***

#### supportsInterface

```solidity
function supportsInterface(bytes4 interfaceId) public view returns (bool);
```

ERC-165 interface support check.

**Parameters:**

| Name          | Type     | Description           |
| ------------- | -------- | --------------------- |
| `interfaceId` | `bytes4` | Interface identifier. |

**Return values:**

| Name      | Type   | Description                           |
| --------- | ------ | ------------------------------------- |
| (unnamed) | `bool` | `true` if the interface is supported. |

***

#### maxDeposit

```solidity
function maxDeposit(address controller) public view returns (uint256);
```

Maximum assets `controller` can claim through `deposit`. Zero when paused.

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name      | Type      | Description               |
| --------- | --------- | ------------------------- |
| (unnamed) | `uint256` | Maximum claimable assets. |

***

#### maxMint

```solidity
function maxMint(address controller) public view returns (uint256);
```

Maximum shares `controller` can mint by claiming a settled deposit request.

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name      | Type      | Description               |
| --------- | --------- | ------------------------- |
| (unnamed) | `uint256` | Maximum claimable shares. |

***

#### maxRedeem

```solidity
function maxRedeem(address controller) public view returns (uint256);
```

Maximum redeemable shares for `controller`. When the vault is closed and nothing is claimable, returns the share balance instead (sync redeem path).

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name     | Type      | Description                |
| -------- | --------- | -------------------------- |
| `shares` | `uint256` | Maximum redeemable shares. |

***

#### maxWithdraw

```solidity
function maxWithdraw(address controller) public view returns (uint256 assets);
```

Asset-denominated counterpart of `maxRedeem`.

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name     | Type      | Description                  |
| -------- | --------- | ---------------------------- |
| `assets` | `uint256` | Maximum withdrawable assets. |

***

#### previewSyncDeposit

```solidity
function previewSyncDeposit(uint256 assets) public view returns (uint256 shares);
```

Shares a depositor would receive for `assets` via `syncDeposit`, net of entry fee.

**Parameters:**

| Name     | Type      | Description        |
| -------- | --------- | ------------------ |
| `assets` | `uint256` | Assets to deposit. |

**Return values:**

| Name     | Type      | Description                   |
| -------- | --------- | ----------------------------- |
| `shares` | `uint256` | Shares the caller would mint. |

***

#### previewSyncRedeem

```solidity
function previewSyncRedeem(uint256 shares) public view returns (uint256 assets);
```

Assets a redeemer would receive for `shares` via `syncRedeem`, net of exit fee and haircut.

**Parameters:**

| Name     | Type      | Description       |
| -------- | --------- | ----------------- |
| `shares` | `uint256` | Shares to redeem. |

**Return values:**

| Name     | Type      | Description                      |
| -------- | --------- | -------------------------------- |
| `assets` | `uint256` | Assets the caller would receive. |

***

#### previewDeposit / previewMint / previewRedeem / previewWithdraw

```solidity
function previewDeposit(uint256) public pure returns (uint256);
function previewMint(uint256) public pure returns (uint256);
function previewRedeem(uint256) public pure returns (uint256);
function previewWithdraw(uint256) public pure returns (uint256);
```

**All four revert.** ERC-7540 mandates that synchronous previews are disabled for asynchronous flows. Use `convertToShares` / `convertToAssets` with a specific `requestId` for settled epochs, or `previewSyncDeposit` / `previewSyncRedeem` for the sync flow.

***

#### convertToShares

```solidity
function convertToShares(
    uint256 assets,
    uint256 requestId
) public view returns (uint256);
```

Assets → shares conversion at the settlement price of `requestId`'s epoch.

**Parameters:**

| Name        | Type      | Description                                       |
| ----------- | --------- | ------------------------------------------------- |
| `assets`    | `uint256` | Assets to convert.                                |
| `requestId` | `uint256` | Request / epoch ID whose settlement price to use. |

**Return values:**

| Name      | Type      | Description                              |
| --------- | --------- | ---------------------------------------- |
| (unnamed) | `uint256` | Equivalent shares at that epoch's price. |

***

#### convertToAssets

```solidity
function convertToAssets(
    uint256 shares,
    uint256 requestId
) public view returns (uint256);
```

Shares → assets conversion at the settlement price of `requestId`'s epoch.

**Parameters:**

| Name        | Type      | Description                                       |
| ----------- | --------- | ------------------------------------------------- |
| `shares`    | `uint256` | Shares to convert.                                |
| `requestId` | `uint256` | Request / epoch ID whose settlement price to use. |

**Return values:**

| Name      | Type      | Description                              |
| --------- | --------- | ---------------------------------------- |
| (unnamed) | `uint256` | Equivalent assets at that epoch's price. |

***

#### pendingDepositRequest

```solidity
function pendingDepositRequest(
    uint256 requestId,
    address controller
) public view returns (uint256 assets);
```

Assets currently waiting to be settled for `controller` at `requestId`.

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `requestId`  | `uint256` | Request / epoch ID.  |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name     | Type      | Description     |
| -------- | --------- | --------------- |
| `assets` | `uint256` | Pending assets. |

***

#### claimableDepositRequest

```solidity
function claimableDepositRequest(
    uint256 requestId,
    address controller
) public view returns (uint256 assets);
```

Assets at `requestId` that have been settled and are now claimable by `controller`.

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `requestId`  | `uint256` | Request / epoch ID.  |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name     | Type      | Description       |
| -------- | --------- | ----------------- |
| `assets` | `uint256` | Claimable assets. |

***

#### pendingRedeemRequest

```solidity
function pendingRedeemRequest(
    uint256 requestId,
    address controller
) public view returns (uint256 shares);
```

Shares currently waiting to be settled for `controller` at `requestId`.

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `requestId`  | `uint256` | Request / epoch ID.  |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name     | Type      | Description     |
| -------- | --------- | --------------- |
| `shares` | `uint256` | Pending shares. |

***

#### claimableRedeemRequest

```solidity
function claimableRedeemRequest(
    uint256 requestId,
    address controller
) public view returns (uint256 shares);
```

Shares at `requestId` that have been settled and whose assets are now claimable.

**Parameters:**

| Name         | Type      | Description          |
| ------------ | --------- | -------------------- |
| `requestId`  | `uint256` | Request / epoch ID.  |
| `controller` | `address` | Controller to check. |

**Return values:**

| Name     | Type      | Description       |
| -------- | --------- | ----------------- |
| `shares` | `uint256` | Claimable shares. |

***

#### isOperator

```solidity
function isOperator(
    address controller,
    address operator
) public view returns (bool);
```

Returns `true` if `operator` is approved by `controller` via `setOperator`.

**Parameters:**

| Name         | Type      | Description        |
| ------------ | --------- | ------------------ |
| `controller` | `address` | Controller.        |
| `operator`   | `address` | Operator to check. |

**Return values:**

| Name      | Type   | Description         |
| --------- | ------ | ------------------- |
| (unnamed) | `bool` | `true` if approved. |

***

#### isAllowed

```solidity
function isAllowed(address account) public view returns (bool);
```

Composite access check — passes the current access mode (whitelist or blacklist) and the external sanctions list, if configured.

**Parameters:**

| Name      | Type      | Description       |
| --------- | --------- | ----------------- |
| `account` | `address` | Address to check. |

**Return values:**

| Name      | Type   | Description                                        |
| --------- | ------ | -------------------------------------------------- |
| (unnamed) | `bool` | `true` if the account can interact with the vault. |

***

#### isTotalAssetsValid

```solidity
function isTotalAssetsValid() public view returns (bool);
```

Returns `true` while the currently posted valuation is still within its `totalAssetsLifespan`. Sync operations require this to be `true`.

**Return values:**

| Name      | Type   | Description                             |
| --------- | ------ | --------------------------------------- |
| (unnamed) | `bool` | `true` if the valuation is still valid. |

***

#### syncMode

```solidity
function syncMode() public view returns (SyncMode);
```

Returns the current sync configuration.

```solidity
enum SyncMode { Both, SyncDeposit, SyncRedeem, None }
```

**Return values:**

| Name      | Type       | Description   |
| --------- | ---------- | ------------- |
| (unnamed) | `SyncMode` | Current mode. |

***

#### isAsyncOnly

```solidity
function isAsyncOnly() public view returns (bool);
```

Returns `true` if `activateAsyncOnly` has been called — the vault has irreversibly given up sync capability. When `true`, `totalAssets` is always treated as invalid.

**Return values:**

| Name      | Type   | Description                                    |
| --------- | ------ | ---------------------------------------------- |
| (unnamed) | `bool` | `true` if the vault is permanently async-only. |

***

#### maxCap

```solidity
function maxCap() external view returns (uint256);
```

Returns the per-vault total-assets cap.

**Return values:**

| Name      | Type      | Description                        |
| --------- | --------- | ---------------------------------- |
| (unnamed) | `uint256` | Max cap in underlying asset units. |

***

#### feeRates

```solidity
function feeRates() public view returns (Rates memory);
```

Returns the current fee rates struct.

```solidity
struct Rates {
    uint16 managementRate;
    uint16 performanceRate;
    uint16 entryRate;     // new in v0.6.0
    uint16 exitRate;      // new in v0.6.0
    uint16 haircutRate;   // new in v0.6.0
}
```

All rates are in basis points. The protocol cut is read separately from the `FeeRegistry`.

**Return values:**

| Name      | Type    | Description                                                      |
| --------- | ------- | ---------------------------------------------------------------- |
| (unnamed) | `Rates` | Current management / performance / entry / exit / haircut rates. |

***

## Curator

The Curator role is bound to a single on-chain address — referred to as the `safe` in the source code (hence the `onlySafe` modifier and the `safe()` view function). The name reflects the common deployment pattern of using a Gnosis-Safe multi-sig, but **no Safe-specific behaviour is enforced**: any address can hold the role, including an EOA, an MPC wallet, or a custom contract. The Curator manages strategy allocation, executes settlements, and toggles operational parameters like the sync mode and the max cap.

#### settleDeposit

```solidity
function settleDeposit(uint256 _newTotalAssets) public;
```

Commit a valuation, take fees, mint shares to the silo, and pull silo assets into the Curator address. Opportunistically also calls `settleRedeem` when possible.

**Parameters:**

| Name              | Type      | Description                                                                                                                              |
| ----------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `_newTotalAssets` | `uint256` | Confirmed total assets at the moment of settlement. Must equal the value previously posted by the valuation manager or security council. |

***

#### settleRedeem

```solidity
function settleRedeem(uint256 _newTotalAssets) public;
```

Commit a valuation, take fees, burn pending shares from the silo, and pull assets from the Curator address to the vault for claim.

**Parameters:**

| Name              | Type      | Description                                         |
| ----------------- | --------- | --------------------------------------------------- |
| `_newTotalAssets` | `uint256` | Confirmed total assets at the moment of settlement. |

***

#### claimSharesOnBehalf

```solidity
function claimSharesOnBehalf(address[] memory controllers) external;
```

UX helper — push claimable deposit shares to a list of controllers.

**Parameters:**

| Name          | Type        | Description                                                               |
| ------------- | ----------- | ------------------------------------------------------------------------- |
| `controllers` | `address[]` | Controllers to claim for. Controllers with nothing claimable are skipped. |

***

#### claimAssetsOnBehalf

```solidity
function claimAssetsOnBehalf(address[] memory controllers) external;
```

UX helper — push claimable redeem assets to a list of controllers. *(New in v0.6.0.)*

**Parameters:**

| Name          | Type        | Description                                                               |
| ------------- | ----------- | ------------------------------------------------------------------------- |
| `controllers` | `address[]` | Controllers to claim for. Controllers with nothing claimable are skipped. |

***

#### updateTotalAssetsLifespan

```solidity
function updateTotalAssetsLifespan(uint128 lifespan) external;
```

Set how long a posted valuation stays valid for sync operations.

**Parameters:**

| Name       | Type      | Description          |
| ---------- | --------- | -------------------- |
| `lifespan` | `uint128` | Lifespan in seconds. |

***

#### expireTotalAssets

```solidity
function expireTotalAssets() public;
```

Invalidate the currently posted valuation immediately. After this call, sync operations revert until a new valuation is posted and confirmed.

***

#### updateMaxCap

```solidity
function updateMaxCap(uint256 _maxCap) external;
```

Set the deposit cap (in underlying assets).

**Parameters:**

| Name      | Type      | Description                                                  |
| --------- | --------- | ------------------------------------------------------------ |
| `_maxCap` | `uint256` | New max cap. Use `type(uint256).max` to effectively disable. |

***

#### setSyncMode

```solidity
function setSyncMode(SyncMode _mode) external;
```

Switch between async-only, sync-deposit-only, sync-redeem-only, or both. Reverts if the vault is in async-only mode. *(New in v0.6.0.)*

**Parameters:**

| Name    | Type       | Description                                     |
| ------- | ---------- | ----------------------------------------------- |
| `_mode` | `SyncMode` | `Both`, `SyncDeposit`, `SyncRedeem`, or `None`. |

***

#### resetHighWaterMark

```solidity
function resetHighWaterMark() external;
```

Reset the high-water mark to the current price per share — used after a known-loss event so the performance fee re-engages from a fresh baseline. Reverts unless `allowHighWaterMarkReset` was set to `true` at vault initialization. *(New in v0.6.0.)*

***

#### close

```solidity
function close(uint256 _newTotalAssets) external;
```

Finalize closing the vault. The Owner (Admin) must first call `initiateClosing`. After `close`, only redemption / withdrawal paths remain available.

**Parameters:**

| Name              | Type      | Description                  |
| ----------------- | --------- | ---------------------------- |
| `_newTotalAssets` | `uint256` | Final total assets at close. |

***

## Valuation Manager

#### updateNewTotalAssets

```solidity
function updateNewTotalAssets(uint256 _newTotalAssets) public;
```

Propose a new vault valuation. Must satisfy `GuardRailsManager.isCompliant` if guardrails are active.

**Parameters:**

| Name              | Type      | Description            |
| ----------------- | --------- | ---------------------- |
| `_newTotalAssets` | `uint256` | Proposed total assets. |

***

## Security Council

#### securityCouncilUpdateTotalAssets

```solidity
function securityCouncilUpdateTotalAssets(uint256 _newTotalAssets) public;
```

Same as `updateNewTotalAssets` but **bypasses guardrails**. Used to recover from valuation events that legitimately exceed the configured bounds. *(New in v0.6.0.)*

**Parameters:**

| Name              | Type      | Description            |
| ----------------- | --------- | ---------------------- |
| `_newTotalAssets` | `uint256` | Proposed total assets. |

***

#### updateGuardrails

```solidity
function updateGuardrails(Guardrails calldata guardrails_) external;
```

Update the price-per-share bounds policy.

```solidity
struct Guardrails {
    uint256 upperRate;  // maximum annualised PPS increase in bps
    int256  lowerRate;  // minimum annualised PPS change in bps (signed: can be negative)
}
```

**Parameters:**

| Name          | Type         | Description                                      |
| ------------- | ------------ | ------------------------------------------------ |
| `guardrails_` | `Guardrails` | New upper / lower annual bounds in basis points. |

***

#### updateActivated

```solidity
function updateActivated(bool activated_) external;
```

Enable or disable guardrail enforcement.

**Parameters:**

| Name         | Type   | Description                            |
| ------------ | ------ | -------------------------------------- |
| `activated_` | `bool` | `true` to enforce, `false` to disable. |

***

## Access Manager (former Whitelist Manager)

#### addToWhitelist

```solidity
function addToWhitelist(address[] memory accounts) external;
```

Add accounts to the whitelist.

**Parameters:**

| Name       | Type        | Description            |
| ---------- | ----------- | ---------------------- |
| `accounts` | `address[]` | Accounts to whitelist. |

***

#### revokeFromWhitelist

```solidity
function revokeFromWhitelist(address[] memory accounts) external;
```

Remove accounts from the whitelist.

**Parameters:**

| Name       | Type        | Description         |
| ---------- | ----------- | ------------------- |
| `accounts` | `address[]` | Accounts to remove. |

***

#### addToBlacklist

```solidity
function addToBlacklist(address[] memory accounts) external;
```

Add accounts to the blacklist. *(New in v0.6.0.)*

**Parameters:**

| Name       | Type        | Description            |
| ---------- | ----------- | ---------------------- |
| `accounts` | `address[]` | Accounts to blacklist. |

***

#### revokeFromBlacklist

```solidity
function revokeFromBlacklist(address[] memory accounts) external;
```

Remove accounts from the blacklist. *(New in v0.6.0.)*

**Parameters:**

| Name       | Type        | Description                            |
| ---------- | ----------- | -------------------------------------- |
| `accounts` | `address[]` | Accounts to remove from the blacklist. |

***

#### setExternalSanctionsList

```solidity
function setExternalSanctionsList(SanctionsList sanctionsList) external;
```

Wire an external sanctions oracle that the vault will query on **every** `isAllowed` check — i.e. on every deposit, redeem, request, share transfer, and operator-triggered claim. If the oracle returns `true` for the address, the call reverts. The hook is intended for the [Chainalysis Sanctions Oracle](https://go.chainalysis.com/chainalysis-oracle-docs.html), a free on-chain registry of OFAC-sanctioned addresses, but any contract that implements the one-method interface below works. Pass `address(0)` to disable the check entirely. *(New in v0.6.0.)*

```solidity
interface SanctionsList {
    function isSanctioned(address addr) external view returns (bool);
}
```

The sanctions check stacks on top of the active access mode (whitelist or blacklist) — an address must pass both to interact with the vault.

**Parameters:**

| Name            | Type            | Description                                                                                                                                                                                                                                                |
| --------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sanctionsList` | `SanctionsList` | Oracle address. Use the Chainalysis-deployed contract for the target chain (see [their docs](https://go.chainalysis.com/chainalysis-oracle-docs.html) for per-network addresses), a custom oracle implementing `isSanctioned`, or `address(0)` to disable. |

***

## Owner (Admin)

The Owner (Admin) is the governance role — it does not run the strategy, but it controls vault configuration, critical safety switches, and role assignments. Enforced on-chain by the standard `onlyOwner` modifier (`Ownable2StepUpgradeable`).

### Lifecycle & emergency

#### initialize

```solidity
function initialize(
    bytes memory data,
    address feeRegistry,
    address wrappedNativeToken
) public;
```

Proxy-time initializer. `data` is an ABI-encoded `InitStruct` containing the vault's full configuration.

**Parameters:**

| Name                 | Type      | Description                                                                         |
| -------------------- | --------- | ----------------------------------------------------------------------------------- |
| `data`               | `bytes`   | ABI-encoded `InitStruct` (underlying, name, symbol, roles, rates, sync mode, etc.). |
| `feeRegistry`        | `address` | Protocol fee registry address.                                                      |
| `wrappedNativeToken` | `address` | Wrapped native token (e.g. WETH) — used by `Silo.depositEth`.                       |

***

#### pause

```solidity
function pause() public;
```

Halt all core user operations (deposit, redeem, withdraw, requests, settlements, valuation updates).

***

#### unpause

```solidity
function unpause() public;
```

Resume operations after a pause.

***

#### initiateClosing

```solidity
function initiateClosing() external;
```

Start the vault wind-down. After this, the Curator finalises via `close(_newTotalAssets)`.

***

#### activateAsyncOnly

```solidity
function activateAsyncOnly() external;
```

**Irreversible.** Permanently disable sync deposits and sync redeems. After this call, `isAsyncOnly()` returns `true` and `totalAssets` is always treated as invalid. *(New in v0.6.0.)*

***

### Roles

#### updateWhitelistManager

```solidity
function updateWhitelistManager(address _whitelistManager) external;
```

Replace the Access Manager address (the role formerly known as Whitelist Manager — kept under its original name in the source for storage-layout compatibility).

**Parameters:**

| Name                | Type      | Description                 |
| ------------------- | --------- | --------------------------- |
| `_whitelistManager` | `address` | New Access Manager address. |

***

#### updateValuationManager

```solidity
function updateValuationManager(address _valuationManager) external;
```

Replace the Valuation Manager address (the role authorised to call `updateNewTotalAssets`).

**Parameters:**

| Name                | Type      | Description                    |
| ------------------- | --------- | ------------------------------ |
| `_valuationManager` | `address` | New Valuation Manager address. |

***

#### updateFeeReceiver

```solidity
function updateFeeReceiver(address _feeReceiver) external;
```

Replace the address that receives the share-denominated fees minted at settlement.

**Parameters:**

| Name           | Type      | Description               |
| -------------- | --------- | ------------------------- |
| `_feeReceiver` | `address` | New fee receiver address. |

***

#### updateSafe

```solidity
function updateSafe(address _safe) external;
```

Replace the address bound to the Curator role (called `safe` in the source for historical reasons — see the [Curator](#curator) section). *(New in v0.6.0.)* Reverts if `lockUpdateSafe` has been called.

**Parameters:**

| Name    | Type      | Description                                                                                         |
| ------- | --------- | --------------------------------------------------------------------------------------------------- |
| `_safe` | `address` | New address for the Curator role. Can be any address (multi-sig, EOA, MPC wallet, custom contract). |

***

#### updateSecurityCouncil

```solidity
function updateSecurityCouncil(address _securityCouncil) external;
```

Replace the Security Council address (the role that manages guardrails and can bypass them via `securityCouncilUpdateTotalAssets`). *(New in v0.6.0.)*

**Parameters:**

| Name               | Type      | Description                   |
| ------------------ | --------- | ----------------------------- |
| `_securityCouncil` | `address` | New Security Council address. |

***

#### updateSuperOperator

```solidity
function updateSuperOperator(address _superOperator) external;
```

Replace the Super Operator address (the global operator that can act on behalf of any controller and bypasses whitelist / blacklist checks — see [Super Operator](#super-operator) for the full scope). *(New in v0.6.0.)* Reverts if `lockSuperOperator` has been called.

**Parameters:**

| Name             | Type      | Description                                             |
| ---------------- | --------- | ------------------------------------------------------- |
| `_superOperator` | `address` | New Super Operator address. Use `address(0)` to remove. |

***

#### lockUpdateSafe

```solidity
function lockUpdateSafe() external;
```

**Irreversible.** Permanently disable `updateSafe`. *(New in v0.6.0.)*

***

#### lockSuperOperator

```solidity
function lockSuperOperator() external;
```

**Irreversible.** Permanently disable `updateSuperOperator`. *(New in v0.6.0.)*

***

#### transferOwnership / acceptOwnership

```solidity
function transferOwnership(address newOwner) public;
function acceptOwnership() public;
```

Two-step transfer of the Owner (Admin) role (`Ownable2StepUpgradeable`). `newOwner` must call `acceptOwnership` for the transfer to take effect.

***

### Access control

#### switchAccessMode

```solidity
function switchAccessMode(AccessMode newMode) public;
```

Switch between whitelist and blacklist mode. *(New in v0.6.0.)*

```solidity
enum AccessMode { Blacklist, Whitelist }
```

**Parameters:**

| Name      | Type         | Description                 |
| --------- | ------------ | --------------------------- |
| `newMode` | `AccessMode` | `Whitelist` or `Blacklist`. |

***

### Fees & metadata

#### updateRates

```solidity
function updateRates(Rates memory newRates) external;
```

Update fee rates. Max bounds are enforced on-chain (entry/exit ≤ 2%, haircut ≤ 20%, management/performance per protocol policy). The protocol cut is not part of this struct — it is read from the `FeeRegistry`.

**Parameters:**

| Name       | Type    | Description                                                                       |
| ---------- | ------- | --------------------------------------------------------------------------------- |
| `newRates` | `Rates` | New management / performance / entry / exit / haircut rates, all in basis points. |

***

#### updateName

```solidity
function updateName(string memory newName) external;
```

Update the ERC20 `name`. *(New in v0.6.0.)*

**Parameters:**

| Name      | Type     | Description |
| --------- | -------- | ----------- |
| `newName` | `string` | New name.   |

***

#### updateSymbol

```solidity
function updateSymbol(string memory newSymbol) external;
```

Update the ERC20 `symbol`. *(New in v0.6.0.)*

**Parameters:**

| Name        | Type     | Description |
| ----------- | -------- | ----------- |
| `newSymbol` | `string` | New symbol. |

***

## Super Operator

The Super Operator is a single global address that satisfies the operator check for any controller on **every user op except `requestDeposit` and `syncDeposit`**, and additionally **bypasses whitelist / blacklist checks**. There is no dedicated function — it works by passing the `isOperatorOrSuperOperator` check in `deposit`, `mint`, `redeem`, `withdraw`, `cancelRequestDeposit(address)`, and `cancelRequestRedeem`.

The address is set by the Owner (Admin) via `updateSuperOperator(address)` and can be permanently locked via `lockSuperOperator()`. Use `address(0)` to disable.

***

## GuardRailsManager (read)

#### isCompliant

```solidity
function isCompliant(
    uint256 currentPps,
    uint256 nextPps,
    uint256 timePast
) public view returns (bool);
```

Pure check used by the vault on every `updateNewTotalAssets` call. Returns `true` if the proposed PPS change stays within the configured upper/lower annual bounds for the elapsed time.

**Parameters:**

| Name         | Type      | Description                            |
| ------------ | --------- | -------------------------------------- |
| `currentPps` | `uint256` | Current price per share.               |
| `nextPps`    | `uint256` | Proposed new price per share.          |
| `timePast`   | `uint256` | Seconds elapsed since the last update. |

**Return values:**

| Name      | Type   | Description          |
| --------- | ------ | -------------------- |
| (unnamed) | `bool` | `true` if compliant. |

***

## Silo (separate contract)

The Silo is a minimal helper contract paired with each vault. It holds pending assets (during async deposits) and pending shares (during async redeems). The vault's constructor configures `IERC20(underlying).forceApprove(vault, max)` so the vault can pull from the silo; no other entry points exist beyond the one below.

#### depositEth

```solidity
function depositEth() external payable;
```

Wrap received ETH into WETH. Called by the vault when a user `requestDeposit`s native ETH and the underlying is WETH.


# Vault ABIs

Copy-paste vault ABI JSON for every deployed implementation version.

Raw ABI for each vault implementation version, extracted from the `@lagoon-protocol/v0-core` package. Each block is the full ABI as single-line JSON — copy it straight into your tooling. Call `version()` on a vault to know which ABI applies; see the [Version History](/resources/version-history).

## v0.6.0

```json
[{"type":"constructor","inputs":[{"name":"disable","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"error","name":"AboveMaxRate","inputs":[{"name":"maxRate","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"AddressEmptyCode","inputs":[{"name":"target","type":"address","internalType":"address"}]},{"type":"error","name":"AddressInsufficientBalance","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"AddressNotAllowed","inputs":[{"name":"_address","type":"address","internalType":"address"}]},{"type":"error","name":"AsyncOnly","inputs":[]},{"type":"error","name":"BelowMinimumAssets","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"minimumAssets","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"CantDepositNativeToken","inputs":[]},{"type":"error","name":"Closed","inputs":[]},{"type":"error","name":"ERC20InsufficientAllowance","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"allowance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InsufficientBalance","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"balance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InvalidApprover","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidReceiver","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSender","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSpender","inputs":[{"name":"spender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC4626ExceededMaxDeposit","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxMint","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxRedeem","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxWithdraw","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC7540InvalidOperator","inputs":[]},{"type":"error","name":"ERC7540PreviewDepositDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewMintDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewRedeemDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewWithdrawDisabled","inputs":[]},{"type":"error","name":"EnforcedPause","inputs":[]},{"type":"error","name":"ExpectedPause","inputs":[]},{"type":"error","name":"FailedInnerCall","inputs":[]},{"type":"error","name":"GuardrailsViolation","inputs":[]},{"type":"error","name":"HighWaterMarkResetNotAllowed","inputs":[]},{"type":"error","name":"InvalidController","inputs":[{"name":"controller","type":"address","internalType":"address"}]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"InvalidReceiver","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"type":"error","name":"LowerRateCannotBeInt256Min","inputs":[]},{"type":"error","name":"MathOverflowedMulDiv","inputs":[]},{"type":"error","name":"MaxCapReached","inputs":[]},{"type":"error","name":"NewTotalAssetsMissing","inputs":[]},{"type":"error","name":"NotClosing","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NotOpen","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"OnlyOneRequestAllowed","inputs":[]},{"type":"error","name":"OnlySafe","inputs":[{"name":"safe","type":"address","internalType":"address"}]},{"type":"error","name":"OnlySecurityCouncil","inputs":[{"name":"securityCouncil","type":"address","internalType":"address"}]},{"type":"error","name":"OnlySyncDepositAllowed","inputs":[]},{"type":"error","name":"OnlyValuationManager","inputs":[{"name":"valuationManager","type":"address","internalType":"address"}]},{"type":"error","name":"OnlyWhitelistManager","inputs":[{"name":"whitelistManager","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RateCanOnlyDecrease","inputs":[{"name":"currentRate","type":"uint256","internalType":"uint256"},{"name":"newRate","type":"uint256","internalType":"uint256"},{"name":"feeType","type":"uint8","internalType":"enum FeeType"}]},{"type":"error","name":"RequestIdNotClaimable","inputs":[]},{"type":"error","name":"RequestNotCancelable","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SafeERC20FailedOperation","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"type":"error","name":"SafeUpdateLocked","inputs":[]},{"type":"error","name":"SuperOperatorUpdateLocked","inputs":[]},{"type":"error","name":"SyncOperationNotAllowed","inputs":[]},{"type":"error","name":"TotalAssetsExpired","inputs":[]},{"type":"error","name":"ValuationUpdateNotAllowed","inputs":[]},{"type":"error","name":"VaultInitializationFailed","inputs":[]},{"type":"error","name":"WrongNewTotalAssets","inputs":[]},{"type":"event","name":"AccessModeUpdated","inputs":[{"name":"newMode","type":"uint8","indexed":false,"internalType":"enum AccessMode"}],"anonymous":false},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"AsyncOnlyActivated","inputs":[],"anonymous":false},{"type":"event","name":"BlacklistUpdated","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"blacklisted","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequestCanceled","inputs":[{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"controller","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"DepositSync","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ExternalSanctionsListUpdated","inputs":[{"name":"oldExternalSanctionList","type":"address","indexed":false,"internalType":"address"},{"name":"newExternalSanctionList","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"FeeReceiverUpdated","inputs":[{"name":"oldReceiver","type":"address","indexed":false,"internalType":"address"},{"name":"newReceiver","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"FeeTaken","inputs":[{"name":"feeType","type":"uint8","indexed":true,"internalType":"enum FeeType"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"rate","type":"uint16","indexed":false,"internalType":"uint16"},{"name":"contextId","type":"uint40","indexed":false,"internalType":"uint40"},{"name":"managerShares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"protocolShares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"GuardrailsStatusUpdated","inputs":[{"name":"activated","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"GuardrailsUpdated","inputs":[{"name":"oldGuardrails","type":"tuple","indexed":false,"internalType":"struct Guardrails","components":[{"name":"upperRate","type":"uint256","internalType":"uint256"},{"name":"lowerRate","type":"int256","internalType":"int256"}]},{"name":"newGuardrails","type":"tuple","indexed":false,"internalType":"struct Guardrails","components":[{"name":"upperRate","type":"uint256","internalType":"uint256"},{"name":"lowerRate","type":"int256","internalType":"int256"}]}],"anonymous":false},{"type":"event","name":"HaircutTaken","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"rate","type":"uint16","indexed":false,"internalType":"uint16"}],"anonymous":false},{"type":"event","name":"HighWaterMarkUpdated","inputs":[{"name":"oldHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"MaxCapUpdated","inputs":[{"name":"previousMaxCap","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"maxCap","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"NameUpdated","inputs":[{"name":"previousName","type":"string","indexed":false,"internalType":"string"},{"name":"newName","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"NewTotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorSet","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"PreMint","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"receiver","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RatesUpdated","inputs":[{"name":"oldRates","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"},{"name":"entryRate","type":"uint16","internalType":"uint16"},{"name":"exitRate","type":"uint16","internalType":"uint16"},{"name":"haircutRate","type":"uint16","internalType":"uint16"}]},{"name":"newRate","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"},{"name":"entryRate","type":"uint16","internalType":"uint16"},{"name":"exitRate","type":"uint16","internalType":"uint16"},{"name":"haircutRate","type":"uint16","internalType":"uint16"}]},{"name":"timestamp","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RedeemRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RedeemRequestCanceled","inputs":[{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"requestedAmount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Referral","inputs":[{"name":"referral","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SafeLocked","inputs":[{"name":"safe","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SafeUpdated","inputs":[{"name":"oldSafe","type":"address","indexed":false,"internalType":"address"},{"name":"newSafe","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SecurityCouncilUpdated","inputs":[{"name":"oldSecurityCouncil","type":"address","indexed":false,"internalType":"address"},{"name":"newSecurityCouncil","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SettleDeposit","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsDeposited","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesMinted","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SettleRedeem","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsWithdrawed","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesBurned","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"StateUpdated","inputs":[{"name":"state","type":"uint8","indexed":false,"internalType":"enum State"}],"anonymous":false},{"type":"event","name":"SuperOperatorLocked","inputs":[{"name":"superOperator","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SuperOperatorUpdated","inputs":[{"name":"oldSuperOperator","type":"address","indexed":false,"internalType":"address"},{"name":"newSuperOperator","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SymbolUpdated","inputs":[{"name":"previousSymbol","type":"string","indexed":false,"internalType":"string"},{"name":"newSymbol","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"SyncModeUpdated","inputs":[{"name":"oldMode","type":"uint8","indexed":false,"internalType":"enum SyncMode"},{"name":"newMode","type":"uint8","indexed":false,"internalType":"enum SyncMode"}],"anonymous":false},{"type":"event","name":"TotalAssetsExpirationUpdated","inputs":[{"name":"oldExpiration","type":"uint128","indexed":false,"internalType":"uint128"},{"name":"newExpiration","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"TotalAssetsLifespanUpdated","inputs":[{"name":"oldLifespan","type":"uint128","indexed":false,"internalType":"uint128"},{"name":"newLifespan","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"TotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"ValuationManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistDisabled","inputs":[],"anonymous":false},{"type":"event","name":"WhitelistManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistUpdated","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"authorized","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"receiver","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"WithdrawSync","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"receiver","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"activateAsyncOnly","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addToBlacklist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addToWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"allowance","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"spender","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"approve","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"asset","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"balanceOf","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"cancelRequestDeposit","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cancelRequestDeposit","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cancelRequestRedeem","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimAssetsOnBehalf","inputs":[{"name":"controllers","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesAndRequestRedeem","inputs":[{"name":"sharesToRedeem","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"requestId","type":"uint40","internalType":"uint40"}],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesOnBehalf","inputs":[{"name":"controllers","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimableDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"claimableRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"close","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"expireTotalAssets","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"feeRates","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"},{"name":"entryRate","type":"uint16","internalType":"uint16"},{"name":"exitRate","type":"uint16","internalType":"uint16"},{"name":"haircutRate","type":"uint16","internalType":"uint16"}]}],"stateMutability":"view"},{"type":"function","name":"forge","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initialize","inputs":[{"name":"data","type":"bytes","internalType":"bytes"},{"name":"feeRegistry","type":"address","internalType":"address"},{"name":"wrappedNativeToken","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initiateClosing","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isAllowed","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isAsyncOnly","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isCompliant","inputs":[{"name":"currentPps","type":"uint256","internalType":"uint256"},{"name":"nextPps","type":"uint256","internalType":"uint256"},{"name":"_timePast","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isOperator","inputs":[{"name":"controller","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTotalAssetsValid","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"lockSuperOperator","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"lockUpdateSafe","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"maxCap","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxDeposit","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxMint","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxRedeem","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxWithdraw","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pendingDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"previewDeposit","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewMint","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewRedeem","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewSyncDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"previewSyncRedeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"previewWithdraw","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"redeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"},{"name":"referral","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestRedeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"resetHighWaterMark","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeFromBlacklist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeFromWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"safe","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"securityCouncilUpdateTotalAssets","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setExternalSanctionsList","inputs":[{"name":"sanctionsList","type":"address","internalType":"contract SanctionsList"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setOperator","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[{"name":"success","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"setSyncMode","inputs":[{"name":"_mode","type":"uint8","internalType":"enum SyncMode"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleDeposit","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleRedeem","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"share","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"switchAccessMode","inputs":[{"name":"newMode","type":"uint8","internalType":"enum AccessMode"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"syncDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"referral","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"syncMode","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"enum SyncMode"}],"stateMutability":"view"},{"type":"function","name":"syncRedeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"minimumAssets","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"totalAssets","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transfer","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transmitFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"unpause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateActivated","inputs":[{"name":"activated_","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateFeeReceiver","inputs":[{"name":"_feeReceiver","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateGuardrails","inputs":[{"name":"guardrails_","type":"tuple","internalType":"struct Guardrails","components":[{"name":"upperRate","type":"uint256","internalType":"uint256"},{"name":"lowerRate","type":"int256","internalType":"int256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateMaxCap","inputs":[{"name":"_maxCap","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateName","inputs":[{"name":"newName","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNewTotalAssets","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateRates","inputs":[{"name":"newRates","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"},{"name":"entryRate","type":"uint16","internalType":"uint16"},{"name":"exitRate","type":"uint16","internalType":"uint16"},{"name":"haircutRate","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSafe","inputs":[{"name":"_safe","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSecurityCouncil","inputs":[{"name":"_securityCouncil","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSuperOperator","inputs":[{"name":"_superOperator","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateSymbol","inputs":[{"name":"newSymbol","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateTotalAssetsLifespan","inputs":[{"name":"lifespan","type":"uint128","internalType":"uint128"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateValuationManager","inputs":[{"name":"_valuationManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateWhitelistManager","inputs":[{"name":"_whitelistManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"type":"function","name":"void","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"withdraw","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"}]
```

## v0.5.1

```json
[{"type":"constructor","inputs":[{"name":"disable","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"MAX_MANAGEMENT_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"MAX_PERFORMANCE_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"MAX_PROTOCOL_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addToWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"allowance","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"spender","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"approve","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"asset","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"balanceOf","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"cancelRequestDeposit","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesAndRequestRedeem","inputs":[{"name":"sharesToRedeem","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"requestId","type":"uint40","internalType":"uint40"}],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesOnBehalf","inputs":[{"name":"controllers","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimableDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"claimableRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"close","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"disableWhitelist","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"expireTotalAssets","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"feeRates","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]}],"stateMutability":"view"},{"type":"function","name":"getRolesStorage","inputs":[],"outputs":[{"name":"_rolesStorage","type":"tuple","internalType":"struct Roles.RolesStorage","components":[{"name":"whitelistManager","type":"address","internalType":"address"},{"name":"feeReceiver","type":"address","internalType":"address"},{"name":"safe","type":"address","internalType":"address"},{"name":"feeRegistry","type":"address","internalType":"contract FeeRegistry"},{"name":"valuationManager","type":"address","internalType":"address"}]}],"stateMutability":"pure"},{"type":"function","name":"initialize","inputs":[{"name":"data","type":"bytes","internalType":"bytes"},{"name":"feeRegistry","type":"address","internalType":"address"},{"name":"wrappedNativeToken","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initiateClosing","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isOperator","inputs":[{"name":"controller","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTotalAssetsValid","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isWhitelisted","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxDeposit","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxMint","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxRedeem","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxWithdraw","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pendingDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"previewDeposit","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewMint","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewRedeem","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewWithdraw","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"redeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"},{"name":"referral","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestRedeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"revokeFromWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"safe","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"setOperator","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[{"name":"success","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"settleDeposit","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleRedeem","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"share","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"syncDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"referral","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"totalAssets","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transfer","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unpause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateFeeReceiver","inputs":[{"name":"_feeReceiver","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNewTotalAssets","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateRates","inputs":[{"name":"newRates","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateTotalAssetsLifespan","inputs":[{"name":"lifespan","type":"uint128","internalType":"uint128"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateValuationManager","inputs":[{"name":"_valuationManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateWhitelistManager","inputs":[{"name":"_whitelistManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"type":"function","name":"withdraw","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequestCanceled","inputs":[{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"controller","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"DepositSync","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"FeeReceiverUpdated","inputs":[{"name":"oldReceiver","type":"address","indexed":false,"internalType":"address"},{"name":"newReceiver","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"HighWaterMarkUpdated","inputs":[{"name":"oldHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"NewTotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorSet","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RatesUpdated","inputs":[{"name":"oldRates","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]},{"name":"newRate","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]},{"name":"timestamp","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RedeemRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Referral","inputs":[{"name":"referral","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SettleDeposit","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsDeposited","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesMinted","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SettleRedeem","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsWithdrawed","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesBurned","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"StateUpdated","inputs":[{"name":"state","type":"uint8","indexed":false,"internalType":"enum State"}],"anonymous":false},{"type":"event","name":"TotalAssetsLifespanUpdated","inputs":[{"name":"oldLifespan","type":"uint128","indexed":false,"internalType":"uint128"},{"name":"newLifespan","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"TotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"ValuationManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistDisabled","inputs":[],"anonymous":false},{"type":"event","name":"WhitelistManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistUpdated","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"authorized","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"receiver","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AboveMaxRate","inputs":[{"name":"maxRate","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"AddressEmptyCode","inputs":[{"name":"target","type":"address","internalType":"address"}]},{"type":"error","name":"AddressInsufficientBalance","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"CantDepositNativeToken","inputs":[]},{"type":"error","name":"Closed","inputs":[]},{"type":"error","name":"ERC20InsufficientAllowance","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"allowance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InsufficientBalance","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"balance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InvalidApprover","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidReceiver","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSender","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSpender","inputs":[{"name":"spender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC4626ExceededMaxDeposit","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxMint","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxRedeem","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxWithdraw","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC7540InvalidOperator","inputs":[]},{"type":"error","name":"ERC7540PreviewDepositDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewMintDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewRedeemDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewWithdrawDisabled","inputs":[]},{"type":"error","name":"EnforcedPause","inputs":[]},{"type":"error","name":"ExpectedPause","inputs":[]},{"type":"error","name":"FailedInnerCall","inputs":[]},{"type":"error","name":"InvalidController","inputs":[{"name":"controller","type":"address","internalType":"address"}]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"MathOverflowedMulDiv","inputs":[]},{"type":"error","name":"NewTotalAssetsMissing","inputs":[]},{"type":"error","name":"NotClosing","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NotOpen","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"NotWhitelisted","inputs":[]},{"type":"error","name":"OnlyAsyncDepositAllowed","inputs":[]},{"type":"error","name":"OnlyOneRequestAllowed","inputs":[]},{"type":"error","name":"OnlySafe","inputs":[{"name":"safe","type":"address","internalType":"address"}]},{"type":"error","name":"OnlySyncDepositAllowed","inputs":[]},{"type":"error","name":"OnlyValuationManager","inputs":[{"name":"valuationManager","type":"address","internalType":"address"}]},{"type":"error","name":"OnlyWhitelistManager","inputs":[{"name":"whitelistManager","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RequestIdNotClaimable","inputs":[]},{"type":"error","name":"RequestNotCancelable","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SafeERC20FailedOperation","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"type":"error","name":"ValuationUpdateNotAllowed","inputs":[]},{"type":"error","name":"WrongNewTotalAssets","inputs":[]}]
```

## v0.5.0

```json
[{"type":"constructor","inputs":[{"name":"disable","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"MAX_MANAGEMENT_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"MAX_PERFORMANCE_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"MAX_PROTOCOL_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addToWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"allowance","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"spender","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"approve","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"asset","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"balanceOf","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"cancelRequestDeposit","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesAndRequestRedeem","inputs":[{"name":"sharesToRedeem","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"requestId","type":"uint40","internalType":"uint40"}],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesOnBehalf","inputs":[{"name":"controllers","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimableDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"claimableRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"close","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"disableWhitelist","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"expireTotalAssets","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"feeRates","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]}],"stateMutability":"view"},{"type":"function","name":"getRolesStorage","inputs":[],"outputs":[{"name":"_rolesStorage","type":"tuple","internalType":"struct Roles.RolesStorage","components":[{"name":"whitelistManager","type":"address","internalType":"address"},{"name":"feeReceiver","type":"address","internalType":"address"},{"name":"safe","type":"address","internalType":"address"},{"name":"feeRegistry","type":"address","internalType":"contract FeeRegistry"},{"name":"valuationManager","type":"address","internalType":"address"}]}],"stateMutability":"pure"},{"type":"function","name":"initialize","inputs":[{"name":"data","type":"bytes","internalType":"bytes"},{"name":"feeRegistry","type":"address","internalType":"address"},{"name":"wrappedNativeToken","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initiateClosing","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isOperator","inputs":[{"name":"controller","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTotalAssetsValid","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isWhitelisted","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxDeposit","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxMint","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxRedeem","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxWithdraw","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pendingDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"previewDeposit","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewMint","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewRedeem","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewWithdraw","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"redeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"},{"name":"referral","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestRedeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"revokeFromWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"safe","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"setOperator","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[{"name":"success","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"settleDeposit","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleRedeem","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"share","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"syncDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"referral","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"totalAssets","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transfer","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unpause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateFeeReceiver","inputs":[{"name":"_feeReceiver","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNewTotalAssets","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateRates","inputs":[{"name":"newRates","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateTotalAssetsLifespan","inputs":[{"name":"lifespan","type":"uint128","internalType":"uint128"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateValuationManager","inputs":[{"name":"_valuationManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateWhitelistManager","inputs":[{"name":"_whitelistManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"type":"function","name":"withdraw","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequestCanceled","inputs":[{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"controller","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"DepositSync","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"FeeReceiverUpdated","inputs":[{"name":"oldReceiver","type":"address","indexed":false,"internalType":"address"},{"name":"newReceiver","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"HighWaterMarkUpdated","inputs":[{"name":"oldHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"NewTotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorSet","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RatesUpdated","inputs":[{"name":"oldRates","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]},{"name":"newRate","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]},{"name":"timestamp","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RedeemRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Referral","inputs":[{"name":"referral","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SettleDeposit","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsDeposited","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesMinted","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SettleRedeem","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsWithdrawed","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesBurned","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"StateUpdated","inputs":[{"name":"state","type":"uint8","indexed":false,"internalType":"enum State"}],"anonymous":false},{"type":"event","name":"TotalAssetsLifespanUpdated","inputs":[{"name":"oldLifespan","type":"uint128","indexed":false,"internalType":"uint128"},{"name":"newLifespan","type":"uint128","indexed":false,"internalType":"uint128"}],"anonymous":false},{"type":"event","name":"TotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"ValuationManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistDisabled","inputs":[],"anonymous":false},{"type":"event","name":"WhitelistManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistUpdated","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"authorized","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"receiver","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AboveMaxRate","inputs":[{"name":"maxRate","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"AddressEmptyCode","inputs":[{"name":"target","type":"address","internalType":"address"}]},{"type":"error","name":"AddressInsufficientBalance","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"CantDepositNativeToken","inputs":[]},{"type":"error","name":"Closed","inputs":[]},{"type":"error","name":"ERC20InsufficientAllowance","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"allowance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InsufficientBalance","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"balance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InvalidApprover","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidReceiver","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSender","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSpender","inputs":[{"name":"spender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC4626ExceededMaxDeposit","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxMint","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxRedeem","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxWithdraw","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC7540InvalidOperator","inputs":[]},{"type":"error","name":"ERC7540PreviewDepositDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewMintDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewRedeemDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewWithdrawDisabled","inputs":[]},{"type":"error","name":"EnforcedPause","inputs":[]},{"type":"error","name":"ExpectedPause","inputs":[]},{"type":"error","name":"FailedInnerCall","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"MathOverflowedMulDiv","inputs":[]},{"type":"error","name":"NewTotalAssetsMissing","inputs":[]},{"type":"error","name":"NotClosing","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NotOpen","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"NotWhitelisted","inputs":[]},{"type":"error","name":"OnlyAsyncDepositAllowed","inputs":[]},{"type":"error","name":"OnlyOneRequestAllowed","inputs":[]},{"type":"error","name":"OnlySafe","inputs":[{"name":"safe","type":"address","internalType":"address"}]},{"type":"error","name":"OnlySyncDepositAllowed","inputs":[]},{"type":"error","name":"OnlyValuationManager","inputs":[{"name":"valuationManager","type":"address","internalType":"address"}]},{"type":"error","name":"OnlyWhitelistManager","inputs":[{"name":"whitelistManager","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RequestIdNotClaimable","inputs":[]},{"type":"error","name":"RequestNotCancelable","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SafeERC20FailedOperation","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"type":"error","name":"ValuationUpdateNotAllowed","inputs":[]},{"type":"error","name":"WrongNewTotalAssets","inputs":[]}]
```

## v0.4.0

```json
[{"type":"constructor","inputs":[{"name":"disable","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"MAX_MANAGEMENT_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"MAX_PERFORMANCE_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"MAX_PROTOCOL_RATE","inputs":[],"outputs":[{"name":"","type":"uint16","internalType":"uint16"}],"stateMutability":"view"},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addToWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"allowance","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"spender","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"approve","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"asset","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"balanceOf","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"cancelRequestDeposit","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesAndRequestRedeem","inputs":[{"name":"sharesToRedeem","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"requestId","type":"uint40","internalType":"uint40"}],"stateMutability":"nonpayable"},{"type":"function","name":"claimSharesOnBehalf","inputs":[{"name":"controllers","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimableDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"claimableRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"close","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToAssets","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"convertToShares","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"requestId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"deposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"disableWhitelist","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"feeRates","inputs":[],"outputs":[{"name":"","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]}],"stateMutability":"view"},{"type":"function","name":"getRolesStorage","inputs":[],"outputs":[{"name":"_rolesStorage","type":"tuple","internalType":"struct Roles.RolesStorage","components":[{"name":"whitelistManager","type":"address","internalType":"address"},{"name":"feeReceiver","type":"address","internalType":"address"},{"name":"safe","type":"address","internalType":"address"},{"name":"feeRegistry","type":"address","internalType":"contract FeeRegistry"},{"name":"valuationManager","type":"address","internalType":"address"}]}],"stateMutability":"pure"},{"type":"function","name":"highWaterMark","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"data","type":"bytes","internalType":"bytes"},{"name":"feeRegistry","type":"address","internalType":"address"},{"name":"wrappedNativeToken","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initiateClosing","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isOperator","inputs":[{"name":"controller","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isWhitelistActivated","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isWhitelisted","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"lastDepositRequestId","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint40","internalType":"uint40"}],"stateMutability":"view"},{"type":"function","name":"lastFeeTime","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"lastRedeemRequestId","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint40","internalType":"uint40"}],"stateMutability":"view"},{"type":"function","name":"maxDeposit","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxMint","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxRedeem","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"maxWithdraw","inputs":[{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"mint","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"pendingDepositRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingRedeemRequest","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"pendingSilo","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"previewDeposit","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewMint","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewRedeem","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"previewWithdraw","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"redeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"assets","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestDeposit","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"},{"name":"referral","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"type":"function","name":"requestRedeem","inputs":[{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"controller","type":"address","internalType":"address"},{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"revokeFromWhitelist","inputs":[{"name":"accounts","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setOperator","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[{"name":"success","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"settleDeposit","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"settleRedeem","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"share","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"totalAssets","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transfer","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unpause","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateFeeReceiver","inputs":[{"name":"_feeReceiver","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateNewTotalAssets","inputs":[{"name":"_newTotalAssets","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateRates","inputs":[{"name":"newRates","type":"tuple","internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateValuationManager","inputs":[{"name":"_valuationManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateWhitelistManager","inputs":[{"name":"_whitelistManager","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"type":"function","name":"withdraw","inputs":[{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"},{"name":"controller","type":"address","internalType":"address"}],"outputs":[{"name":"shares","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"DepositRequestCanceled","inputs":[{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"controller","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"FeeReceiverUpdated","inputs":[{"name":"oldReceiver","type":"address","indexed":false,"internalType":"address"},{"name":"newReceiver","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"HighWaterMarkUpdated","inputs":[{"name":"oldHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newHighWaterMark","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"NewTotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorSet","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RatesUpdated","inputs":[{"name":"oldRates","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]},{"name":"newRate","type":"tuple","indexed":false,"internalType":"struct Rates","components":[{"name":"managementRate","type":"uint16","internalType":"uint16"},{"name":"performanceRate","type":"uint16","internalType":"uint16"}]},{"name":"timestamp","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RedeemRequest","inputs":[{"name":"controller","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"sender","type":"address","indexed":false,"internalType":"address"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Referral","inputs":[{"name":"referral","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"requestId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SettleDeposit","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsDeposited","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesMinted","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"SettleRedeem","inputs":[{"name":"epochId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"settledId","type":"uint40","indexed":true,"internalType":"uint40"},{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"totalSupply","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"assetsWithdrawed","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"sharesBurned","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"StateUpdated","inputs":[{"name":"state","type":"uint8","indexed":false,"internalType":"enum State"}],"anonymous":false},{"type":"event","name":"TotalAssetsUpdated","inputs":[{"name":"totalAssets","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"name":"account","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"ValuationManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistDisabled","inputs":[],"anonymous":false},{"type":"event","name":"WhitelistManagerUpdated","inputs":[{"name":"oldManager","type":"address","indexed":false,"internalType":"address"},{"name":"newManager","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"WhitelistUpdated","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"authorized","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"receiver","type":"address","indexed":true,"internalType":"address"},{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"assets","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"AboveMaxRate","inputs":[{"name":"maxRate","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"AddressEmptyCode","inputs":[{"name":"target","type":"address","internalType":"address"}]},{"type":"error","name":"AddressInsufficientBalance","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"CantDepositNativeToken","inputs":[]},{"type":"error","name":"Closed","inputs":[]},{"type":"error","name":"ERC20InsufficientAllowance","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"allowance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InsufficientBalance","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"balance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InvalidApprover","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidReceiver","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSender","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSpender","inputs":[{"name":"spender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC4626ExceededMaxDeposit","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxMint","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxRedeem","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"shares","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC4626ExceededMaxWithdraw","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"assets","type":"uint256","internalType":"uint256"},{"name":"max","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC7540InvalidOperator","inputs":[]},{"type":"error","name":"ERC7540PreviewDepositDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewMintDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewRedeemDisabled","inputs":[]},{"type":"error","name":"ERC7540PreviewWithdrawDisabled","inputs":[]},{"type":"error","name":"EnforcedPause","inputs":[]},{"type":"error","name":"ExpectedPause","inputs":[]},{"type":"error","name":"FailedInnerCall","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"MathOverflowedMulDiv","inputs":[]},{"type":"error","name":"NewTotalAssetsMissing","inputs":[]},{"type":"error","name":"NotClosing","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"NotOpen","inputs":[{"name":"currentState","type":"uint8","internalType":"enum State"}]},{"type":"error","name":"NotWhitelisted","inputs":[]},{"type":"error","name":"OnlyOneRequestAllowed","inputs":[]},{"type":"error","name":"OnlySafe","inputs":[{"name":"safe","type":"address","internalType":"address"}]},{"type":"error","name":"OnlyValuationManager","inputs":[{"name":"valuationManager","type":"address","internalType":"address"}]},{"type":"error","name":"OnlyWhitelistManager","inputs":[{"name":"whitelistManager","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RequestIdNotClaimable","inputs":[]},{"type":"error","name":"RequestNotCancelable","inputs":[{"name":"requestId","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SafeERC20FailedOperation","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"type":"error","name":"WrongNewTotalAssets","inputs":[]}]
```


# Lagoon SDKs

The Lagoon SDKs are a collection of TypeScript libraries designed to simplify interactions with Lagoon Vaults. They offer modular, framework-agnostic core functionality that makes it easy to integrate Vault operations into any application.

Their architecture is inspired by Morpho’s SDK design principles, combining clean abstractions with specialized modules for popular web3 libraries to streamline development workflows

### Overview

The SDK consists of two main packages:

* **`@lagoon-protocol/v0-core`** - Framework-agnostic vault entities and utilities
* **`@lagoon-protocol/v0-viem`** - Viem-based extensions for seamless blockchain interactions

This library will evolve in the near future. We are actively listening to emerging integration needs and are open to discussions around external contributions.

### Features

The SDKs have a modular architecture that cleanly separates core logic from blockchain interaction layers, enabling seamless integration across diverse environments, from frontend applications to backend services.

The core package provides:

* `Token` class for ERC20 token handling

```typescript
export interface IToken {
  address: Address;
  name?: string;
  symbol?: string;
  decimals?: BigIntish;
  price?: BigIntish;
  totalSupply: bigint;
}
```

* `Vault` class for vault state management

```typescript
export interface IVault extends IToken {
  asset: Address;
  underlyingDecimals: number;
  owner: Address;
  pendingOwner: Address;
  whitelistManager: Address;
  feeReceiver: Address;
  safe: Address;
  feeRegistry: Address;
  valuationManager: Address;
  newRatesTimestamp: bigint;
  lastFeeTime: bigint;
  highWaterMark: bigint;
  cooldown: bigint;
  feeRates: Rates
  totalAssets: bigint;
  newTotalAssets: bigint;
  depositEpochId: number;
  depositSettleId: number;
  lastDepositEpochIdSettled: number;
  redeemEpochId: number;
  redeemSettleId: number;
  lastRedeemEpochIdSettled: number;
  pendingSilo: Address;
  wrappedNativeToken: Address;
  decimals: number;
  decimalsOffset: number;
  totalAssetsExpiration: bigint;
  totalAssetsLifespan: bigint;
  state: State,
  isWhitelistActivated: boolean,
  version: Version
}
```

* `VaultUtils` for common calculations
* Chain addresses and configuration constants

The Viem integration package provides:

* Blockchain data fetching capabilities
* Seamless integration with Viem clients

### Quick Start

#### Installation

Choose the package that fits your needs:

```bash
# For Viem integration (recommanded)
npm install @lagoon-protocol/v0-viem

# For framework-agnostic usage
npm install @lagoon-protocol/v0-core
```

#### Example: Calculate Vault APR

This is for example purpose only.

```typescript
import { Vault } from "@lagoon-protocol/v0-viem";
import { VaultUtils } from "@lagoon-protocol/v0-core";
import { Address, createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';

const client = createPublicClient({
  chain: mainnet,
  transport: http(),
});

async function fetchVault(address: Address, blockNumber: bigint) {
  const vault = await Vault.fetch(address, client, { blockNumber });
  if (!vault) {
    throw new Error("Vault not found")
  }
  return vault
}

async function calculateVaultAPR({
  vaultAddress,
  startBlockNumber,
  endBlockNumber,
  decimals = 18
}: { vaultAddress: Address, startBlockNumber: bigint, endBlockNumber: bigint, decimals?: number }) {
  const startBlock = await client.getBlock({ blockNumber: startBlockNumber });
  const endBlock = await client.getBlock({ blockNumber: endBlockNumber });

  const vaultStart = await fetchVault(vaultAddress, startBlock.number);
  const vaultEnd = await fetchVault(vaultAddress, endBlock.number);

  const basePrice = vaultStart.convertToAssets(VaultUtils.ONE_SHARE);
  const currentPrice = vaultEnd.convertToAssets(VaultUtils.ONE_SHARE);

  const periodSeconds = endBlock.timestamp - startBlock.timestamp;

  const SECONDS_PER_YEAR = 365n * 24n * 60n * 60n;
  const BASIS_POINT = 10n ** BigInt(decimals + 2);

  const periodYield = ((currentPrice - basePrice) * SECONDS_PER_YEAR * BASIS_POINT);
  return periodYield / (periodSeconds * basePrice);
}

const decimals = 18
// If the vault is asynchronous, you can use the oldest and youngest TotalAssetUpdated event block numbers as the startBlockNumber and endBlockNumber, respectively.
const vaultApr = await calculateVaultAPR({ vaultAddress: '0x...', startBlockNumber: 1234n, endBlockNumber: 456n, decimals })

console.log(`vault APR: ${formatUnits(vaultApr, decimals)}%`);

```

* **GitHub Repository:** <https://github.com/hopperlabsxyz/sdk-v0>
* **Core Package NPM:** <https://www.npmjs.com/package/@lagoon-protocol/v0-core>
* **Viem Package NPM:** <https://www.npmjs.com/package/@lagoon-protocol/v0-viem>


# Integration

This section is designed for developers integrating Lagoon Vaults into their applications or services.

<table data-view="cards"><thead><tr><th data-type="content-ref"></th></tr></thead><tbody><tr><td><a href="/developer-hub/integration/get-a-user-position">Get a user position</a></td></tr><tr><td><a href="/developer-hub/integration/async-deposit-flow">Async deposit flow</a></td></tr><tr><td><a href="/developer-hub/integration/synchronous-deposit-flow">Synchronous deposit flow</a></td></tr><tr><td><a href="/developer-hub/integration/vault-subgraphs">Vault Subgraphs</a></td></tr><tr><td><a href="/developer-hub/integration/vaults-frontend-integration">Vaults Frontend Integration</a></td></tr><tr><td><a href="/developer-hub/integration/apr-computations">APR computations</a></td></tr></tbody></table>


# Vault state


# Get a user position

Lagoon vaults are based on [ERC7540](https://eips.ethereum.org/EIPS/eip-7540) ; the standard for asynchronous deposits and redemptions in a vault.

7540 is an extension of 4626 that add functions around requests and tweak others like `max` functions and deposit/mint/withdraw/redeem functions.

A user total share balance is the addition of the return of three functions:

* `vault.balanceOf(userAddress);` → ERC20 function
* `vault.maxMint(userAddress);` → shares ready to be claimed (to not be confused with the ERC4626 maxMint function)
* `vault.pendingRedeemRequest(0, userAddress);` → user shares waiting to be redeemed. [Why 0 ?](https://eips.ethereum.org/EIPS/eip-7540#request-ids)


# Async deposit flow

### 1) User requests a deposit

```solidity
 function requestDeposit(
        uint256 assets,
        address controller,
        address owner
    ) external payable returns (uint256 requestId);
```

Args:

* assets: the quantity of underlying to deposit.
* controller: the address that will control the request. The user address.
* owner: the address from which the asset will be transfered from. The user address.

{% hint style="info" %}
An asset.approve() transaction from the user to the vault should happen before the request deposit.
{% endhint %}

After the transaction, users can check their pending requests by calling:

```solidity
function pendingDepositRequest(
        uint256 requestId, 
        address controller
    ) external view returns (uint256 assets);
```

Args:

* requestId, the id of the deposit request. Put 0 as a wildcard.
* controller. User address.

Return:

* Amount of assets pending

### 2) User claim his shares

After a settleDeposits, the shares are claimable and waiting in the vault.

{% hint style="warning" %}
*Claiming the shares is not mandatory to start earning.*
{% endhint %}

A user can know the amount of claimable shares by calling:

```solidity
function maxMint(address) public view virtual returns (uint256 shares)
```

He can claim them by calling:

```solidity
function mint(uint256 shares, address receiver) public virtual returns (uint256 assets)
```

or

```solidity
function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares)
```

Args:

* shares: the amount of shares to claim. Between 0 and the return of maxMint(userAddress).
* receiver: user address.

### Ux tip - Claim shares and request redeem in one tx

A user with claimable shares can directly request a redemption by calling:

```solidity
function claimSharesAndRequestRedeem(
   uint256 sharesToRedeem
    ) public onlyOpen whenNotPaused returns (uint40 requestId)
```

Note: Already claimed shares can be requested to be redeemed via this method. It also means that you could only use this function to do redemption requests.

```
Example:
userClaimableShares: 10
userSharesBalance: 5
claimSharesAndRequestRedeem(15) --> valid call

userClaimableShares: 0
userSharesBalance: 5
claimSharesAndRequestRedeem(5) --> valid call
```

{% hint style="success" %}
This will improve the UX and remove one transaction in the process.
{% endhint %}


# Synchronous deposit flow

This page will guide you through activating synchronous deposits.

## How to do a synchronous deposit ?

Synchronous deposits can be done by calling:

```solidity
function syncDeposit(uint256 assets, address receiver, address referral) payable returns (uint256 shares);
```

| Variable | Definition                                                                |
| -------- | ------------------------------------------------------------------------- |
| assets   | Amount of assets to deposit.                                              |
| receiver | Recipient of the shares.                                                  |
| referral | Address that referred the depositor. Put the address 0 if not applicable. |

## How to know if synchronous deposits are currently possible?

if the function `isTotalAssetsValid()` returns true, users can do synchronous deposits. If it returns false, users must do [async deposits](/developer-hub/integration/async-deposit-flow).

```solidity
function isTotalAssetsValid() returns (bool);
```

## Typescript example with viem

Here is an example of how to decide weither a user should do a synchronous or an asynchronous deposit.

```typescript
const isSyncDepositAllowed = await client.readContract({
  abi: vaultAbi,
  address: vault.address,
  functionName: "isTotalAssetsValid",
});

if (isSyncDepositAllowed) {
  await client.writeContract({
    abi: vaultAbi,
    address: vault.address,
    functionName: "syncDeposit", // synchronous deposit
    args: [1000n, user.address, user.address],
  });
} else {
  await client.writeContract({
    abi: vaultAbi,
    address: vault.address,
    functionName: "requestDeposit", // asynchronous deposit
    args: [1000n, user.address, user.address],
  });
}
```


# Vault Subgraphs

{% hint style="warning" %}
**Deprecated** — the Lagoon subgraphs documented on this page have been replaced by the [Lagoon API](/developer-hub/lagoon-api), a single multi-chain GraphQL endpoint. The subgraphs remain available during the transition but new integrations should target the new API.
{% endhint %}

You can find the list of graphql endpoints [here](/resources/networks-and-addresses).

Lagoon subgraphs include all the events emitted by vaults and some of the factories.\
On top of the vault events, you can find an extra entity named PeriodSummary:

```
type PeriodSummary @entity(immutable: false) {
  id: Bytes!
  vault: Bytes! # address
  totalAssetsAtStart: BigInt!
  totalSupplyAtStart: BigInt!
  totalAssetsAtEnd: BigInt!
  totalSupplyAtEnd: BigInt!
  netTotalSupplyAtEnd: BigInt!
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  duration: BigInt!
}
```

Period summaries are not events but are piece of data that summaries key vault metrics evolution. A period being a portion of time between two updates of TotalAssets.

At the start of each period, we create a new PeriodSummary entity, meaning that as long as the vault is open, the most recent PeriodSummary will be partially filled. It will be completely filled when TotalAssets is updated again and consequently, the period is over.

Elements definition:

| Elements              | Definition                                                                                                                                          |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                  | the id of the entity.                                                                                                                               |
| `totalAssetsAtStart`  | the value of TotalAssets at the beginning of the period.                                                                                            |
| `vault`               | the address of the vault                                                                                                                            |
| `totalSupplyAtStart`  | the amount of shares at the beginning of the period.                                                                                                |
| `totalAssetsAtEnd`    | the value of TotalAssets at the end of the period, meaning after the TotalAssetsUpdate but before the potential settlements of requests.            |
| `totalSupplyAtEnd`    | the amount of shares at the end of the period, meaning after the TotalAssetsUpdate but before the settlements of requests and fee taking.           |
| `netTotalSupplyAtEnd` | the amount of shares at the end of the period, meaning after the TotalAssetsUpdate and after the fee taking but before the settlements of requests. |
| `blockNumber`         | the block number at the beginning of the period.                                                                                                    |
| `blockTimestamp`      | the timestamp at the beginning of the period.                                                                                                       |
| `duration`            | the duration of the period.                                                                                                                         |

\ <br>


# Vaults Frontend Integration

This guide provides third-party developers with everything needed to integrate Lagoon Vaults data into their frontends.

## Data Sources Overview

Lagoon Vault data comes from three primary sources:

| Data Type                     | Source                | Access Method           |
| ----------------------------- | --------------------- | ----------------------- |
| **Vault Configuration**       | Environment Variables | Environment Variables   |
| **Real-time Blockchain Data** | Smart Contracts       | RPC Calls               |
| **Computed Metrics**          | Event Processing      | Subgraph + Calculations |

## Data sources

### 1. Get All Vaults

```http
VAULTS=[] in .env
```

**Response Structure:**

```typescript
interface Vault {
  address: string;           // Vault contract address
  chainId: number;          // Blockchain network ID
  name?: string;            // Vault display name
  logoUrl?: string;         // Vault logo URL
  shortDescription?: string; // Brief description
  description?: string;     // Full description
  averageProcessing?: string; // Settlement time
  referralShare?: string;   // Referral percentage
  assetManager?: {          // Curator information
    name: string;
    url: string;
  };
  asset?: {                 // Underlying asset
    symbol: string;
    address: string;
    decimals: number;
    chainId: number;
  };
  points?: Array<{          // Reward points
    name: string;
    value: string;
    icon: string;
  }>;
  additionalAprs?: Array<{  // Additional yield sources
    asset: string;
    estimatedRewardApr?: string;
    estimatedReward30dApr?: string;
  }>;
  visible: boolean;
}
```

### 2. Get Specific Vault

```http
Filter on chaindId and address
```

### 3. Get Vault Events (for APR calculation)

{% hint style="warning" %}
**Deprecated** — the Lagoon subgraphs used below are deprecated and will be replaced by a Lagoon-hosted endpoint. They remain available during the transition. If you are building on Lagoon and rely on subgraph data, please reach out to the Lagoon team — the replacement endpoint will be announced soon.
{% endhint %}

```http
Subgraph graphQL query
```

### 4. Get price feed

```http
From NEXT_PUBLIC_ASSETS
```

## Environment Configuration

### Vault Configuration

Vaults are defined in the `VAULTS` environment variable:

```json
[
  {
    "address": "0x5864672c5e37E4E58c261014F8E94Ee31f575d47",
    "chainId": 42161,
    "logoUrl": "/9summits.png",
    "shortDescription": "ETH yield strategies",
    "description": "Detailed strategy description...",
    "averageProcessing": "7 days",
    "referralShare": "15%",
    "assetManager": {
      "name": "9Summits",
      "url": "https://www.9summits.io"
    },
    "visible": true,
    "points": [
      {
        "name": "Eigenlayer Points",
        "value": "3x",
        "icon": "https://example.com/icon.png"
      }
    ]
  }
]
```

### Asset Configuration

Assets are defined in `NEXT_PUBLIC_ASSETS`:

```json
{
  "WETH": {
    "priceFeed": {
      "address": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
      "chainId": 1
    },
    "logo": "/weth.svg"
  }
}
```

### Events configuration

```graphql
query VaultEvents($first: Int!, $vaultAddress: Bytes!) {
    deposits(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      assets
      blockNumber
      blockTimestamp
      id
      owner
      sender
      shares
      transactionHash
      vault
      logIndex
    }
    withdraws(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      assets
      blockNumber
      blockTimestamp
      id
      owner
      receiver
      sender
      shares
      transactionHash
      vault
      logIndex
    }
    depositRequests(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      assets
      blockNumber
      blockTimestamp
      id
      owner
      sender
      transactionHash
      controller
      requestId
      vault
      logIndex
    }
    redeemRequests(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      blockNumber
      blockTimestamp
      id
      owner
      sender
      shares
      transactionHash
      controller
      requestId
      vault
      logIndex
    }
    settleRedeems(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      assetsWithdrawed
      blockNumber
      blockTimestamp
      epochId
      id
      settledId
      sharesBurned
      totalAssets
      totalSupply
      transactionHash
      vault
      logIndex
    }
    settleDeposits(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      assetsDeposited
      blockNumber
      blockTimestamp
      epochId
      id
      settledId
      sharesMinted
      totalSupply
      totalAssets
      transactionHash
      vault
      logIndex
    }
    totalAssetsUpdateds(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      transactionHash
      totalAssets
      id
      blockNumber
      blockTimestamp
      vault
      logIndex
    }
    newTotalAssetsUpdateds(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      transactionHash
      totalAssets
      totalSupply
      id
      blockNumber
      blockTimestamp
      vault
      logIndex
    }
    totalAssetsUpdateds(
      first: $first
      orderBy: blockTimestamp
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      transactionHash
      totalAssets
      totalSupply
      id
      blockNumber
      blockTimestamp
      logIndex
    }
    periodSummaries(
      first: $first
      orderBy: blockNumber
      orderDirection: desc
      where: { vault: $vaultAddress }
    ) {
      id
      blockTimestamp
      blockNumber
      totalAssetsAtStart
      totalSupplyAtStart
      previousPeriodNetTotalSupplyAtEnd
      previousPeriodTotalAssetsAtEnd
      previousPeriodTotalSupplyAtEnd
      vault
    }
  }
```

## Blockchain Data Access

### Key Contract Functions

#### 1. Vault Information to complete .env data

```typescript
// Get vault state
const vaultState = await publicClient.readContract({
  address: vaultAddress,
  abi: vaultAbi,
  functionName: 'totalAssets' | 'totalSupply' | 'paused'
});

// Get price per share
const pricePerShare = await publicClient.readContract({
  address: vaultAddress,
  abi: vaultAbi,
  functionName: 'convertToAssets',
  args: [parseUnits('1', vaultDecimals)]
});
```

#### 2. Asset Information for tvl calculation

```typescript
// Get asset price from Chainlink
const assetPrice = await publicClient.readContract({
  address: priceFeedAddress,
  abi: chainlinkAbi,
  functionName: 'latestRoundData'
});
```

## Data Integration Examples

### 1. Vault APR (Computed)

APR is calculated from historical vault events:

```typescript
// Fetch vault events for APR calculation from the alchemy subgraph

// APR calculation logic (simplified)
function calculateAPR(events, vault) {
  const settlements = events.settleDeposits.concat(events.settleRedeems)
    .sort((a, b) => Number(a.blockTimestamp) - Number(b.blockTimestamp));
  
  if (settlements.length < 2) return 0;
  
  const newest = settlements[settlements.length - 1];
  const oldest = settlements[0];
  
  const timeSpan = Number(newest.blockTimestamp) - Number(oldest.blockTimestamp);
  const priceChange = newest.pricePerShare / oldest.pricePerShare;
  
  // Annualized return
  const yearsElapsed = timeSpan / (365.25 * 24 * 60 * 60);
  return (Math.pow(priceChange, 1 / yearsElapsed) - 1) * 100;
}
```

### 2. TVL (Computed)

TVL is calculated from environment config

```typescript
const { totalAssets, decimals, asset } = vault;
const totalAssetFormatted = convertBigIntToNumber({
        value: BigInt(totalAssets),
        decimals: asset.decimals,
        precision: decimals,
      });

const usdPriceFormatted = convertBigIntToNumber({
        value: BigInt(asset.usdPrice.value),
        decimals: asset.usdPrice.decimals,
        precision: asset.usdPrice.precision,
      });

const vaultTvl = totalAssetFormatted * usdPriceFormatted;
```

### 3. Vault Curators (Off-chain)

```typescript
// Curator info comes from vault configuration
// From assetManager attribute in Vault env variable
```

### 4. Vault Rewards (Off-chain + External APIs)

```typescript
// Curator info comes from vault configuration
// From rewards attribute in Vault env variab
```

## Quick Reference

### Data Source Summary

| Information          | Source                          |
| -------------------- | ------------------------------- |
| **Vault Name**       | Environment Config              |
| **Vault Address**    | Environment Config              |
| **Underlying Asset** | Environment Config + Blockchain |
| **Vault APR**        | Computed from Events            |
| **Vault Curators**   | Environment Config              |
| **Vault Rewards**    | Environment Config              |
| **TVL**              | Computed from Events            |

### Key Environment Variables

* `VAULTS`: JSON array of vault configurations
* `NEXT_PUBLIC_ASSETS`: Asset definitions with price feeds
* `THEGRAPH_URLS`: GraphQL endpoints for event data

### Important Notes

1. **APR Calculation**: Requires historical settlement events and may return 0 for new vaults
2. **Asset Prices**: Sourced from Chainlink price feeds defined in asset configuration
3. **Real-time Data**: Use blockchain RPC calls for most current vault state


# APR computations

This page describes the various methods used to compute Lagoon Vaults APR.

In order to compute those metrics, we will rely on the Period Summaries given by the [Lagoon subgraphs.](/developer-hub/integration/vault-subgraphs)

{% hint style="info" %}
Period summaries are pieces of data that summaries key vault metrics. A period being the time between two updates of TotalAssets.
{% endhint %}

As a reminder, here is what we can find inside a Period Summary:

```graphql
type PeriodSummary @entity(immutable: false) {
  id: Bytes!
  vault: Bytes! # address
  totalAssetsAtStart: BigInt!
  totalSupplyAtStart: BigInt!
  totalAssetsAtEnd: BigInt!
  totalSupplyAtEnd: BigInt! # Before fee taking
  netTotalSupplyAtEnd: BigInt! # After fee taking
  blockNumber: BigInt! 
  blockTimestamp: BigInt! # Timestamp of the start of the period
  duration: BigInt! # Duration of the period
}
```

## Single Period APR

### How to compute the linear Net APR of a single period ?

Using totalAssetsAtStart and totalSupplyAtStart we can get the pricePerShareAtStart:

```typescript
import { VaultUtils } from '@lagoon-protocol/v0-core';

const ppsAtStart = VaultUtils.convertToAssets(10n ** BigInt(vaultDecimals), {
    decimalsOffset: vaultDecimals - assetDecimals,
    totalAssets: summary.totalAssetsAtStart,
    totalSupply: summary.totalSupplyAtStart,
  });
```

Then using totalAssetsAtEnd and netTotalSupplyAtEnd we can get the netPricePerShareAtEnd:

```typescript
const netPPSAtEnd = VaultUtils.convertToAssets(10n ** BigInt(vaultDecimals), {
    decimalsOffset: vaultDecimals - assetDecimals,
    totalAssets: summary.totalAssetsAtEnd,
    totalSupply: summary.netTotalSupplyAtEnd,
  });
```

Using those 2 values, we can compute the evolution and annualize it using the period duration.

```typescript
const gain = netPPSAtEnd - ppsAtStart;
const decimals = 18;
const SECONDS_PER_YEAR = 365n * 24n * 60n * 60n;

# used to increase the precision of the result
const INCREASE_PRECISION = 10n ** BigInt(decimals + 2);


const periodYield = gain * SECONDS_PER_YEAR * INCREASE_PRECISION;
return Number(
    formatUnits(periodYield / (summary.duration * oldestPrice), decimals)
);
```

### How to compute the linear Gross APR of a single period ?

The method is exactly the same as the one used previously. The difference will reside in the totalSupply used at the end of the period. This time we use summary.totalSupplyAtEnd.

```typescript
const netPPSAtEnd = VaultUtils.convertToAssets(10n ** BigInt(vaultDecimals), {
    decimalsOffset: vaultDecimals - assetDecimals,
    totalAssets: summary.totalAssetsAtEnd,
    totalSupply: summary.totalSupplyAtEnd,
 });
```

## Multiple periods APR

### How to select a subset of periods summaries for a given duration, eg. 30 days?

1\) Find the most recent period summary within the timeframe, here 30 days. If none is found, APR is 0.

2\) Determine the start of the period by removing the duration to the end of the most recent period summary. We will call this value the `targetTimestamp`.

3\) Find the price per share at `targetTimestamp:`

* if `targetTimestamp` is older than the first periodSummary, we will use the first periodSummary timestamp and pps
* if the `targetTimestamp` is within a periodSummary `p`, we will do an linear interpolation of the price per share using the `p.startPricePerShare,` and `p.endNetPricePerShare` .

Here are a code snippet and a visual representation of the computation process:

```typescript
export function computeInterpolatedApr(
  timeFrame: number,
  {
    periodSummaries,
    vaultDecimals,
    assetDecimals,
   
  }: {
    periodSummaries: Transaction[];
    vaultDecimals: number;
    assetDecimals: number;
  }
) {
  
    if (periodSummaries.length === 0) {
      return 0;
    }
    const vaultAddress = periodSummaries[0].data.vaultAddress;
    const chainId = periodSummaries[0].chainId;

    // first we want to check if the most recent period summary is within the timeframe
    const { newest } = extractOldestAndNewestEvent(periodSummaries)!;
    assertPeriodSummary(newest);

    if (
      isTimestampOlderThan(
        Number(newest.timestamp) + Number(newest.data.duration),
        timeFrame
      )
    ) {
      return 0;
    }

    const extrapolationTargetTimestamp = Number(newest.timestamp) - timeFrame;

    const priceReference = getPriceReferenceAtTimestamp({
      periodSummaries,
      timestamp: extrapolationTargetTimestamp,
      vaultDecimals,
      assetDecimals,
    });
    if (!priceReference) {
      return 0;
    }
    const startPrice = priceReference.pricePerShare;
    const startTimestamp = priceReference.timestamp;

    const newPrice = VaultUtils.convertToAssets(
      10n ** BigInt(vaultDecimals),
      {
        decimalsOffset: vaultDecimals - assetDecimals,
        totalAssets: newest.data.totalAssetsAtStart,
        totalSupply: newest.data.totalSupplyAtStart,
      }
    );

  const netApr = computeAPR({
     newPrice,
     newTimestamp: newest.timestamp,
     oldPrice: startPrice,
     oldTimestamp: startTimestamp,
   });
}

/**
 * @description Get the most recent and oldest events of an array of sorted events.
 * @param events - The array of events to get the most recent and oldest events from.
 * @returns The most recent and oldest events.
 */
export function extractOldestAndNewestEvent<T extends { timestamp: BigIntish }>(
  events: T[]
):
  | {
      oldest: T;
      newest: T;
    }
  | undefined {
  if (events.length == 0) {
    return undefined;
  } else {
    const isAscending =
      events[0].timestamp < events[events.length - 1].timestamp;
    return {
      oldest: isAscending ? events[0] : events[events.length - 1],
      newest: isAscending ? events[events.length - 1] : events[0],
    };
  }
}

export function isTimestampBeforeDuration(
  timestamp: number,
  duration: number
): boolean {
  return timestamp < new Date().getTime() / 1000 - duration;
}

/**
 * Get the price per share at a timestamp, using an interpolation between inside a period summary. If the target timestamp is too old, we return the closest price per share.
 *  @param periodSummariesSubset - The period summaries to get a subset of, expected to be sorted by blockTimestamp.
 * @param timestamp - The timestamp to get the price per share at.
 * @param vaultDecimals - The number of decimals the vault has.
 * @param assetDecimals - The number of decimals the asset has.
 * @returns The price per share at the timestamp and the final timestamp selected.
 */
export function getPriceReferenceAtTimestamp({
  periodSummaries,
  timestamp,
  vaultDecimals,
  assetDecimals,
}: {
  periodSummaries: Transaction[];
  timestamp: number;
  vaultDecimals: number;
  assetDecimals: number;
}):
  | {
      pricePerShare: bigint;
      timestamp: BigIntish;
    }
  | undefined {
  const decimalsOffset = vaultDecimals - assetDecimals;
  const computePps = (totalAssets: bigint, totalSupply: bigint) =>
    VaultUtils.convertToAssets(10n ** BigInt(vaultDecimals), {
      decimalsOffset,
      totalAssets,
      totalSupply,
    });
  if (periodSummaries.length === 0) {
    throw new Error('GetPricePerShareAtTimestamp: periodSummaries is empty');
  }
  const isAscending =
    periodSummaries[0].timestamp <
    periodSummaries[periodSummaries.length - 1].timestamp;

  // we want the period summaries to be in descending order
  if (isAscending) {
    // make a deep copy of the array
    const reversed: Transaction[] = [...periodSummaries];
    reversed.reverse();
    periodSummaries = reversed;
  }

  // earliest summary older than timestamp
  let summary = periodSummaries.find((p) => Number(p.timestamp) <= timestamp);
  if (!summary) {
    // if no summary before timestamp, we use the oldest summary
    // usually the pps will be 1 but we might handle vault migrations with a native
    // pps different from 1
    summary = periodSummaries[periodSummaries.length - 1];

    const pricePerShare = computePps(
      summary.data.totalAssetsAtStart,
      summary.data.totalSupplyAtStart
    );
    return {
      pricePerShare,
      timestamp: Number(summary.timestamp),
    };
  }
 
  if (Number(summary.timestamp) + Number(summary.data.duration) < timestamp) {
    throw new Error(
      `GetPricePerShareAtTimestamp: summary before timestamp doesn't end after timestamp. Period summary: ${summary.timestamp} + ${summary.data.duration} < ${timestamp}`
    );
  } // this should not happen

  const atStartPps = computePps(
    summary.data.totalAssetsAtStart,
    summary.data.totalSupplyAtStart
  );

  const atEndPps = computePps(
    summary.data.totalAssetsAtEnd,
    summary.data.netTotalSupplyAtEnd
  );

  const ppsEvolutionDuringPeriod = atEndPps - atStartPps;

  // timepast between start of summary and timestamp
  const timePast = timestamp - Number(summary.timestamp);

  // we do an interpolation between the start and end price per share of the summary
  const ppsEvolution =
    (ppsEvolutionDuringPeriod * BigInt(timePast)) /
    BigInt(summary.data.duration);

  return {
    pricePerShare: atStartPps + ppsEvolution,
    timestamp,
  };
}

```

##

<figure><img src="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FKNXkyIbE6nPZhySotdLC%2FAPR%20computation%202.png?alt=media&amp;token=400cdbc0-9bfe-48bf-88ab-508ee6725f7f" alt=""><figcaption></figcaption></figure>

## How to compute a linear 30day Gross APR ?

It is not possible to do this, as it would only remove the fees for the last period used, which is not an accurate indicator of what the yield would have been without fees over multiple periods.

## How to compute a Time-Weighted Rate Return (TWRR) 30day ?

The [summaries subset selection](#how-to-select-a-subset-of-periods-summaries-for-a-given-duration-eg.-30-days) will be the same as previously described.

In this computation we will do the average of the linear APR of the various periods, weighted by their duration.

Here is an example:

| Period | Duration | APR |
| ------ | -------- | --- |
| 1      | 400      | 10% |
| 2      | 600      | 20% |

TotalDuration = 400 + 600 = 1000.

Period 1 Time Weighted APR (P1TW) : 400 / 1000 \* 10% = 0.4 \* 10% = 4%.

Period 2 Time Weighted APR (P2TW) : 600 / 1000 \* 20% = 0.6 \* 20% = 12%.

TWRR : P1TW + P2TW = 16%.

Here is a typescript example to compute the gross TWRR over a subset of Period Summaries.

{% hint style="info" %}
We compute the Gross TWRR because we use summary.totalSupplyAtEnd. If we use summary.netTotalSupplyAtEnd we will get the Net TWRR.
{% endhint %}

```typescript
function computeTWRR(
    summaries: PeriodSummaryEvent[],
    decimals: number,
  ): number
     {
    let grossTWR = 0;
    let totalDuration = 0;

    for (let i = 0; i < summaries.length; i++) {
      const summary = summaries[i];

      const ppsAtStart = VaultUtils.convertToAssets(10n ** BigInt(vaultDecimals), {
        decimalsOffset: vaultDecimals - assetDecimals,
        totalAssets: summary.totalAssetsAtStart,
        totalSupply: summary.totalSupplyAtStart,
      });
      
      const grossPPSAtEnd = VaultUtils.convertToAssets(10n ** BigInt(vaultDecimals), {
        decimalsOffset: vaultDecimals - assetDecimals,
        totalAssets: summary.totalAssetsAtEnd,
        totalSupply: summary.totalSupplyAtEnd,
      });
      

      const duration = Number(currentPeriod.duration);

      const grossApr = this.computeApr({
        startPricePerShare: pricePerShareAtStart,
        endPricePerShare: grossPricePerShareAtEnd,
        duration,
      });

      grossTWR += grossApr * duration;
      totalDuration += duration;
    }
    return grossTWR: grossTWR / totalDuration;
  }
```


# Compute vault share valuation

*The method described below is identical to that used for an ERC4626 vault.*

To calculate the value of a single share, first determine the price per share of the vault in terms of assets. To achieve this, call the function `convertToAssets(uint256 sharers) returns (uint256 assets);` with the argument set to `10 ** vault.decimals().`

The price per share is given with a scaling factor of `10 ** underlyingAsset.decimals`. To obtain a standard value, you have to divide the price by this scaling factor.

To calculate the value of a share in dollars, multiply the price per share by the price of the underlying asset in dollars:\
`pricePerShare / 10 ** underlyingAsset.decimals * underlyingAssetPriceInDollar = shareValueInDollar`.


# Lagoon API

Off-chain GraphQL API exposing vault state, user positions, and event history across all supported chains.

The Lagoon API is a single multi-chain GraphQL endpoint that returns indexed vault data — current state, historical state, user positions, the full event stream, and reference data such as chains, assets, curators, and integrators.

```
POST https://api.lagoon.finance/query
Content-Type: application/json
```

Reads are public; no API key is required.

## Quickstart

Confirm connectivity and check indexing health for every chain in one call:

```graphql
{
  _meta {
    lastIndexedBlocks {
      chainId
      number
      hash
      chain { name }
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=%7B%0A%20%20_meta%20%7B%0A%20%20%20%20lastIndexedBlocks%20%7B%0A%20%20%20%20%20%20chainId%0A%20%20%20%20%20%20number%0A%20%20%20%20%20%20hash%0A%20%20%20%20%20%20chain%20%7B%20name%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

Same query as a curl call:

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"{ _meta { lastIndexedBlocks { chainId number hash chain { name } } } }"}'
```

`_meta.lastIndexedBlocks` returns the most recent tracked block per chain. An hourly health-check event guarantees the value advances at least once per hour even on quiet chains — if a chain is more than \~1 hour behind, the indexer is lagging.

{% hint style="success" %}
Open <https://api.lagoon.finance/query> in a browser to launch **Apollo Sandbox**, an interactive schema explorer. Introspection is enabled, so the full schema (types, fields, descriptions) is browsable without any client setup — Sandbox is the authoritative reference for every field name in this documentation. Throughout these docs, "Try in Apollo Sandbox" links open Sandbox with the example query already populated in the Operation panel.
{% endhint %}

## Where to go next

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Common queries</strong></td><td>Recipes for the queries integrators reach for first — list vaults, fetch a vault, get a user's positions, stream events, read historical state, global TVL.</td><td><a href="/developer-hub/lagoon-api/common-queries">Common queries</a></td></tr><tr><td><strong>Conventions</strong></td><td>Pagination, filtering, ordering, scalar formats, and how to query historical data and indexing health.</td><td><a href="/developer-hub/lagoon-api/conventions">Conventions</a></td></tr><tr><td><strong>Mutations</strong></td><td>The single mutation today — updating off-chain vault metadata with an EIP-712 signature from the vault owner.</td><td><a href="/developer-hub/lagoon-api/mutations">Mutations</a></td></tr><tr><td><strong>Smart Contract Reference</strong></td><td>On-chain counterpart to this API — every external entry point on the v0.6.0 vault implementation.</td><td><a href="/developer-hub/smart-contract-reference">Smart Contract Reference</a></td></tr></tbody></table>


# Common queries

Copy-pasteable curl recipes for the queries integrators reach for first.

Every recipe below shows the query itself in a `graphql` block, a one-click link that opens [Apollo Sandbox](https://api.lagoon.finance/query) with the query pre-loaded, and the equivalent `curl` call. Replace the example vault address, chain ID, or user address with your own and the queries will return live data.

## Recipes

| # | Recipe                                                                            | What it returns                                                            |
| - | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| 1 | [List vaults on a chain](#list-vaults-on-a-chain)                                 | Paginated vaults filtered by chain & visibility, with state and APR.       |
| 2 | [Get a single vault by address](#get-a-single-vault-by-address)                   | One vault with full current state, asset, and chain.                       |
| 3 | [Get a user's positions across vaults](#get-a-users-positions-across-vaults)      | A user's share balance and pending/claimable deposits and redeems.         |
| 4 | [Stream vault events](#stream-vault-events)                                       | Recent on-chain events for a vault, typed via the `TransactionData` union. |
| 5 | [Historical vault state at a timestamp](#historical-vault-state-at-a-timestamp)   | Point-in-time reconstruction via `stateAt`.                                |
| 6 | [Global Lagoon TVL](#global-lagoon-tvl)                                           | Aggregate USD TVL across all Lagoon vaults.                                |
| — | [How the Lagoon dApp uses these queries](#how-the-lagoon-dapp-uses-these-queries) | Patterns from the production frontend worth copying.                       |

## List vaults on a chain

Top vaults on Ethereum by USD TVL, paginated, only those visible on the Lagoon frontend:

```graphql
query ListVaults {
  vaults(
    first: 10
    skip: 0
    orderBy: totalAssetsUsd
    orderDirection: desc
    where: { chainId_eq: 1, isVisible_eq: true }
  ) {
    items {
      address
      name
      symbol
      state {
        totalAssetsUsd
        pricePerShareUsd
        yearlyApr { linearNetApr twrrNetApr }
      }
    }
    pageInfo { hasNextPage totalCount }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20ListVaults%20%7B%0A%20%20vaults%28%0A%20%20%20%20first%3A%2010%0A%20%20%20%20skip%3A%200%0A%20%20%20%20orderBy%3A%20totalAssetsUsd%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%20%20where%3A%20%7B%20chainId_eq%3A%201%2C%20isVisible_eq%3A%20true%20%7D%0A%20%20%29%20%7B%0A%20%20%20%20items%20%7B%0A%20%20%20%20%20%20address%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20symbol%0A%20%20%20%20%20%20state%20%7B%0A%20%20%20%20%20%20%20%20totalAssetsUsd%0A%20%20%20%20%20%20%20%20pricePerShareUsd%0A%20%20%20%20%20%20%20%20yearlyApr%20%7B%20linearNetApr%20twrrNetApr%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20pageInfo%20%7B%20hasNextPage%20totalCount%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query ListVaults { vaults(first: 10, skip: 0, orderBy: totalAssetsUsd, orderDirection: desc, where: { chainId_eq: 1, isVisible_eq: true }) { items { address name symbol state { totalAssetsUsd pricePerShareUsd yearlyApr { linearNetApr twrrNetApr } } } pageInfo { hasNextPage totalCount } } }"}'
```

Returns `items` (the vaults) plus `pageInfo.totalCount` for total match count and `pageInfo.hasNextPage` for paging.

## Get a single vault by address

Fetch one vault with its current state, underlying asset, and chain:

```graphql
query GetVault {
  vaultByAddress(
    address: "0x936facdf10c8c36294e7b9d28345255539d81bc7"
    chainId: 1
  ) {
    address
    name
    symbol
    creationDate
    asset { address symbol decimals }
    chain { id name }
    state {
      totalAssets
      totalSupply
      pricePerShare
      pricePerShareUsd
      totalAssetsUsd
      managementFee
      performanceFee
      syncMode
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20GetVault%20%7B%0A%20%20vaultByAddress%28%0A%20%20%20%20address%3A%20%220x936facdf10c8c36294e7b9d28345255539d81bc7%22%0A%20%20%20%20chainId%3A%201%0A%20%20%29%20%7B%0A%20%20%20%20address%0A%20%20%20%20name%0A%20%20%20%20symbol%0A%20%20%20%20creationDate%0A%20%20%20%20asset%20%7B%20address%20symbol%20decimals%20%7D%0A%20%20%20%20chain%20%7B%20id%20name%20%7D%0A%20%20%20%20state%20%7B%0A%20%20%20%20%20%20totalAssets%0A%20%20%20%20%20%20totalSupply%0A%20%20%20%20%20%20pricePerShare%0A%20%20%20%20%20%20pricePerShareUsd%0A%20%20%20%20%20%20totalAssetsUsd%0A%20%20%20%20%20%20managementFee%0A%20%20%20%20%20%20performanceFee%0A%20%20%20%20%20%20syncMode%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query GetVault { vaultByAddress(address: \"0x936facdf10c8c36294e7b9d28345255539d81bc7\", chainId: 1) { address name symbol creationDate asset { address symbol decimals } chain { id name } state { totalAssets totalSupply pricePerShare pricePerShareUsd totalAssetsUsd managementFee performanceFee syncMode } } }"}'
```

`state` carries every live metric (TVL, supply, price-per-share, fees, sync mode, guardrails, roles). Pick only the fields you need.

## Get a user's positions across vaults

A user's full position on a given chain — share balance, pending and claimable deposits, pending and claimable redeems — in one round trip:

```graphql
query GetUserPositions($address: Address!, $chainId: Int!) {
  userByAddress(address: $address, chainId: $chainId) {
    address
    vaultPositions {
      vault { address name symbol }
      state {
        balance
        usd
        pendingDeposit { assets shares }
        pendingRedeem { assets shares isCancelable }
        claimableDeposit { assets shares assetsActualized }
        claimableRedeem { assets shares }
      }
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20GetUserPositions%28%24address%3A%20Address%21%2C%20%24chainId%3A%20Int%21%29%20%7B%0A%20%20userByAddress%28address%3A%20%24address%2C%20chainId%3A%20%24chainId%29%20%7B%0A%20%20%20%20address%0A%20%20%20%20vaultPositions%20%7B%0A%20%20%20%20%20%20vault%20%7B%20address%20name%20symbol%20%7D%0A%20%20%20%20%20%20state%20%7B%0A%20%20%20%20%20%20%20%20balance%0A%20%20%20%20%20%20%20%20usd%0A%20%20%20%20%20%20%20%20pendingDeposit%20%7B%20assets%20shares%20%7D%0A%20%20%20%20%20%20%20%20pendingRedeem%20%7B%20assets%20shares%20isCancelable%20%7D%0A%20%20%20%20%20%20%20%20claimableDeposit%20%7B%20assets%20shares%20assetsActualized%20%7D%0A%20%20%20%20%20%20%20%20claimableRedeem%20%7B%20assets%20shares%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query GetUserPositions($address: Address!, $chainId: Int!) { userByAddress(address: $address, chainId: $chainId) { address vaultPositions { vault { address name symbol } state { balance usd pendingDeposit { assets shares } pendingRedeem { assets shares isCancelable } claimableDeposit { assets shares assetsActualized } claimableRedeem { assets shares } } } } }",
    "variables": { "address": "0xUSER", "chainId": 1 }
  }'
```

This is the off-chain equivalent of the three on-chain calls described in [Get a user position](/developer-hub/integration/get-a-user-position) (`balanceOf` + `maxMint` + `pendingRedeemRequest`), plus the dollar value and the claimable-deposit current-price actualization.

## Stream vault events

Most recent settlement events for a vault, with the event payload pulled from the `TransactionData` union via inline fragments:

```graphql
query StreamVaultEvents {
  transactions(
    first: 20
    skip: 0
    orderBy: timestamp
    orderDirection: desc
    where: {
      vault_in: ["0x936facdf10c8c36294e7b9d28345255539d81bc7"]
      type_in: [TotalAssetsUpdated, SettleDeposit, SettleRedeem, FeeTaken]
    }
  ) {
    items {
      timestamp
      blockNumber
      hash
      type
      data {
        __typename
        ... on TotalAssetsUpdated { totalAssets }
        ... on SettleDeposit { totalAssets totalSupply }
        ... on SettleRedeem { totalAssets totalSupply }
        ... on FeeTaken { feeType totalShares }
      }
    }
    pageInfo { hasNextPage totalCount }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20StreamVaultEvents%20%7B%0A%20%20transactions%28%0A%20%20%20%20first%3A%2020%0A%20%20%20%20skip%3A%200%0A%20%20%20%20orderBy%3A%20timestamp%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20vault_in%3A%20%5B%220x936facdf10c8c36294e7b9d28345255539d81bc7%22%5D%0A%20%20%20%20%20%20type_in%3A%20%5BTotalAssetsUpdated%2C%20SettleDeposit%2C%20SettleRedeem%2C%20FeeTaken%5D%0A%20%20%20%20%7D%0A%20%20%29%20%7B%0A%20%20%20%20items%20%7B%0A%20%20%20%20%20%20timestamp%0A%20%20%20%20%20%20blockNumber%0A%20%20%20%20%20%20hash%0A%20%20%20%20%20%20type%0A%20%20%20%20%20%20data%20%7B%0A%20%20%20%20%20%20%20%20__typename%0A%20%20%20%20%20%20%20%20...%20on%20TotalAssetsUpdated%20%7B%20totalAssets%20%7D%0A%20%20%20%20%20%20%20%20...%20on%20SettleDeposit%20%7B%20totalAssets%20totalSupply%20%7D%0A%20%20%20%20%20%20%20%20...%20on%20SettleRedeem%20%7B%20totalAssets%20totalSupply%20%7D%0A%20%20%20%20%20%20%20%20...%20on%20FeeTaken%20%7B%20feeType%20totalShares%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20pageInfo%20%7B%20hasNextPage%20totalCount%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query StreamVaultEvents { transactions(first: 20, skip: 0, orderBy: timestamp, orderDirection: desc, where: { vault_in: [\"0x936facdf10c8c36294e7b9d28345255539d81bc7\"], type_in: [TotalAssetsUpdated, SettleDeposit, SettleRedeem, FeeTaken] }) { items { timestamp blockNumber hash type data { __typename ... on TotalAssetsUpdated { totalAssets } ... on SettleDeposit { totalAssets totalSupply } ... on SettleRedeem { totalAssets totalSupply } ... on FeeTaken { feeType totalShares } } } pageInfo { hasNextPage totalCount } } }"}'
```

`TransactionData` is a union — request only the variants you care about with `... on EventName` fragments. The full list of event types is in the `TransactionType` enum (browsable in Sandbox). See [Key data structures and epoch mechanism](/developer-hub/key-data-structures-and-epoch-mechanism) for the semantics of each event.

## Historical vault state at a timestamp

Reconstruct a vault as it existed at a past Unix timestamp:

```graphql
query HistoricalVaultState {
  vaultByAddress(
    address: "0x936facdf10c8c36294e7b9d28345255539d81bc7"
    chainId: 1
  ) {
    stateAt(timestamp: 1780000000) {
      totalAssets
      totalSupply
      pricePerShare
      pricePerShareUsd
      totalAssetsUsd
      managementFee
      performanceFee
      state
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20HistoricalVaultState%20%7B%0A%20%20vaultByAddress%28%0A%20%20%20%20address%3A%20%220x936facdf10c8c36294e7b9d28345255539d81bc7%22%0A%20%20%20%20chainId%3A%201%0A%20%20%29%20%7B%0A%20%20%20%20stateAt%28timestamp%3A%201780000000%29%20%7B%0A%20%20%20%20%20%20totalAssets%0A%20%20%20%20%20%20totalSupply%0A%20%20%20%20%20%20pricePerShare%0A%20%20%20%20%20%20pricePerShareUsd%0A%20%20%20%20%20%20totalAssetsUsd%0A%20%20%20%20%20%20managementFee%0A%20%20%20%20%20%20performanceFee%0A%20%20%20%20%20%20state%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"query HistoricalVaultState { vaultByAddress(address: \"0x936facdf10c8c36294e7b9d28345255539d81bc7\", chainId: 1) { stateAt(timestamp: 1780000000) { totalAssets totalSupply pricePerShare pricePerShareUsd totalAssetsUsd managementFee performanceFee state } } }"}'
```

`stateAt` returns `null` (or a `BAD_USER_INPUT` error) for timestamps before the vault's first indexed state. For a time series of any of these fields, use `stateHistory` instead — see [Conventions → Historical data](/developer-hub/lagoon-api/conventions#historical-data).

## Global Lagoon TVL

```graphql
{
  getGlobalTVL
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=%7B%0A%20%20getGlobalTVL%0A%7D)

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{"query":"{ getGlobalTVL }"}'
```

Returns a single `Float` — the aggregate USD TVL across all Lagoon vaults, sourced from DeFiLlama.

## How the Lagoon dApp uses these queries

The production [app.lagoon.finance](https://app.lagoon.finance) frontend is built on exactly this API. A few patterns from that integration that are worth copying:

* **Server-side fetch, no client library.** The dApp uses plain `fetch` with `cache: 'no-store'` from Next.js route handlers — no Apollo or urql. Letting the framework handle revalidation (ISR / `revalidate` directives) is simpler than maintaining a normalized cache, and the API returns whole entities anyway.
* **Compose queries from fragments.** Vault listing pages and vault detail pages share a `VaultFields` fragment but pick different sub-fragments (`VaultFieldsListLight` skips APR data for fast homepage rendering; `VaultFieldsDetail` adds composition, fees, and roles). Define one fragment per logical view and interpolate into multiple queries.
* **`isVisible_eq: true` for frontend listings.** Vaults flagged as not visible are still indexed and queryable, but should be filtered out of any list shown to end users.
* **Page with `pageInfo.totalCount` and `hasNextPage`.** The dApp's transaction-history view does offset pagination with a small `first` value (e.g. 10) and uses `totalCount` to render the page count up-front.
* **Health-check on every request batch.** Route handlers that fan out to multiple queries include `_meta { lastIndexedBlocks { chainId number } }` so the UI can surface "data may be stale" when a chain is more than \~1 hour behind.
* **Lowercased addresses in filters.** Always normalize address inputs (e.g. with viem's `getAddress` / `.toLowerCase()`) before passing them to `_eq` / `_in` filters.


# Conventions

Pagination, filtering, ordering, scalar formats, historical data, and indexing health.

The same shape applies to every paginated query in the API. Once you've used one, the others read the same way.

{% hint style="warning" %}
**The schema is the source of truth.** This page documents conventions, not every field. For exhaustive type and field listings, use [Apollo Sandbox](https://api.lagoon.finance/query) — introspection is enabled.
{% endhint %}

## Pagination

All list queries are offset-paginated with two required arguments:

| Argument | Type   | Description                              |
| -------- | ------ | ---------------------------------------- |
| `first`  | `Int!` | Page size. Keep ≤ 100.                   |
| `skip`   | `Int!` | Offset from the start of the result set. |

The response is wrapped in a `Page` type — for example `VaultPage`, `TransactionPage`, `UserPage` — with two fields:

| Field      | Type         | Description                   |
| ---------- | ------------ | ----------------------------- |
| `items`    | `[Entity!]!` | The current page of entities. |
| `pageInfo` | `PageInfo!`  | Pagination metadata.          |

`PageInfo` exposes `count`, `limit`, `skip`, `totalCount`, `hasNextPage`, `hasPreviousPage`. Always request `pageInfo { hasNextPage totalCount }` if you need to know when to stop.

## Filtering

Each list query accepts a typed `where: EntityFilterInput`. Filter fields follow a `<field>_<op>` naming convention:

| Suffix                          | Meaning                        | Example                                   |
| ------------------------------- | ------------------------------ | ----------------------------------------- |
| `_eq`                           | equals                         | `chainId_eq: 1`                           |
| `_not_eq`                       | not equals                     | `state_not_eq: Closed`                    |
| `_in`                           | in array                       | `address_in: ["0x…", "0x…"]`              |
| `_not_in`                       | not in array                   | `chainId_not_in: [137, 10]`               |
| `_contains`                     | array contains value           | `curatorIds_contains: "0x…"`              |
| `_contains_any`                 | array contains any of          | `curatorIds_contains_any: ["0x…", "0x…"]` |
| `_gt` / `_gte` / `_lt` / `_lte` | numeric / timestamp comparison | `timestamp_gt: 1780000000`                |

Not every field on every entity supports every operator — Apollo Sandbox lists exactly which `<field>_<op>` keys exist per filter input.

Example: visible Ethereum vaults with a specific symbol whitelist:

```graphql
query FilterExample {
  vaults(
    first: 50
    skip: 0
    orderBy: totalAssetsUsd
    orderDirection: desc
    where: {
      chainId_eq: 1
      isVisible_eq: true
      symbol_in: ["T9cbBTC", "T9USDC"]
    }
  ) {
    items { address name symbol }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20FilterExample%20%7B%0A%20%20vaults%28%0A%20%20%20%20first%3A%2050%0A%20%20%20%20skip%3A%200%0A%20%20%20%20orderBy%3A%20totalAssetsUsd%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20chainId_eq%3A%201%0A%20%20%20%20%20%20isVisible_eq%3A%20true%0A%20%20%20%20%20%20symbol_in%3A%20%5B%22T9cbBTC%22%2C%20%22T9USDC%22%5D%0A%20%20%20%20%7D%0A%20%20%29%20%7B%0A%20%20%20%20items%20%7B%20address%20name%20symbol%20%7D%0A%20%20%7D%0A%7D)

## Ordering

Two arguments, both with safe defaults:

| Argument         | Type               | Description                                                                                        |
| ---------------- | ------------------ | -------------------------------------------------------------------------------------------------- |
| `orderBy`        | `<Entity>OrderBy!` | Typed enum, per-entity. For example `VaultOrderBy.totalAssetsUsd`, `TransactionOrderBy.timestamp`. |
| `orderDirection` | `OrderDirection`   | `asc` or `desc`. Defaults to `asc`.                                                                |

## Scalars

| Scalar       | Format                                   | Notes                                                                            |
| ------------ | ---------------------------------------- | -------------------------------------------------------------------------------- |
| `Address`    | `0x`-prefixed lowercase hex string       | Returned lowercase; accepted in either case.                                     |
| `BigInt`     | Decimal string                           | Used for token amounts, block numbers, Unix timestamps, basis points. JSON-safe. |
| `HexString`  | `0x`-prefixed hex string                 | Transaction hashes, block hashes.                                                |
| `JSONObject` | Arbitrary JSON object                    | Free-form metadata.                                                              |
| `Float`      | IEEE-754 double                          | USD values, APRs, percentages.                                                   |
| Timestamps   | Unix **seconds**, as `Float` or `BigInt` | Not milliseconds.                                                                |

## Historical data

Every vault exposes its own history without a separate query:

### `vault.stateAt(timestamp: Int!)`

Point-in-time reconstruction of the vault from indexed onchain history. Returns a `HistoricalVaultState` with the same metric fields as `state` (totalAssets, pricePerShare, fees, roles, access mode, guardrails, APRs, …). Returns `null` (or `BAD_USER_INPUT`) for timestamps before the vault's first state row.

### `vault.stateHistory`

Time series of every field in `state` that has a recorded history (price per share, total assets, supply, fees, etc.). Each field returns an ascending list of data points within an optional `TimeRangeOptions` window (default: from vault creation to now). **Capped at the 1000 most recent events per underlying table** — for full backfills, page through `transactions` directly.

`stateHistory` is the building block for rolling your own APR or PnL — see [APR computations](/developer-hub/integration/apr-computations) for the formulas used by the indexer.

## Request limits

| Limit          | If exceeded                                                                                                                 |
| -------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Query depth    | Restructure into shallower queries.                                                                                         |
| Max complexity | Trim fields from the selection set, or lower `first`.                                                                       |
| Rate limit     | You'll receive `HTTP 429`. Back off and retry with exponential backoff; contact the Lagoon team if you need a higher limit. |

## Indexing health

`_meta.lastIndexedBlocks` returns the most recent block per chain that produced a tracked event. Pass `chainIds` to scope the response:

```graphql
query IndexingHealth {
  _meta(chainIds: [1, 8453]) {
    lastIndexedBlocks {
      chainId
      number
      hash
      chain { name }
    }
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=query%20IndexingHealth%20%7B%0A%20%20_meta%28chainIds%3A%20%5B1%2C%208453%5D%29%20%7B%0A%20%20%20%20lastIndexedBlocks%20%7B%0A%20%20%20%20%20%20chainId%0A%20%20%20%20%20%20number%0A%20%20%20%20%20%20hash%0A%20%20%20%20%20%20chain%20%7B%20name%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

This value can trail the chain head on low-activity chains, but lag is bounded to \~1 hour. If a chain reports a number more than \~1 hour behind, treat its data as stale.


# Mutations

Updating off-chain vault metadata with an EIP-712 signature from the vault owner.

The API exposes a single mutation today, used by vault owners to update **off-chain metadata** — the descriptive fields shown on the Lagoon frontend. None of these fields affect on-chain behaviour; for on-chain configuration, use the vault contract directly (see [Smart Contract Reference](/developer-hub/smart-contract-reference)).

## `updateVaultMetadata`

```graphql
mutation UpdateVaultMetadata(
  $vault: Address!
  $chainId: Int!
  $input: UpdateVaultMetadataInput!
  $signature: String!
  $deadline: Int!
) {
  updateVaultMetadata(
    vaultAddress: $vault
    chainId: $chainId
    input: $input
    signature: $signature
    deadline: $deadline
  ) {
    address
    name
    description
    shortDescription
    maxCapacity
    transparencyUrl
  }
}
```

[**Try in Apollo Sandbox →**](https://api.lagoon.finance/query?document=mutation%20UpdateVaultMetadata%28%0A%20%20%24vault%3A%20Address%21%0A%20%20%24chainId%3A%20Int%21%0A%20%20%24input%3A%20UpdateVaultMetadataInput%21%0A%20%20%24signature%3A%20String%21%0A%20%20%24deadline%3A%20Int%21%0A%29%20%7B%0A%20%20updateVaultMetadata%28%0A%20%20%20%20vaultAddress%3A%20%24vault%0A%20%20%20%20chainId%3A%20%24chainId%0A%20%20%20%20input%3A%20%24input%0A%20%20%20%20signature%3A%20%24signature%0A%20%20%20%20deadline%3A%20%24deadline%0A%20%20%29%20%7B%0A%20%20%20%20address%0A%20%20%20%20name%0A%20%20%20%20description%0A%20%20%20%20shortDescription%0A%20%20%20%20maxCapacity%0A%20%20%20%20transparencyUrl%0A%20%20%7D%0A%7D)

### Input fields

`UpdateVaultMetadataInput` — every field is optional; omitted fields are left unchanged.

| Field               | Type     | Description                                                                                                                                                            |
| ------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `description`       | `String` | Detailed description of the vault and its strategy.                                                                                                                    |
| `shortDescription`  | `String` | One-line summary.                                                                                                                                                      |
| `maxCapacity`       | `String` | Off-chain soft cap on total deposits, surfaced to the frontend so vault operators can limit incoming deposits via the UI. Purely informative, no on-chain enforcement. |
| `averageSettlement` | `Float`  | Average settlement time in hours.                                                                                                                                      |
| `transparencyUrl`   | `String` | URL to a transparency report or dashboard.                                                                                                                             |

### Authentication

The mutation is gated by an **EIP-712 signature** from the vault owner. The server recovers the signer from `signature` over the typed data, then checks that the recovered address matches the on-chain owner of `vaultAddress` on `chainId`. `deadline` is a Unix-seconds timestamp after which the signature is rejected (replay protection); the Lagoon dApp uses a 5-minute TTL.

#### Domain

```ts
{
  name: 'Lagoon Vault Admin',
  version: '1',
  chainId,            // uint256 — same chainId as the mutation argument
  verifyingContract,  // address — same vaultAddress as the mutation argument
}
```

#### Typed data

`primaryType: 'UpdateVaultMetadata'`

```ts
UpdateVaultMetadata: [
  { name: 'chainId',           type: 'uint256' },
  { name: 'vaultAddress',      type: 'address' },
  { name: 'description',       type: 'string'  },
  { name: 'shortDescription',  type: 'string'  },
  { name: 'transparencyUrl',   type: 'string'  },
  { name: 'maxCapacity',       type: 'string'  },
  { name: 'averageSettlement', type: 'string'  },
  { name: 'deadline',          type: 'uint256' },
]
```

{% hint style="warning" %}
**Defaults must match exactly or the signature will silently fail to verify.**

* Omitted `string` fields → `''` (empty string)
* Omitted `uint256` fields → `0n`
* `averageSettlement` is hashed as a **string**, not a number — format with `value.toFixed(6)` so the canonical decimal representation matches the backend.
  {% endhint %}

#### Signing with viem / wagmi

```ts
import { useSignTypedData } from 'wagmi';

const signature = await signTypedDataAsync({
  domain: {
    name: 'Lagoon Vault Admin',
    version: '1',
    chainId: BigInt(chainId),
    verifyingContract: vaultAddress,
  },
  types: {
    UpdateVaultMetadata: [
      { name: 'chainId',           type: 'uint256' },
      { name: 'vaultAddress',      type: 'address' },
      { name: 'description',       type: 'string'  },
      { name: 'shortDescription',  type: 'string'  },
      { name: 'transparencyUrl',   type: 'string'  },
      { name: 'maxCapacity',       type: 'string'  },
      { name: 'averageSettlement', type: 'string'  },
      { name: 'deadline',          type: 'uint256' },
    ],
  },
  primaryType: 'UpdateVaultMetadata',
  message: {
    chainId: BigInt(chainId),
    vaultAddress,
    description:       input.description       ?? '',
    shortDescription:  input.shortDescription  ?? '',
    transparencyUrl:   input.transparencyUrl   ?? '',
    maxCapacity:       input.maxCapacity       ?? '',
    averageSettlement: input.averageSettlement != null
      ? input.averageSettlement.toFixed(6)
      : '',
    deadline: BigInt(deadline),
  },
});
```

### Example call

Shape of the call (the `signature` below is a placeholder — produce yours by signing the EIP-712 payload with the vault owner's key):

```bash
curl -sS -X POST https://api.lagoon.finance/query \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation UpdateVaultMetadata($vault: Address!, $chainId: Int!, $input: UpdateVaultMetadataInput!, $signature: String!, $deadline: Int!) { updateVaultMetadata(vaultAddress: $vault, chainId: $chainId, input: $input, signature: $signature, deadline: $deadline) { address name description shortDescription maxCapacity transparencyUrl } }",
    "variables": {
      "vault": "0x936facdf10c8c36294e7b9d28345255539d81bc7",
      "chainId": 1,
      "input": { "shortDescription": "rETH yield strategy.", "averageSettlement": 24 },
      "signature": "0x...",
      "deadline": 1800000000
    }
  }'
```

The mutation returns the updated `Vault` so the client can read back the new metadata without a follow-up query.


# Networks & Addresses

The Lagoon protocol contracts deployed on every network the protocol is aware of — the **Vault Factory**, the **ProtocolRegistry**, and the **vault logic implementations** registered on that registry.

{% tabs %}
{% tab title="Arbitrum" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://arbiscan.io/address/0x9de724b0efee0fba07fe21a16b9bf9bbb5204fb4">0x9de724b0efee0fba07fe21a16b9bf9bbb5204fb4</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://arbiscan.io/address/0x6da4d1859ba1d02d095d2246142cdad52233e27c">0x6da4d1859ba1d02d095d2246142cdad52233e27c</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://arbiscan.io/address/0xe50554ec802375c9c3f9c087a8a7bb8c26d3dedf">0xe50554ec802375c9c3f9c087a8a7bb8c26d3dedf</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://arbiscan.io/address/0x3f5a9e1d82c595d14ba93c97eb8a77928cfdee70">0x3f5a9e1d82c595d14ba93c97eb8a77928cfdee70</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Avalanche" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://avascan.info/blockchain/c/address/0xc094c224ce0406bc338e00837b96ad2e265f7287">0xc094c224ce0406bc338e00837b96ad2e265f7287</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://avascan.info/blockchain/c/address/0xd7f69ba99c6981eab5579aa16871ae94c509d578">0xd7f69ba99c6981eab5579aa16871ae94c509d578</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://avascan.info/blockchain/c/address/0x33f65c8d025b5418c7f8dd248c2ec1d31881d465">0x33f65c8d025b5418c7f8dd248c2ec1d31881d465</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://avascan.info/blockchain/c/address/0x41669db18dd923f726572ccfd4b1929e203fcc9d">0x41669db18dd923f726572ccfd4b1929e203fcc9d</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Base" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://basescan.org/address/0x6fc0f2320483fa03fbfdf626ddbae2cc4b112b51">0x6fc0f2320483fa03fbfdf626ddbae2cc4b112b51</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://basescan.org/address/0x6da4d1859ba1d02d095d2246142cdad52233e27c">0x6da4d1859ba1d02d095d2246142cdad52233e27c</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://basescan.org/address/0xe50554ec802375c9c3f9c087a8a7bb8c26d3dedf">0xe50554ec802375c9c3f9c087a8a7bb8c26d3dedf</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://basescan.org/address/0xd04deaba7fd06634764cbffe140011c69063ac77">0xd04deaba7fd06634764cbffe140011c69063ac77</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Binance Smart Chain" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://bscscan.com/address/0x3f680ab9e51eeed9381de5275f4995611ff884d5">0x3f680ab9e51eeed9381de5275f4995611ff884d5</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://bscscan.com/address/0x9c275714fb882988fbbffdc39a162e0cc9fea64c">0x9c275714fb882988fbbffdc39a162e0cc9fea64c</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://bscscan.com/address/0x7175e7e5c246e2e5c8c54ede2ee0180e39fca879">0x7175e7e5c246e2e5c8c54ede2ee0180e39fca879</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://bscscan.com/address/0xf8ce398f05849a00a962de8de16a0af6aff60eb1">0xf8ce398f05849a00a962de8de16a0af6aff60eb1</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Ethereum" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://etherscan.io/address/0x8d6f5479b14348186fae9bc7e636e947c260f9b1">0x8d6f5479b14348186fae9bc7e636e947c260f9b1</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://etherscan.io/address/0x6da4d1859ba1d02d095d2246142cdad52233e27c">0x6da4d1859ba1d02d095d2246142cdad52233e27c</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://etherscan.io/address/0xe50554ec802375c9c3f9c087a8a7bb8c26d3dedf">0xe50554ec802375c9c3f9c087a8a7bb8c26d3dedf</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://etherscan.io/address/0x6c77c47fb8168e22976c3b0338cb1769c952249f">0x6c77c47fb8168e22976c3b0338cb1769c952249f</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Hemi" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://explorer.hemi.xyz/address/0xb457e9c025a8af99e32b03668e34f80d20a71d2c">0xb457e9c025a8af99e32b03668e34f80d20a71d2c</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://explorer.hemi.xyz/address/0x35723a53ccb5adecfbcf50cd1b190e15d896c389">0x35723a53ccb5adecfbcf50cd1b190e15d896c389</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://explorer.hemi.xyz/address/0xe35901b2a7d8d38a0e49d9bc9de7f4f9df31cc6d">0xe35901b2a7d8d38a0e49d9bc9de7f4f9df31cc6d</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://explorer.hemi.xyz/address/0xf8ce398f05849a00a962de8de16a0af6aff60eb1">0xf8ce398f05849a00a962de8de16a0af6aff60eb1</a></td></tr></tbody></table>
{% endtab %}

{% tab title="HyperEVM" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://hyperevmscan.io/address/0x90beb507a1ba7d64633540cbce615b574224cd84">0x90beb507a1ba7d64633540cbce615b574224cd84</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://hyperevmscan.io/address/0xd70937aa2b73a8a2100932c4f5a8d32c9be8b80f">0xd70937aa2b73a8a2100932c4f5a8d32c9be8b80f</a></td></tr><tr><td>Logic v0.2.0</td><td><a href="https://hyperevmscan.io/address/0xc1d5f01a6491b97b94f3670aed4becb897293cf8">0xc1d5f01a6491b97b94f3670aed4becb897293cf8</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://hyperevmscan.io/address/0x23f4966ab6418cd54c95ec807a842a5f1ed9ef03">0x23f4966ab6418cd54c95ec807a842a5f1ed9ef03</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Linea" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://lineascan.build/address/0x8d6f5479b14348186fae9bc7e636e947c260f9b1">0x8d6f5479b14348186fae9bc7e636e947c260f9b1</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://lineascan.build/address/0xc81dd51239119db80d5a6e1b7347f3c3bc8674d9">0xc81dd51239119db80d5a6e1b7347f3c3bc8674d9</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://lineascan.build/address/0xa3c233c61436008e05edde6adb3f81a410fa80c2">0xa3c233c61436008e05edde6adb3f81a410fa80c2</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Monad" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://monadvision.com/address/0xccdc4d06ca12a29c47d5d105fed59a6d07e9cf70">0xccdc4d06ca12a29c47d5d105fed59a6d07e9cf70</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://monadvision.com/address/0xbf994c358f939011595ab4216ac005147863f9d6">0xbf994c358f939011595ab4216ac005147863f9d6</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://monadvision.com/address/0x870dd43a868c35b036347c46042d97c7247eea15">0x870dd43a868c35b036347c46042d97c7247eea15</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Optimism" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://optimistic.etherscan.io/address/0xa8e0684887b9475f8942df6a89beba5b25219632">0xa8e0684887b9475f8942df6a89beba5b25219632</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://optimistic.etherscan.io/address/0x7ab55b30e3c382451fcca104521a8b5f45beeaf9">0x7ab55b30e3c382451fcca104521a8b5f45beeaf9</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://optimistic.etherscan.io/address/0xbb2dcc67a94946400a605f2a97933471be8bc538">0xbb2dcc67a94946400a605f2a97933471be8bc538</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Plasma" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://plasmascan.to/address/0xf838e8bd649fc6fbc48d44e9d87273c0519c45c9">0xf838e8bd649fc6fbc48d44e9d87273c0519c45c9</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://plasmascan.to/address/0xfd9fa4986c6cb8cbce6b632dd7c587ebccaedb7a">0xfd9fa4986c6cb8cbce6b632dd7c587ebccaedb7a</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://plasmascan.to/address/0xa61faeb94249f08e05e7ed7502d6ec86297bc9e4">0xa61faeb94249f08e05e7ed7502d6ec86297bc9e4</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Rayls" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://explorer.rayls.com/address/0xfa032de1214fd89b465c306bf46f778318bde357">0xfa032de1214fd89b465c306bf46f778318bde357</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://explorer.rayls.com/address/0x70cfb8860933c7ab2e3c92c942f403af0941f96b">0x70cfb8860933c7ab2e3c92c942f403af0941f96b</a></td></tr><tr><td>Logic v0.6.0</td><td><a href="https://explorer.rayls.com/address/0xd04deaba7fd06634764cbffe140011c69063ac77">0xd04deaba7fd06634764cbffe140011c69063ac77</a></td></tr></tbody></table>
{% endtab %}

{% tab title="TAC" %}

<table><thead><tr><th width="220">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Factory</td><td><a href="https://explorer.tac.build/address/0x66ab87a9282df99e38c148114f815a9c073eca8d">0x66ab87a9282df99e38c148114f815a9c073eca8d</a></td></tr><tr><td>ProtocolRegistry</td><td><a href="https://explorer.tac.build/address/0x3408c51bfc34cbf7112a20fb3f4bc9b74aed7982">0x3408c51bfc34cbf7112a20fb3f4bc9b74aed7982</a></td></tr><tr><td>Logic v0.5.0</td><td><a href="https://explorer.tac.build/address/0x11652aead69716e1d5d132f3bf0848d2fd422b8a">0x11652aead69716e1d5d132f3bf0848d2fd422b8a</a></td></tr></tbody></table>
{% endtab %}
{% endtabs %}

## **Test Factory Smart Contract**

The table below lists the Lagoon Vault Factory contract addresses deployed for each supported testnet network or deployed for testing purpose.

<table><thead><tr><th width="234.93359375">Chain</th><th>Factory Address</th></tr></thead><tbody><tr><td><strong>Arbitrum mainnet</strong></td><td><a href="https://arbiscan.io/address/0xb1ee4f77a1691696a737ab9852e389cf4cb1f1f5#writeProxyContract#F1">https://arbiscan.io/address/0xb1ee4f77a1691696a737ab9852e389cf4cb1f1f5#writeProxyContract#F1</a></td></tr><tr><td><strong>Hoodi - Ethereum testnet</strong></td><td><a href="https://hoodi.etherscan.io/address/0xd039Ee9e7d6B3cfEa29250A7D559A4dDB21B25E2#writeProxyContract#F1">https://hoodi.etherscan.io//address/0xd039Ee9e7d6B3cfEa29250A7D559A4dDB21B25E2#writeProxyContract#F1</a></td></tr></tbody></table>


# Terms of use

{% file src="/files/5wxqTjERVX7w42Pbvte8" %}


# Version History

Track every protocol release and what changed.

Lagoon evolves through versioned releases. Each release is audited before deployment and registered in the [ProtocolRegistry](/vault/upgradability-and-opt-in-proxy), which governs which implementations vaults can upgrade to. Vault operators opt in to new versions through the delay-based upgrade mechanism.

{% hint style="info" %}
All releases listed here have been reviewed by independent auditors. See the full audit reports on the [Audits](/resources/audits) page.
{% endhint %}

***

## <mark style="color:$primary;">v0.6.0</mark> — June 2026

The largest feature release since launch. v0.6.0 introduces new fee types, a dual access control system, vault guardrails, and several new operational controls.

**New features:**

* **Entry and exit fees** — Configurable fees on deposits and redemptions, capped at 2% each. Rates can only decrease, never increase.
* **Haircut fee** — A fee applied to synchronous redemptions, capped at 20%, redistributed to remaining holders by burning shares.
* **Management fee refactor** — Management fee is now computed on the time-weighted average AUM over the period, instead of the final `totalAssets` value.
* **Dual access control** — The Whitelist Manager role is renamed **Access Manager** and can now operate vaults in whitelist mode or blacklist mode (mutually exclusive). The mode is chosen at vault creation and the owner can switch it later with `switchAccessMode`.
* **External sanctions list** — Optional second access layer that queries an on-chain sanctions oracle (Chainalysis-compatible) on every access check.
* **Async only** — Owner can permanently disable synchronous deposits and redemptions, locking the vault into the ERC-7540 async flow.
* **Security Council role** — New governance role responsible for managing price-per-share guardrails.
* **Price-per-share guardrails** — Upper and lower annual rate bounds that gate `totalAssets` updates, enforced on-chain.
* **High water mark reset** — The curator address can reset the performance fee baseline down to the current price per share, when opted in at vault creation.
* **Max cap** — Per-vault cap on total assets, enforced on deposit operations.
* **Sync redeem toggle** — The curator address can independently enable or disable synchronous redemptions via `SyncMode`.
* **Cancel request redeem** — Users can cancel a pending redeem request before settlement, returning shares from the pending silo.
* **Redeem on behalf** — The curator address can redeem shares on behalf of any user who would be allowed to redeem themselves; the Super Operator can additionally bypass access checks.
* **Super Operator** — Privileged role that bypasses whitelist/blacklist restrictions and can act on behalf of users.
* **Initial total assets** — Vaults can be deployed with a non-zero starting `totalAssets`, with matching shares pre-minted to the curator address, to support clean migration from a previous vault or off-chain book.
* **Update name / symbol / curator address** — Owner can update the ERC-20 name, symbol, and the curator (custodian) address after deployment.

**Breaking changes:**

* **`updateRates`** — The `Rates` struct gains three fields (`entryRate`, `exitRate`, `haircutRate`), changing the function's ABI. New rates now apply **immediately**: the rate-update cooldown mechanism from previous versions is removed. Entry and exit rates can only be decreased after initial configuration, and the function reverts on a closed vault.
* **`disableWhitelist` removed** — Replaced by `switchAccessMode`, part of the dual access control system.
* **`isWhitelisted` removed** — Replaced by `isAllowed`, which covers both whitelist and blacklist modes.
* **`feeRates` return type changed** — Returns the extended `Rates` struct with the three new fee fields.
* **View functions removed** — `getRolesStorage`, `MAX_MANAGEMENT_RATE`, `MAX_PERFORMANCE_RATE`, and `MAX_PROTOCOL_RATE` are no longer exposed on the vault.
* **Vault initialization** — The init struct replaces `enableWhitelist` with an `accessMode` enum, drops `rateUpdateCooldown`, and adds fields for the new v0.6.0 features (entry/exit/haircut rates, Security Council, sanctions list, initial total assets, Super Operator, high water mark reset). Deployment integrations must be updated.

***

## <mark style="color:$primary;">v0.5.1</mark> — July 2025

**Major architecture update:**

* Introduced the **OptinProxy** and **DelayProxyAdmin** contracts, shifting toward a permissionless model where the protocol proposes vault implementations without enforcing them.
* New **OptinProxyFactory** for deploying proxy infrastructure.
* **ProtocolRegistry** now combines FeeRegistry and LogicRegistry into a single protocol-level contract.

***

## <mark style="color:$primary;">v0.5.0</mark> — May 2025

**New feature:**

* **Synchronous deposits** — Vaults can accept instant deposits when the valuation is marked as valid by the curator, controlled by a configurable `totalAssetsLifespan` parameter.
* Added whitelist check to the `claimSharesAndRequestRedeem` function.

**Breaking changes:**

* **View functions removed** — `highWaterMark`, `lastFeeTime`, `isWhitelistActivated`, `lastDepositRequestId`, `lastRedeemRequestId`, and `pendingSilo` are no longer exposed on the vault.

***

## <mark style="color:$primary;">v0.4.0</mark> — April 2025

**New feature:**

* **Claim shares on behalf** — The curator can now claim shares on behalf of depositors and transfer them directly to user addresses.

***

## <mark style="color:$primary;">v0.3.0</mark> — April 2025

**Improvements:**

* Introduced `BeaconProxyFactory` for streamlined vault deployment using the Beacon proxy pattern.
* Added a `version()` view function for retrieving the deployed vault version.
* Restructured the source folder organization to support future proxy upgrades.

**Breaking changes:**

* **`initialize` signature changed** — Now takes `(bytes data, address feeRegistry, address wrappedNativeToken)` instead of the init struct directly. Affects deployment tooling only; deployed vaults are unaffected.

***

## <mark style="color:$primary;">v0.2.0</mark> — January 2025

**New features and fixes:**

* **`claimSharesAndRequestRedeem`** — A new function enabling single-transaction share claiming and redemption initiation.
* Corrected fee sequencing for management and performance fees.
* Fixed a performance fee under-calculation bug.
* Added settlement protection safeguards against malicious valuation oracle activity.

***

## <mark style="color:$primary;">v0.1.0</mark> — September 2024

**Initial release:**

* ERC-7540 vault implementation adapted to the Lagoon protocol specifications.
* Asynchronous deposit and redemption flows with NAV-based settlement.
* Role-based permissions: Vault Admin, Curator, Valuation Provider, Whitelist Manager.
* Management and performance fees with high-water mark logic.


# Audits

FInd below the audits carried out for Lagoon Protocol.

<table data-view="cards"><thead><tr><th></th><th></th><th data-type="files"></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>Release (v0.1.0)</td><td>07-11-2024</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/aUGQBCCKrkRj2a2JqcU7/NM_0304_HopperLabs.pdf">NM_0304_HopperLabs.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Release (v0.1.0)</td><td>27-09-2024</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/inufZt8d5BRJq6tJWoED/lagoon-review.pdf">lagoon-review.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/HfUuy59y2IxSA5PHi8qI/Capture%20d%E2%80%99e%CC%81cran%202024-12-17%20a%CC%80%2011.32.26.png">Capture d’écran 2024-12-17 à 11.32.26.png</a></td></tr><tr><td>Release (v0.2.0)</td><td>30-01-2025</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/6mNZOJq6XeTjGMcMnM5N/NM_0432_Lagoon.pdf">NM_0432_Lagoon.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Release (v0.3.0)</td><td>03-04-2025</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Fcjt5DaNb1FBoKp1EL22z%2FNM_0499_Lagoon.pdf?alt=media&amp;token=32994685-63a0-402e-804f-30170ec0733b">NM_0499_Lagoon.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Release (v0.4.0)</td><td>17-04-2025</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F6ikCSitYVQQdDDcWfVdp%2FNM_0516_Lagoon.pdf?alt=media&amp;token=87aeab5a-284c-4fc9-a210-e4ea168bac5e">NM_0516_Lagoon.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Release (v0.5.0)</td><td>13-05-2025</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F8HkE2EU7hepf08gYGPsx%2FNM_0534_Lagoon.pdf?alt=media&amp;token=5884c02c-9290-4e7e-bebf-07f9aad8ba51">NM_0534_Lagoon.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Release (v0.5.1)</td><td>10-07-2025</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F9pXJSEmutn6clKhvly6m%2FNM_0581-FINAL_Lagoon.pdf?alt=media&amp;token=b6e6194b-62ac-490c-a079-9805fb141d24">NM_0581-FINAL_Lagoon.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Low Level Bug Disclosure</td><td>22-01-2026</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FtDP4IRcaDp90PdfyOytL%2FNM_0534_Bug_Disclosure.pdf?alt=media&amp;token=ab07f771-439e-4d3e-912f-dda8f8b72e7c">NM_0534_Bug_Disclosure.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Release (v0.5.1)</td><td>04-03-2026</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2FILDRIc5ZH9HblSRMBoLw%2FToB-v0.5.0.pdf?alt=media&amp;token=de43990a-2cd4-4d7d-a216-d07aa493e03e">ToB-v0.5.0.pdf</a></td><td data-object-fit="contain"><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F8FcHqmJlo4eQckhVnpxV%2FScreenshot%202026-03-25%20at%2016.17.54.png?alt=media&amp;token=96dac28e-77c8-4c95-a1fd-71b58edc1d43">Screenshot 2026-03-25 at 16.17.54.png</a></td></tr><tr><td>Release (v0.6.0)</td><td>25-05-2026</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2Frk5VgBBMxx0fkaXD65tQ%2FNM_0822_Lagoon.pdf?alt=media&amp;token=1afc48dd-0c6b-43aa-b358-946e87026279">NM_0822_Lagoon.pdf</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/t0jMBbf61lHQPzWGbBDC/nm.jpg">nm.jpg</a></td></tr><tr><td>Release (v0.6.0)</td><td>11-05-2026</td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F3Ig5AUs4tRCYQjsMIas1%2FToB-v0.6.0.pdf?alt=media&amp;token=71eb59b5-e843-40df-a009-2a4354687fc9">ToB-v0.6.0.pdf</a></td><td><a href="https://2098527692-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5vcVbvvRrtwZ0uaFrufF%2Fuploads%2F8FcHqmJlo4eQckhVnpxV%2FScreenshot%202026-03-25%20at%2016.17.54.png?alt=media&amp;token=96dac28e-77c8-4c95-a1fd-71b58edc1d43">Screenshot 2026-03-25 at 16.17.54.png</a></td></tr></tbody></table>


# Brand Kit

Discover Lagoon's official brand assets.

## Symbol

Each symbol comes in 2 different file formats, with variations for light and dark backgrounds.

→ Select the desired version, right-click on the symbol and choose "Save as".

<table data-view="cards"><thead><tr><th></th><th data-type="files"></th><th></th><th data-type="files"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td>PNG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/hFCXvmhtFw3Vv216YDZA/symbol_lagoon_color.png">symbol_lagoon_color.png</a></td><td><br>SVG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/nGU1m891Pr0rhpst1E01/symbol_lagoon_color.svg">symbol_lagoon_color.svg</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/hKLZLR736sP9JP1mgGVj/Symbol%201.png">Symbol 1.png</a></td></tr><tr><td>PNG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/OE8Vg1kjclFSP7kkVkL7/symbol_lagoon_white.png">symbol_lagoon_white.png</a></td><td>SVG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/7RsB9cphnAFpePXKoT6L/symbol_lagoon_white.svg">symbol_lagoon_white.svg</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/GmXXDdRmAE6XusyE2fK8/Symbol%203.png">Symbol 3.png</a></td></tr><tr><td>PNG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/1RurSHu5YGzzF92dDchg/symbol_lagoon_black.png">symbol_lagoon_black.png</a></td><td>SVG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/bpaRkVaMH3sNxFgvIdHe/symbol_lagoon_black.svg">symbol_lagoon_black.svg</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/fYEkt7eK8oKgLHTtRR64/Symbol%204.png">Symbol 4.png</a></td></tr></tbody></table>

***

## Logotype

Each logotype comes in 2 different file formats, with variations for light and dark backgrounds.

→ Select the desired version, right-click on the logotype and choose "Save as".

<table data-view="cards"><thead><tr><th></th><th data-type="files"></th><th></th><th data-type="files"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td>PNG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/GTDwmku2YVjNjTFoNYGB/logo_lagoon_color.png">logo_lagoon_color.png</a></td><td>SVG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/VHXOLO85YGH53JtXAB3M/logo_lagoon_color.svg">logo_lagoon_color.svg</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/CUWnevVaA9iYnNQzNd6D/Logo%201.png">Logo 1.png</a></td></tr><tr><td>PNG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/ssLrcqygIAwJcRvg29AQ/logo_lagoon_mixed.png">logo_lagoon_mixed.png</a></td><td>SVG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/UMRelQB7e6Fpd80LsBZF/logo_lagoon_mixed.svg">logo_lagoon_mixed.svg</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/cvz4u9w7DAfwTkfwEjVJ/Logo%202.png">Logo 2.png</a></td></tr><tr><td>PNG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/eb9fS2ZDCV4TWlFZhan9/logo_lagoon_white.png">logo_lagoon_white.png</a></td><td>SVG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/gCAfb4WlkdrGMIWmTjie/logo_lagoon_white.svg">logo_lagoon_white.svg</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/74W98IUNo5cNWGAjvUiF/Logo%203.png">Logo 3.png</a></td></tr><tr><td>PNG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/ZzdWd7y3U9qPD9GVnR4V/logo_lagoon_black.png">logo_lagoon_black.png</a></td><td>SVG</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/DLlVy3XotJvGb6QlVddZ/logo_lagoon_black.svg">logo_lagoon_black.svg</a></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/n7aJ8skX1d1336ek3Eut/Logo%204.png">Logo 4.png</a></td></tr></tbody></table>

***

## Typography

DM Sans is the only font used by Lagoon. Download it on [Google Fonts](https://fonts.google.com/specimen/DM+Sans).

<table data-view="cards" data-full-width="false"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/yYsTFGadtPjff7aKi80T/Typeface%20Light.png">Typeface Light.png</a></td></tr><tr><td></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/FvlPTgbR8gZhUyxjETn2/Typeface%20Regular.png">Typeface Regular.png</a></td></tr><tr><td></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/vyumGnadqgrZCT3Ma7MB/Typeface%20Medium.png">Typeface Medium.png</a></td></tr><tr><td></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/s6NXcGb5CYhMLlrSc5fl/Typeface%20SemiBold.png">Typeface SemiBold.png</a></td></tr><tr><td></td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/wLEZCiJmsh24i3j2Hdjg/Typeface%20Bold.png">Typeface Bold.png</a></td></tr><tr><td></td><td></td></tr></tbody></table>

Registered under the [SIL Open Font License](https://openfontlicense.org/): allowing for free use, modification, and distribution of the font. Available for commercial use.

***

## Colors

Each color comes with a specific HEX code. Copy-paste to use it.

<table data-column-title-hidden data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Black</strong><br>#00014A</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/EgvlPHh2NsAxf60Jk7dQ/Black.png">Black.png</a></td></tr><tr><td><strong>Dark Blue</strong><br>#00165B</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/O2lJae61xZ4BScRam2sE/Dark%20Blue.png">Dark Blue.png</a></td></tr><tr><td><strong>Dark Teal</strong><br>#1E7C76</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/SBEzGzm5RDr7JQBM1Bsy/Dark%20Teal.png">Dark Teal.png</a></td></tr><tr><td><strong>Teal</strong><br>#00C8BA</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/z1U45xy0EDArsWqhMGNg/Teal.png">Teal.png</a></td></tr><tr><td><strong>Light Blue</strong><br>#A1D8FF</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/3dN4TvdtukwQo4jfHktr/Light%20Blue.png">Light Blue.png</a></td></tr><tr><td><strong>Light Green</strong><br>#A4F6BD</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/Ggkfe4xbpCVfKA1w8GYz/Light%20Green.png">Light Green.png</a></td></tr><tr><td><strong>Sky Blue</strong><br>#C9F5FF</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/IxTbHwbjSU0eEttvSFoU/Sky%20Blue.png">Sky Blue.png</a></td></tr><tr><td><strong>White</strong><br>#FFFFF</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/0vfbdkG6GVF69CA0m2iO/White.png">White.png</a></td></tr><tr><td><strong>Aqua</strong><br>#00D1FF</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/NR4ijv5f6jq50mIGagrC/Aqua.png">Aqua.png</a></td></tr><tr><td><strong>Electric Blue</strong><br>#0042F0</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/Vtxt2pmyqbLTQYCREpsj/Electric%20blue.png">Electric blue.png</a></td></tr></tbody></table>

***

## Gradients

Each gradient comes with a specific combination of HEX codes. Copy-paste to use them and follow the other instructions.

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Background gradient</strong></td><td>linear-gradient(90deg, #001658 9.37%, #002585 54.69%, #0039CB 72.81%, #13CFC2 91.2%, #A4F6BD 100%)</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/Lbzl2fNFWPgAn630xn4T/Background%20gradient.png">Background gradient.png</a></td></tr><tr><td><strong>Accent gradient</strong></td><td>linear-gradient(279deg, #A4F6BD 6.77%, #13CFC2 50%, #00D1FF 93.24%)</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/aOHU0jLTxXU4nL2THAbL/Accent%20gradient.png">Accent gradient.png</a></td></tr><tr><td><strong>Logo gradient #1</strong></td><td>linear-gradient(270deg, #91F1BD 0%, #2BD5C1 25%, #13CFC2 50%, #079AC6 100%), linear-gradient(279deg, #A4F6BD 6.77%, #13CFC2 50%, #00D1FF 93.24%)</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/ogyBPMknDFHJ6DlSczJ1/Logo%20gradient%20#1.png">Logo gradient #1.png</a></td></tr><tr><td><strong>Logo gradient #2</strong></td><td>linear-gradient(270deg, #00D1FF 0%, #0039CB 100%), linear-gradient(270deg, #91F1BD 0%, #2BD5C1 25%, #13CFC2 50%, #079AC6 100%), linear-gradient(279deg, #A4F6BD 6.77%, #13CFC2 50%, #00D1FF 93.24%)</td><td><a href="https://content.gitbook.com/content/5vcVbvvRrtwZ0uaFrufF/blobs/IX2nkjJRt0aRjND1CC9K/Logo%20gradient%20#2.png">Logo gradient #2.png</a></td></tr></tbody></table>


