# Welcome to Nucleus

The Default Yield Provider for Networks

## Overview

Nucleus is the default yield provider for networks. Nucleus stands to revolutionize the way users interact with networks by removing the opportunity costs of exploring new ecosystems via embedding yield for all users at the network layer.

Nucleus enables networks to create a new yield generating primitive at the base of a network’s ecosystem. Users are able to generate yield by default on a wide variety of assets by bridging supported assets to the network. These assets will allow users to earn more while exploring all of the unique applications in the network’s ecosystem.

Nucleus's mission is to enable yield by default in every network in the crypto ecosystem to further empower the builders, users, and infrastructure within them.


# Official Links

**Website:** [**http://nucleusearn.io/**](http://nucleusearn.io/)

**Twitter:** [**https://x.com/nucleusearn**](https://x.com/nucleusearn)

**Discord:** [**https://discord.gg/wPRjEwa4xw**](https://discord.gg/wPRjEwa4xw)

**Github:** [**https://github.com/Ion-Protocol/nucleus-boring-vault**](https://github.com/Ion-Protocol/nucleus-boring-vault)

**Webapp:** [**https://app.nucleusearn.io/**](https://app.nucleusearn.io/dashboard)


# FAQ

Common questions about Nucleus.

### What is Yield by Default?

* Yield by Default is the concept of earning yield by participating in an network supported by Nucleus. Users who bridge their assets can earn yield while exploring the network ecosystem for novel and unique applications.

### Where does Nucleus’s yield come from?

* Nucleus generates yield for ETH and BTC-based network assets from infrastructure-based DeFi primitives. Infrastructure-based yields remove user exposure to traditional market risks such as price-based liquidations, decreases in price leading to loss of capital, and impermanent loss. These yield sources can be viewed in [Revenue Strategies](/nucleus-architecture/revenue-strategies).

### What are the risks associated with using Nucleus?

* No platform can be considered entirely risk free. The risks related to Nucleus platform are the smart contract risk (risk of a bug within the protocol code) and for ETH and BTC default yield, network risk (risks around the infrastructure of a network failing). Every possible step has been taken to minimize these risks as much as possible. Nucleus's codebase is public and open source and has been audited multiple times. Additional risk and security related information can be found in [Security](/security/audits).

### How does Nucleus bridge between networks?

* Nucleus leverages canonical network bridges as well as trusted third party bridging infrastructure including but not limited to LayerZero, Hyperlane, and more.

### Has Nucleus been audited?

* Yes Nucleus has been audited numerous times. Every application that Nucleus interacts with has also undergone multiple audits. More information around Nucleus's audit history can be found in [Audits](/security/audits).

### What happens to your assets once they are deposited?

* Once a user deposits their assets, they are deployed within the Nucleus implementation's pre-ordained strategy. The underlying assets are accepted into the Nucleus custody contract within the network that the deposit is made and deployed into strategies curated by the vault risk manager that may exist on the origination network or another that is connected to the strategy.

### How does the asset accrue yield?

* All Nucleus assets report an on-chain exchange rate that reports the value of the asset over time.
* Yield automatically accrues to the asset via the exchange rate and is generated through the pre-set strategy.

### What happens when a withdrawal occurs?

* When a withdrawal transaction is being made, a user first sets their withdrawal parameters.&#x20;
* They must then wait for the solver to pick up the transaction and execute the withdrawal within the deadline time period.&#x20;
* For more details on withdrawals, check here: <https://docs.nucleusearn.io/nucleus-architecture/withdrawals>

### Why do certain vaults/assets have different withdraw fees/slippage rates?

* Nucleus assets maintain multiple assets and positions, so when users request a withdrawal in a specific asset, the solver often has to route assets across multiple DEX venues. Based on the output asset and amount, this swap price can vary.
* For example, assume a user wants to withdraw WBTC. The max slippage is 1%. The vault may need to swap some LBTC into WBTC to fulfill this order, incurring 0.6% of slippage.
* Since max slippage 1% >= 0.6%, the user only pays 0.6% (the max slippage was not hit).
* But if the user’s max slippage was < 0.6%, the solver would not be able to fill the order, requiring the user to resubmit the request.


# Overview

A high level overview of Nucleus' technical architecture.

## Summary

The technical objective of Nucleus is to be a composable platform to enable the generation of yield by a user in any arbitrary network that can allow the minter of a Nucleus-powered Network Asset to accrue yield from both the Ethereum Mainnet and "another network" in aggregate.

This "another network" can be any state environment with a support for any secure interchain messaging protocol—whether it's an Ethereum rollup, an alt-layer 1, or a different blockchain framework like Cosmos. But for simplicity, the "new network" will simply be referred to as an "L2" in this docs.

To enable the above, the Nucleus architecture includes a set of contracts that facilitates cross-chain deposits, withdrawals, liquidity management, and a set of backend keepers and oracles that synchronizes data between multiple chain environments.&#x20;

<figure><img src="/files/mX3RntWRNl2z7okBqjHK" alt=""><figcaption></figcaption></figure>


# Vault Framework

## BoringVault

The BoringVault is the ERC20 token contract that custodies all deposit assets and exposes permissions for minting and burning the vault shares. The other contracts rely on permissions granted by the BoringVault to execute certain actions.&#x20;

## Teller&#x20;

The Teller—with the permissions granted by the BoringVault to mint and burn the shares—defines the logic for minting shares upon deposit. The Teller checks whether the given asset is part of its list of supported assets, queries the assets' value via the Accountant, and determines how many shares to mint for the given amount of deposit tokens.

The Teller also can be extended to support different types of bridges. For example, the Teller may use the LayerZero bridge to bridge its minted shares.&#x20;

## Accountant

The Accountant is the source of truth for the vault's exchange rate as well as the value of each whitelisted deposit assets.

Because the Teller is able to accept an arbitrary number of whitelisted assets, in order to determine how many shares to mint given an asset, it needs to query both the vault's base exchange rate and the specific price of the asset.&#x20;

For example, consider a user who wants to deposit `1 wstETH`:

* Assume the current exchange rate of the vault is `1.5 ETH/Share`.&#x20;
* Assume the current price of `wstETH` is `1.2 ETH/wstETH`.
* When the user deposits `1 wstETH` to the Teller, the Teller first converts this value to the `ETH` denomination.&#x20;
  * This is `1 wstETH * 1.2 ETH/wstETH = 1.2 ETH`
* Then, the Teller converts the `ETH` value to the amount of shares to mint.&#x20;

  * This is   `1.2 ETH / 1.5 ETH/Share = ~0.8 Shares`

## Manager

The Manager contract ensures the BoringVault's security as its custodied assets are managed and deployed into external protocols by the strategists.&#x20;

The Manager contract assigns a merkle root to a specific strategist address. The leaves of this merkle root defines the type of transaction that the strategist is able to call on behalf of the BoringVault.&#x20;

To see an example of how the Manager ensures the security of the BoringVault while delegating the liquidity management to strategists, consider the following example where a strategist is permitted to lend to a market on Ion Protocol:

* Lending on Ion Protocol can be done by calling `IonPool.supply(address,uint256,bytes32[]).`
  * The `address` type here referes to the recipient of the minted `iTokens` which corresponds 1:1 with the lent asset.&#x20;
  * The `uint256` type specifies the supply amount, and this does not need to be restricted for security.&#x20;
  * The `bytes32[]` is a whitelist proof for interacting with the `IonPool` contract.&#x20;
* Now, the `Manager` considers the following attack vector:
  * If the strategist is able to make a `supply` call to the `IonPool` while specifying the `address` as a malicious EOA, this means that the strategist would be able to drain the BoringVault's funds by lending to Ion Protocol and sending the `iTokens` to a malicious address.&#x20;
  * This means we would want every BoringVault's `supply` call to specify the `address` as its own address.&#x20;
* In order to achieve the above, the Manager uploads a merkle root where the leaves are constructed with the following fields:
  * The address of the `IonPool`.&#x20;
  * The `bytes4` selector of the `supply` function.
  * The address of the `recipient`&#x20;
  * A `boolean` for whether the contract call requires `msg.value` or not.
  * The address of the `Decoder` contract that can parse out the sensitive function parameter (the `address recipient` field) given calldata of this `supply` function call.
* Then, the Manager stores a merkle root built from this leaf, and enforces the strategist to pass in a merkle proof.&#x20;
  * Now, if the strategist attempts to pass `calldata` that does not meet all of the requirements specified in the leaf, then the `Manager` will revert.
* This process allows the Manager to guarantee that the strategist can only call transactions allowed by the precomputed merkle root.

> Nucleus's vault interfaces were inspired from [Veda](https://veda.tech)'s open source [BoringVault repo](https://github.com/Se7en-Seas/boring-vault). We want to give credit to the [Se7enSeas](https://github.com/Se7en-Seas) team for creating this architecture and allowing its free distribution.


# Cross-chain Infrastructure

## The Crosschain Vault

### L1 Mints and Native Mints

On Nucleus, the vault's owner can specify a list of assets that they are willing to accept as deposit assets in the vault. Most (but not all) vaults contain what are called "sister deployments." This effectively conveys the fact that there are two vaults that exist, one on Ethereum Mainnet and one in the L2 environment that can accept deposits and mint the Network Asset. These assets can be specified separately for the L1 and the L2 vault.

Allowed assets can be deposited on the L1 and the resulting network asset—i.e. the vault shares—can be minted on the L1 itself, or be atomically bridged to the L2 using the underlying messaging protocol.&#x20;

For ***native mints***—i.e. users who wants to mint their network asset tokens by depositing their L2 assets within the L2 environment—they can interact with the L2 vault contract in order to mint the network asset token directly on the L2.&#x20;

For more on deposits, see [Teller in Vault Framework.](/nucleus-architecture/vault-framework#teller)

### Bridging

L1 and L2 vaults are connected through a mint and burn bridge using an interchain messaging protocol that supports the L2.&#x20;

For example, consider a user who wants to deposit assets on Ethereum Mainnet (L1) and mint the network asset token on Optimism (L2). The user may deposit `ETH`, mint the vault shares named `opETH` (the network asset token ticker), and bridge these shares to Optimism (L2) through the OP Stack's canonical messenger or the LayerZero network to first burn the shares on the L1 and to mint the corresponding amount of shares on the L2.

The messaging protocol is a modular component of the vault that can plug and play different types of bridges that the L2 supports.


# Withdrawals

Withdrawals on Nucleus vaults are facilitated by a network of solvers that search multiple venues to provide low-cost routes and convenient execution for users.&#x20;

#### How long do withdrawals take?

* Withdrawals are network and asset-dependent but most are completed within 3 or 7 days. The reported deadline is the maximum amount of time that it will take, often withdrawals are completed prior to the deadline. This timeframe is showcased on the Redeem Tab

<figure><img src="/files/lcrCK5aR7dHYpuPYT3sO" alt=""><figcaption></figcaption></figure>

#### Withdrawal flow

1. User submits Withdrawal Request on the redeem tab (this may require the approval of multiple transactions including a bridging transaction and withdrawal transaction).
2. Solver picks up transaction request.
3. Solver executes transaction within designated time (this is typically within 3 or 7 days).
4. Once the transaction is executed, the user receives the withdrawn assets requested and the Default Yield tokens are burned.

#### Withdrawal fees

**Bridge fee** - the fee charged by the underlying bridge provider (if applicable)

**Withdrawal fee** - the fee used by solvers for gas and any costs such as slippage occurred by the withdrawal execution.

#### What assets can be withdrawn and where?

* This is dependent on each specific vault
* Make sure to check the withdrawal asset tab
* All vaults will allow you to withdraw to Ethereum mainnet or the primary destination chain where yield accrues.

#### Why does a delay exist?

When a user deposits their assets, the assets are used to engage in yield generating activities on Ethereum mainnet (or the primary destination chain). While these positions are almost always liquid positions (able to be exited without a lock-up duration), they still need to be unwound. This typically requires multiple transactions and optimal route determination.&#x20;

Alternatively, the solvers can also bring in external liquidity to fill the users’ withdraw orders upfront by buying the user shares, proceeding to withdraw the shares for profit at a later date.


# Revenue Strategies

### Revenue Strategies

The deposits made to the vault can be utilized in whitelisted DeFi strategies to earn yield. The various types of assets deposited in the vault can either be held idle, or be deployed to external protocols that offer safe, risk minimized yield.&#x20;

The vault’s liquidity management can also be delegated to certain sophisticated actors while ensuring the security of the funds.

For example, the vault can whitelist professional DeFi risk managers to manage a specific strategy—such as LRT lending markets—and allow the strategist to continuously lend and withdraw from multiple whitelisted lending pools to optimize yield while minimizing risk for the depositors. While the strategist can conduct specific actions such as lend/withdraw that can optimize yield, the strategist would not be able to send malicious transactions such as transferring liquidity to a malicious contract.&#x20;

For more details on security assumptions, see [Manager in ](/nucleus-architecture/vault-framework#manager)[Vault Framework.](/nucleus-architecture/vault-framework#manager)

### Yield Accrual

When the vault is deployed on the L1 and the L2, the liquidity can be transferred to and from each network and also be deployed for unique opportunities on the respective chains. This means that the total value of the vault must account for liquidity in multiple network states. Because a smart contract cannot atomically query the state of another network, Nucleus uses an offchain oracle to query the total balances of unutilized assets and tokenized DeFi positions to report the aggregate value of the vault. This value, divided by the aggregate total supply, is the exchange rate that is updated on-chain.&#x20;

This system is analogous to how many liquid staking providers such as Lido keep track of their exchange rates, where the staking provider's offchain daemon queries the total balance of ETH on the execution layer as well as the total value of ETH staked across its validators on the beaconchain. The daemon then combines these two values and updates the staking contract, either increasing or decreaseing the exchange rate of the \`lstETH\` contract. If the staking protocol's validators accrue yield, the exchange rate increases. If the validators suffer a loss greater than the earnings via slashings, then the exchange rate would decrease. Similarly, as the Nucleus vaults earn yield, the exchange rate would increase, but also decrease if the vault suffers a loss. For example, if a validator that the vault lent its liquidity is slashed, the exchange rate would go down.&#x20;

For more details on exchange rates, see [Accountant in Vault Framework.](/nucleus-architecture/vault-framework#accountant)


# Market-agnostic Lending

Nucleus is partnered with Ion Protocol, a completely price-agnostic lending platform that leverages provable validator-backed data to allow users to borrow ETH and other staked/restaked assets against their LSTs and restaking positions.

* All loan positions in Ion are price-agnostic, and their parameters (interest rates, LTVs, position health, etc.) are determined by consensus layer data.
* This means liquidations are triggered by **changes in consensus layer state, not by price oracles, meaning the only insolvency risk users are exposed are derived by slashing.**

Nucleus can deposit any combination of the following collateral types into the protocol's lending markets at scale:

1. LSTs
2. LST LP Positions
3. Restaking Positions
4. Liquid Restaking Positions (LRTs)
5. Staked LST LP Positions (e.g. Aura Finance’s ERC-4626 positions)

Nucleus can lend capital within its vaults to these markets, generating returns on top of the base rewards of their collateral.


# Cross-chain Intents

With the growth of chain abstraction protocols and intent-based bridges, there has been a new found demand for off-chain stakeholders to assist in providing liquidity to fill orders for cross-chain bridging and swaps.&#x20;

Nucleus services this demand for liquidity by utilizing capital that’s not being deploying in other Infra-based revenue strategies. Nucleus deploys capital within its vaults to assist solvers in filling cross-chain intents and orders across balance abstraction orderflow auctions.

One of the crucial aspects of Nucleus that enables it to be a perfect fit for this market is the fact that it de-facto manages an immense amount of liquidity in an extremely large amount of network environments. This allows the protocol to fill orders at a much more competitive rate with relatively low infrastructural overhead.


# Ownership by Default

Coming soon...


# Reward Distribution

This page will cover the additional token incentive rewards that users may see from protocols or networks when holding a Default Yield asset.

### Reward Qualification Criteria

Every 24 hour period there is a random snapshot taken at a specific block number. At the time of this specific block, the quantity of Nucleus Default Yield Tokens that a wallet holds or has ownership over is proportional to the amount of rewards they are entitled to for that 24 hour period. This includes but is not limited to:

* The Default Yield asset itself
* LP token balances
* Collateral balances in dApps

This dynamic will render deposits that are sold or transferred before the block at which the snapshot occurs invalid to receive rewards during the 24 hour period.

### Cadence

Rewards are currently “weekly” in the sense that a set amount of rewards are set to be distributed every week, and each 24hr period qualifies a user for 1/7th of the week's rewards.

### Calculation

$$
rewardsAPY = (dailyTokenAmt\*tokenPrice ) \*365/currentTVL
$$

The APY that is shown on the Nucleus frontend is a combination of various yield sources such as Default Yield and associated network or dApp token incentives (points are NOT factored into APY calculations).&#x20;

{% hint style="info" %}
A note on fluctuating APY values:

\
Associated networks or dApps distribute specific dollar amounts of their tokens on set cadences, but if the price of an incentive token decreases in value before the distribution timeframe, it will make the dollar value claimed lower than the anticipated APY. <br>

This also can occur in the opposite direction as well. If a token's price increases right before the claim period, the dollar value of the tokens will be higher than the APY showcased at the time of deposit.
{% endhint %}


# Nucleus Points

### Overview

Nucleus Points track all Default Yield positions that each wallet holds across various sources. These sources include but are not limited to:

* The Default Yield asset itself
* LP token balances
* Collateral balances

Each source may have a different multiplier. For example, during a promotional period, LP tokens may be earning 2x the standard rate of rewards. In this case, for each of the Default Yield assets held in the LP position, a user would earn 2x the Nucleus Points compared to holding the same amount of Default Yield assets not in the LP.

### Calculation Methodology

$$
nucleusPointsPerDay = valueofDeposits/100 \* pointsMultiplier
$$

* \[1] point for every \[$100 USD] effective balance every \[24] hours
* This is monitored continuously
* Fractional point totals will be rounded down

> *Note - Nucleus Points are only updated on the frontend application every 24 hours*


# Deployed Assets

Deployed addresses for each network's Nucleus vaults.

<table><thead><tr><th width="125">Asset</th><th>Chain</th><th width="262">Token Contract Address</th><th width="269">Teller Address</th></tr></thead><tbody><tr><td>ssETH</td><td>Ethereum, Sei</td><td>0xA8A3A5013104e093245164eA56588DBE10a3Eb48</td><td>0x97D0B97A9FA017f8aD2565a5c6AED5745f3918b9</td></tr><tr><td>seiyanETH</td><td>Ethereum, Sei</td><td>0x9fAaEA2CDd810b21594E54309DC847842Ae301Ce</td><td>0xB52C7d88F0514796877B04cF945E56cC4C66CD05</td></tr><tr><td>FETH</td><td>Ethereum, Form</td><td>0x6C587402dC88Ef187670F744dFB9d6a09Ff7fd76</td><td>0xd567b6D8e9C95d8a29e60018156becaBDC63E851</td></tr><tr><td>earnETH</td><td>Ethereum, Swell Network</td><td>0x215DC1cC32d9d08a0081e55E55895C8Cf006839a</td><td>0x685aDb4797fb38D4Fc4a69750aa048B398160429</td></tr><tr><td>earnBTC</td><td>Ethereum, Swell Network</td><td>0x66E47E6957B85Cf62564610B76dD206BB04d831a</td><td>0x1DA9ceFA0F46b2087b2cF7dbF9E62Dd94076Ece1</td></tr><tr><td>unifiETH</td><td>Ethereum</td><td>0x196ead472583bc1e9af7a05f860d9857e1bd3dcc</td><td>0x08eb2eccdf6ebd7aba601791f23ec5b5f68a1d53</td></tr><tr><td>unifiBTC</td><td>Ethereum</td><td>0x170d847a8320f3b6a77ee15b0cae430e3ec933a0</td><td>0x0743647a607822781f9d0a639454e76289182f0b</td></tr><tr><td>unifiUSD</td><td>Ethereum</td><td>0x82c40e07277eBb92935f79cE92268F80dDc7caB4</td><td>0x5d3Fb47FE7f3F4Ce8fe55518f7E4F7D6061B54DD</td></tr><tr><td>tETH</td><td>Ethereum</td><td>0x19e099B7aEd41FA52718D780dDA74678113C0b32</td><td>0x6Ae187EacF40ebd1e571a655dB92A1f47452E0Bf</td></tr><tr><td>tUSD</td><td>Ethereum</td><td>0x722a851B6798D65b80526562Fc3a36E19b1F883b</td><td>0x9Ff67b826b34feE9bf4135962754a808C4a14Fbc</td></tr><tr><td>rariETH</td><td>Ethereum, Rari Chain</td><td>0x5d82Ac302C64B229dC94f866FD10EC6CcF8d47A2</td><td>0x5CcE6CB6B4b62C020f0CFCDB95FCdf6Ca706bE88</td></tr><tr><td>bobaETH</td><td>Ethereum</td><td>0x52e4d8989fa8b3e1c06696e7b16def5d7707a0d1</td><td>0xCd721cd24811013c35fFd4BaeF63F07A600EA8bA</td></tr></tbody></table>


# Smart Contracts

Detailed interface and developer docs for Nucleus contracts.

In this section you can find a full breakdown of the entire repository of smart contracts for Nucleus.


# README

```
 .-. .-..-. .-.  ,--,  ,-.    ,---.  .-. .-.   .---.
 |  \| || | | |.' .')  | |    | .-'  | | | |  ( .-._)
 |   | || | | ||  |(_) | |    | `-.  | | | | (_) \
 | |\  || | | |\  \    | |    | .-'  | | | | _  \ \
 | | |)|| `-')| \  `-. | `--. |  `--.| `-')|( `-'  )
 /(  (_)`---(_)  \____\|( __.'/( __.'`---(_) `----'
(__)                   (_)   (__)
```

## Boring Vault Architecture

Boring Vaults are flexible vault contracts that allow for intricate strategies, secured by both onchain and offchain mechanisms.

The BoringVault architecture is made up of:

* **BoringVault**: A barebones vault contract that outsources complex functionality to external contracts.
* **Manager**: Limits the possible strategies BoringVaults can use, without large gas overheads, or unnecessary risk.
* **Teller**: Facilitates user deposits and withdraws in/out of the BoringVault.
* **Accountant**: Provides a safe share price for Teller interactions via offchain oracles.

###

### Arctic Architecture

The Arctic Architecture implements a unique Manager, Teller, and Accountant.

#### ManagerWithMerkleVerification

This Manager restricts the strategies that BoringVaults can employ by storing all possible actions in a [merkle tree](https://en.wikipedia.org/wiki/Merkle_tree). Each leaf of the merkle tree contains:

* `DecoderAndSanitizer` address, a contract used to extract sensitive function arguments from the calldata to `Target`
* `Target` address, the address the call is made to
* `ValueNonZero`, a bool indicating whether or not the BoringVault can transfer native ETH to the `Target`
* `Selector`, the bytes4 function selector on the `Target`
* `PackedAddressArguments`, a bytes value containing all sensitive function arguments found by the `DecoderAndSanitizer`

Each leaf allows the BoringVault to make an explicit action. Using this setup the merkle tree can be used to restrict:

1. What contracts the BoringVault can interact with.
2. What functions on those contracts the BoringVault can call.
3. What sensitive arguments can be passed into those functions.
4. Whether or not the BoringVault can transfer ETH with those function calls.

This Manager also supports a unique merkle tree per strategist, which offers a ton of flexibility and improvements in the future. For instance the main strategist can have access to a large merkle tree, but a strategist account intended to only exit certain positions based off market conditions would have a much smaller merkle tree that only allowed them to perform their job.

#### TellerWithMultiAssetSupport

This Teller allows users to enter/exit the BoringVault with a broader set of assets, additionally it only supports permissioned withdraws, and it allows permissioned accounts to refund deposits within a certain time period. These features allow users to only interact with the asset they choose, but also offer a ton of protection for the BoringVault.

When DeFi products allow users to deposit and withdraw multiple different assets, it is a double edged sword, on the one hand users can choose exactly what they want in and out in order to reduce transactions and simplify their account management, but on the other hand it opens up a lot of MEV opportunities that only harm the users in the product because MEV bots will treat the product as a swapping pool, and arbitrage it. This Teller allows users this freedom of choice but substantially mitigates the MEV opportunities using the following:

1. After deposits all of the depositors shares are locked to their account for the `shareLockPeriod`, which makes flashloan arbitrages impossible.
2. During this period permissioned accounts have the ability to refund the deposit, which will completely reverse any state changes.
3. Withdraws are permissioned using an `AtomicQueue` which is convenient for users as they submit one transaction, then their money automatically shows up in their account in the next few days, however inconvenient for arbitragers as they can not control when their withdraw goes through.

This Teller was designed to take all the good things about multiple deposit assets, but remove the MEV opportunities so that users are not taken advantage of.

#### AccountantWithRateProviders

This Accountant provides the exchange rate information needed by the Teller to accept multiple deposit assets, and is designed to be manipulation resitant using the following:

1. The share exchange rate is calculated offchain, because it is possible for attackers to manipulate onchain data sources.
2. Exchange rates written on chain are rate limited, and bound limited.
   1. *Rate Limiting*: Exchange rates can only be updated so often.
   2. *Bound Limiting*: Exchange rates must fall within a certain bound created using the previous exchange rate on chain.
   3. These two restrictions greatly limit how fast the exchange rate can change, and if either of them are violated, the Accountant enters a `paused` state which stops all BoringVault deposits and withdraws, and new exchange rate updates, until permissioned accounts unpause it.

### Audits

All audits are stored in the audit folder.

### Documentation

For more detailed information, please refer to the [documentation](https://docs.veda.tech).

### Development

In order to run the tests make sure the following is done.

1. Foundry is [installed](https://book.getfoundry.sh/getting-started/installation)
2. Copy `sample.env`, rename the copy to `.env`, and add your infura key.
3. Run `forge install`
4. Run `forge test`


# CONTRACTS


# contents

* atomic-queue
* base
* helper
* interfaces
* micro-managers
* migration
* oracles


# atomic-queue


# Contents

* AtomicQueue
* AtomicSolver
* AtomicSolverV2
* AtomicSolverV3
* IAtomicSolver


# AtomicQueue

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/atomic-queue/AtomicQueue.sol)

**Inherits:** ReentrancyGuard

**Author:** crispymangoes

Allows users to create `AtomicRequests` that specify an ERC20 asset to `offer` and an ERC20 asset to `want` in return.

Making atomic requests where the exchange rate between offer and want is not relatively stable is effectively the same as placing a limit order between those assets, so requests can be filled at a rate worse than the current market rate.

It is possible for a user to make multiple requests that use the same offer asset. If this is done it is important that the user has approved the queue to spend the total amount of assets aggregated from all their requests, and to also have enough `offer` asset to cover the aggregate total request of `offerAmount`.

## State Variables

### userAtomicRequest

Maps user address to offer asset to want asset to a AtomicRequest struct.

```solidity
mapping(address => mapping(ERC20 => mapping(ERC20 => AtomicRequest))) public userAtomicRequest;
```

## Functions

### getUserAtomicRequest

Get a users Atomic Request.

```solidity
function getUserAtomicRequest(address user, ERC20 offer, ERC20 want) external view returns (AtomicRequest memory);
```

**Parameters**

| Name    | Type      | Description                                         |
| ------- | --------- | --------------------------------------------------- |
| `user`  | `address` | the address of the user to get the request for      |
| `offer` | `ERC20`   | the ERC0 token they want to exchange for the want   |
| `want`  | `ERC20`   | the ERC20 token they want in exchange for the offer |

### isAtomicRequestValid

Helper function that returns either true: Withdraw request is valid. false: Withdraw request is not valid.

*It is possible for a withdraw request to return false from this function, but using the request in `updateAtomicRequest` will succeed, but solvers will not be able to include the user in `solve` unless some other state is changed.*

```solidity
function isAtomicRequestValid(
    ERC20 offer,
    address user,
    AtomicRequest calldata userRequest
)
    external
    view
    returns (bool);
```

**Parameters**

| Name          | Type            | Description                                       |
| ------------- | --------------- | ------------------------------------------------- |
| `offer`       | `ERC20`         | the ERC0 token they want to exchange for the want |
| `user`        | `address`       | the address of the user making the request        |
| `userRequest` | `AtomicRequest` | the request struct to validate                    |

### updateAtomicRequest

Allows user to add/update their withdraw request.

It is possible for a withdraw request with a zero atomicPrice to be made, and solved. If this happens, users will be selling their shares for no assets in return. To determine a safe atomicPrice, share.previewRedeem should be used to get a good share price, then the user can lower it from there to make their request fill faster.

```solidity
function updateAtomicRequest(ERC20 offer, ERC20 want, AtomicRequest calldata userRequest) external nonReentrant;
```

**Parameters**

| Name          | Type            | Description                                                   |
| ------------- | --------------- | ------------------------------------------------------------- |
| `offer`       | `ERC20`         | the ERC20 token the user is offering in exchange for the want |
| `want`        | `ERC20`         | the ERC20 token the user wants in exchange for offer          |
| `userRequest` | `AtomicRequest` | the users request                                             |

### solve

Called by solvers in order to exchange offer asset for want asset.

Solvers are optimistically transferred the offer asset, then are required to approve this contract to spend enough of want assets to cover all requests.

*It is very likely `solve` TXs will be front run if broadcasted to public mem pools, so solvers should use private mem pools.*

```solidity
function solve(
    ERC20 offer,
    ERC20 want,
    address[] calldata users,
    bytes calldata runData,
    address solver
)
    external
    nonReentrant;
```

**Parameters**

| Name      | Type        | Description                                                           |
| --------- | ----------- | --------------------------------------------------------------------- |
| `offer`   | `ERC20`     | the ERC20 offer token to solve for                                    |
| `want`    | `ERC20`     | the ERC20 want token to solve for                                     |
| `users`   | `address[]` | an array of user addresses to solve for                               |
| `runData` | `bytes`     | extra data that is passed back to solver when `finishSolve` is called |
| `solver`  | `address`   | the address to make `finishSolve` callback to                         |

### viewSolveMetaData

Helper function solvers can use to determine if users are solvable, and the required amounts to do so.

Repeated users are not accounted for in this setup, so if solvers have repeat users in their `users` array the results can be wrong.

*Since a user can have multiple requests with the same offer asset but different want asset, it is possible for `viewSolveMetaData` to report no errors, but for a solve to fail, if any solves were done between the time `viewSolveMetaData` and before `solve` is called.*

```solidity
function viewSolveMetaData(
    ERC20 offer,
    ERC20 want,
    address[] calldata users
)
    external
    view
    returns (SolveMetaData[] memory metaData, uint256 totalAssetsForWant, uint256 totalAssetsToOffer);
```

**Parameters**

| Name    | Type        | Description                                         |
| ------- | ----------- | --------------------------------------------------- |
| `offer` | `ERC20`     | the ERC20 offer token to check for solvability      |
| `want`  | `ERC20`     | the ERC20 want token to check for solvability       |
| `users` | `address[]` | an array of user addresses to check for solvability |

### \_calculateAssetAmount

Helper function to calculate the amount of want assets a users wants in exchange for `offerAmount` of offer asset.

```solidity
function _calculateAssetAmount(
    uint256 offerAmount,
    uint256 atomicPrice,
    uint8 offerDecimals
)
    internal
    pure
    returns (uint256);
```

## Events

### AtomicRequestUpdated

Emitted when `updateAtomicRequest` is called.

```solidity
event AtomicRequestUpdated(
    address user,
    address offerToken,
    address wantToken,
    uint256 amount,
    uint256 deadline,
    uint256 minPrice,
    uint256 timestamp
);
```

### AtomicRequestFulfilled

Emitted when `solve` exchanges a users offer asset for their want asset.

```solidity
event AtomicRequestFulfilled(
    address user,
    address offerToken,
    address wantToken,
    uint256 offerAmountSpent,
    uint256 wantAmountReceived,
    uint256 timestamp
);
```

## Errors

### AtomicQueue\_\_UserRepeated

```solidity
error AtomicQueue__UserRepeated(address user);
```

### AtomicQueue\_\_RequestDeadlineExceeded

```solidity
error AtomicQueue__RequestDeadlineExceeded(address user);
```

### AtomicQueue\_\_UserNotInSolve

```solidity
error AtomicQueue__UserNotInSolve(address user);
```

### AtomicQueue\_\_ZeroOfferAmount

```solidity
error AtomicQueue__ZeroOfferAmount(address user);
```

## Structs

### AtomicRequest

Stores request information needed to fulfill a users atomic request.

*atomicPrice MUST be in terms of `want` asset decimals.*

```solidity
struct AtomicRequest {
    uint64 deadline;
    uint88 atomicPrice;
    uint96 offerAmount;
    bool inSolve;
}
```

**Properties**

| Name          | Type     | Description                                                                                |
| ------------- | -------- | ------------------------------------------------------------------------------------------ |
| `deadline`    | `uint64` | unix timestamp for when request is no longer valid                                         |
| `atomicPrice` | `uint88` | the price in terms of `want` asset the user wants their `offer` assets "sold" at           |
| `offerAmount` | `uint96` | the amount of `offer` asset the user wants converted to `want` asset                       |
| `inSolve`     | `bool`   | bool used during solves to prevent duplicate users, and to prevent redoing multiple checks |

### SolveMetaData

Used in `viewSolveMetaData` helper function to return data in a clean struct.

```solidity
struct SolveMetaData {
    address user;
    uint8 flags;
    uint256 assetsToOffer;
    uint256 assetsForWant;
}
```

**Properties**

| Name            | Type      | Description                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `user`          | `address` | the address of the user                                                                                                                                                                                                                                                                                                                                                                                   |
| `flags`         | `uint8`   | 8 bits indicating the state of the user only the first 4 bits are used XXXX0000 Either all flags are false(user is solvable) or only 1 is true(an error occurred). From right to left - 0: indicates user deadline has passed. - 1: indicates user request has zero offer amount. - 2: indicates user does not have enough offer asset in wallet. - 3: indicates user has not given AtomicQueue approval. |
| `assetsToOffer` | `uint256` | the amount of offer asset to solve                                                                                                                                                                                                                                                                                                                                                                        |
| `assetsForWant` | `uint256` | the amount of assets users want for their offer assets                                                                                                                                                                                                                                                                                                                                                    |


# AtomicSolver

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/atomic-queue/AtomicSolver.sol)

**Inherits:** IAtomicSolver, Owned, ERC721Holder

**Author:**

## State Variables

### \_solving

```solidity
bool private _solving;
```

### \_balancerVault

```solidity
address private immutable _balancerVault;
```

### approvedToCallFinishSolve

```solidity
mapping(address => bool) private approvedToCallFinishSolve;
```

## Functions

### constructor

```solidity
constructor(address _owner, address _vault) Owned(_owner);
```

### updateMapping

```solidity
function updateMapping(address who, bool state) external onlyOwner;
```

### finishSolve

```solidity
function finishSolve(
    bytes calldata runData,
    address initiator,
    ERC20,
    ERC20 want,
    uint256,
    uint256 assetsForWant
)
    external;
```

### doStuff

```solidity
function doStuff(
    address[] calldata targets,
    uint256[] calldata values,
    bytes[] calldata ammo
)
    external
    payable
    onlyOwner;
```

### receiveFlashLoan

```solidity
function receiveFlashLoan(
    address[] calldata tokens,
    uint256[] calldata amounts,
    uint256[] calldata feeAmounts,
    bytes calldata userData
)
    external;
```

### getEth

```solidity
function getEth(address payable receiver) external onlyOwner;
```

### receive

```solidity
receive() external payable;
```


# AtomicSolverV2

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/atomic-queue/AtomicSolverV2.sol)

**Inherits:** IAtomicSolver, Auth

**Author:** crispymangoes

## State Variables

### eETH

```solidity
ERC20 internal constant eETH = ERC20(0x35fA164735182de50811E8e2E824cFb9B6118ac2);
```

### weETH

```solidity
ERC20 internal constant weETH = ERC20(0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee);
```

## Functions

### constructor

```solidity
constructor(address _owner, Authority _authority) Auth(_owner, _authority);
```

### p2pSolve

Solver wants to exchange p2p share.asset() for withdraw queue shares.

*Solver should approve this contract to spend share.asset().*

```solidity
function p2pSolve(
    AtomicQueue queue,
    ERC20 offer,
    ERC20 want,
    address[] calldata users,
    uint256 minOfferReceived,
    uint256 maxAssets
)
    external
    requiresAuth;
```

### redeemSolve

Solver wants to redeem withdraw offer shares, to help cover withdraw.

*`offer` MUST be an ERC4626 vault.*

```solidity
function redeemSolve(
    AtomicQueue queue,
    ERC20 offer,
    ERC20 want,
    address[] calldata users,
    uint256 minAssetDelta,
    uint256 maxAssets
)
    external
    requiresAuth;
```

### redeemLiquidSolve

Solver wants to redeem withdraw offer shares, to help cover withdraw.

*`offer` MUST be an ERC4626 vault.*

```solidity
function redeemLiquidSolve(
    AtomicQueue queue,
    ERC20 offer,
    ERC20 want,
    address[] calldata users,
    uint256 minAssetDelta,
    uint256 maxAssets
)
    external
    requiresAuth;
```

### finishSolve

Implement the finishSolve function WithdrawQueue expects to call.

*nonReentrant is not needed on this function because it is impossible to reenter, because the above solve functions have the nonReentrant modifier. The only way to have the first 2 checks pass is if the msg.sender is the queue, and this contract is msg.sender of `Queue.solve()`, which is only called in the above functions.*

```solidity
function finishSolve(
    bytes calldata runData,
    address initiator,
    ERC20 offer,
    ERC20 want,
    uint256 offerReceived,
    uint256 wantApprovalAmount
)
    external
    requiresAuth;
```

### \_p2pSolve

Helper function containing the logic to handle p2p solves.

```solidity
function _p2pSolve(
    address queue,
    bytes memory runData,
    ERC20 offer,
    ERC20 want,
    uint256 offerReceived,
    uint256 wantApprovalAmount
)
    internal;
```

### \_redeemSolve

Helper function containing the logic to handle redeem solves.

```solidity
function _redeemSolve(
    address queue,
    bytes memory runData,
    ERC20 offer,
    ERC20 want,
    uint256 offerReceived,
    uint256 wantApprovalAmount
)
    internal;
```

### \_redeemLiquidSolve

Helper function containing the logic to handle redeem solves.

```solidity
function _redeemLiquidSolve(
    address queue,
    bytes memory runData,
    ERC20 offer,
    ERC20 want,
    uint256 offerReceived,
    uint256 wantApprovalAmount
)
    internal;
```

## Errors

### AtomicSolverV2\_\_\_WrongInitiator

```solidity
error AtomicSolverV2___WrongInitiator();
```

### AtomicSolverV2\_\_\_AlreadyInSolveContext

```solidity
error AtomicSolverV2___AlreadyInSolveContext();
```

### AtomicSolverV2\_\_\_FailedToSolve

```solidity
error AtomicSolverV2___FailedToSolve();
```

### AtomicSolverV2\_\_\_SolveMaxAssetsExceeded

```solidity
error AtomicSolverV2___SolveMaxAssetsExceeded(uint256 actualAssets, uint256 maxAssets);
```

### AtomicSolverV2\_\_\_P2PSolveMinSharesNotMet

```solidity
error AtomicSolverV2___P2PSolveMinSharesNotMet(uint256 actualShares, uint256 minShares);
```

### AtomicSolverV2\_\_\_RedeemSolveMinAssetDeltaNotMet

```solidity
error AtomicSolverV2___RedeemSolveMinAssetDeltaNotMet(uint256 actualDelta, uint256 minDelta);
```

## Enums

### SolveType

The Solve Type, used in `finishSolve` to determine the logic used.

P2P Solver wants to swap share.asset() for user(s) shares

REDEEM Solver needs to redeem shares, then can cover user(s) required assets.

```solidity
enum SolveType {
    P2P,
    REDEEM,
    REDEEM_LIQUID
}
```


# AtomicSolverV3

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/atomic-queue/AtomicSolverV3.sol)

**Inherits:** IAtomicSolver, Auth

**Author:** crispymangoes

## State Variables

### eETH

```solidity
ERC20 internal constant eETH = ERC20(0x35fA164735182de50811E8e2E824cFb9B6118ac2);
```

### weETH

```solidity
ERC20 internal constant weETH = ERC20(0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee);
```

## Functions

### constructor

```solidity
constructor(address _owner, Authority _authority) Auth(_owner, _authority);
```

### p2pSolve

Solver wants to exchange p2p share.asset() for withdraw queue shares.

*Solver should approve this contract to spend share.asset().*

```solidity
function p2pSolve(
    AtomicQueue queue,
    ERC20 offer,
    ERC20 want,
    address[] calldata users,
    uint256 minOfferReceived,
    uint256 maxAssets
)
    external
    requiresAuth;
```

### redeemSolve

Solver wants to redeem withdraw offer shares, to help cover withdraw.

*`offer` MUST be an ERC4626 vault.*

```solidity
function redeemSolve(
    AtomicQueue queue,
    ERC20 offer,
    ERC20 want,
    address[] calldata users,
    uint256 minimumAssetsOut,
    uint256 maxAssets,
    TellerWithMultiAssetSupport teller
)
    external
    requiresAuth;
```

### finishSolve

Implement the finishSolve function WithdrawQueue expects to call.

*nonReentrant is not needed on this function because it is impossible to reenter, because the above solve functions have the nonReentrant modifier. The only way to have the first 2 checks pass is if the msg.sender is the queue, and this contract is msg.sender of `Queue.solve()`, which is only called in the above functions.*

```solidity
function finishSolve(
    bytes calldata runData,
    address initiator,
    ERC20 offer,
    ERC20 want,
    uint256 offerReceived,
    uint256 wantApprovalAmount
)
    external
    requiresAuth;
```

### \_p2pSolve

Helper function containing the logic to handle p2p solves.

```solidity
function _p2pSolve(
    address queue,
    bytes memory runData,
    ERC20 offer,
    ERC20 want,
    uint256 offerReceived,
    uint256 wantApprovalAmount
)
    internal;
```

### \_redeemSolve

Helper function containing the logic to handle redeem solves.

```solidity
function _redeemSolve(
    address queue,
    bytes memory runData,
    ERC20 offer,
    ERC20 want,
    uint256 offerReceived,
    uint256 wantApprovalAmount
)
    internal;
```

## Errors

### AtomicSolverV3\_\_\_WrongInitiator

```solidity
error AtomicSolverV3___WrongInitiator();
```

### AtomicSolverV3\_\_\_AlreadyInSolveContext

```solidity
error AtomicSolverV3___AlreadyInSolveContext();
```

### AtomicSolverV3\_\_\_FailedToSolve

```solidity
error AtomicSolverV3___FailedToSolve();
```

### AtomicSolverV3\_\_\_SolveMaxAssetsExceeded

```solidity
error AtomicSolverV3___SolveMaxAssetsExceeded(uint256 actualAssets, uint256 maxAssets);
```

### AtomicSolverV3\_\_\_P2PSolveMinSharesNotMet

```solidity
error AtomicSolverV3___P2PSolveMinSharesNotMet(uint256 actualShares, uint256 minShares);
```

### AtomicSolverV3\_\_\_BoringVaultTellerMismatch

```solidity
error AtomicSolverV3___BoringVaultTellerMismatch(address vault, address teller);
```

## Enums

### SolveType

The Solve Type, used in `finishSolve` to determine the logic used.

P2P Solver wants to swap share.asset() for user(s) shares

REDEEM Solver needs to redeem shares, then can cover user(s) required assets.

```solidity
enum SolveType {
    P2P,
    REDEEM
}
```


# IAtomicSolver

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/atomic-queue/IAtomicSolver.sol)

## Functions

### finishSolve

This function must be implemented in order for an address to be a `solver` for the AtomicQueue

```solidity
function finishSolve(
    bytes calldata runData,
    address initiator,
    ERC20 offer,
    ERC20 want,
    uint256 assetsToOffer,
    uint256 assetsForWant
)
    external;
```

**Parameters**

| Name            | Type      | Description                                                                                                              |
| --------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ |
| `runData`       | `bytes`   | arbitrary bytes data that is dependent on how each solver is setup it could contain swap data, or flash loan data, etc.. |
| `initiator`     | `address` | the address that initiated a solve                                                                                       |
| `offer`         | `ERC20`   | the ERC20 asset sent to the solver                                                                                       |
| `want`          | `ERC20`   | the ERC20 asset the solver must approve the queue for                                                                    |
| `assetsToOffer` | `uint256` | the amount of `offer` sent to the solver                                                                                 |
| `assetsForWant` | `uint256` | the amount of `want` the solver must approve the queue for                                                               |


# base


# Boring Vault


# BoringVault

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/BoringVault.sol)

**Inherits:** ERC20, Auth, ERC721Holder, ERC1155Holder

## State Variables

### hook

Contract responsible for implementing `beforeTransfer`.

```solidity
BeforeTransferHook public hook;
```

## Functions

### constructor

```solidity
constructor(
    address _owner,
    string memory _name,
    string memory _symbol,
    uint8 _decimals
)
    ERC20(_name, _symbol, _decimals)
    Auth(_owner, Authority(address(0)));
```

### manage

Allows manager to make an arbitrary function call from this contract.

*Callable by MANAGER\_ROLE.*

```solidity
function manage(
    address target,
    bytes calldata data,
    uint256 value
)
    external
    requiresAuth
    returns (bytes memory result);
```

### manage

Allows manager to make arbitrary function calls from this contract.

*Callable by MANAGER\_ROLE.*

```solidity
function manage(
    address[] calldata targets,
    bytes[] calldata data,
    uint256[] calldata values
)
    external
    requiresAuth
    returns (bytes[] memory results);
```

### enter

Allows minter to mint shares, in exchange for assets.

*If assetAmount is zero, no assets are transferred in.*

*Callable by MINTER\_ROLE.*

```solidity
function enter(address from, ERC20 asset, uint256 assetAmount, address to, uint256 shareAmount) external requiresAuth;
```

### exit

Allows burner to burn shares, in exchange for assets.

*If assetAmount is zero, no assets are transferred out.*

*Callable by BURNER\_ROLE.*

```solidity
function exit(address to, ERC20 asset, uint256 assetAmount, address from, uint256 shareAmount) external requiresAuth;
```

### setBeforeTransferHook

Sets the share locker.

If set to zero address, the share locker logic is disabled.

*Callable by OWNER\_ROLE.*

```solidity
function setBeforeTransferHook(address _hook) external requiresAuth;
```

### \_callBeforeTransfer

Check if from addresses shares are locked, reverting if so.

```solidity
function _callBeforeTransfer(address from) internal view;
```

### transfer

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

### transferFrom

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

### receive

```solidity
receive() external payable;
```

## Events

### Enter

```solidity
event Enter(address indexed from, address indexed asset, uint256 amount, address indexed to, uint256 shares);
```

### Exit

```solidity
event Exit(address indexed to, address indexed asset, uint256 amount, address indexed from, uint256 shares);
```


# Decoders and Sanitizers


# Contents

* ERC4626DecoderAndSanitizer
* NativeWrapperDecoderAndSanitizer
* IonPoolDecoderAndSanitizer


# IonPoolDecoderAndSanitizer

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/DecodersAndSanitizers/IonPoolDecoderAndSanitizer.sol)

**Inherits:** BaseDecoderAndSanitizer

## Functions

### constructor

```solidity
constructor(address _boringVault) BaseDecoderAndSanitizer(_boringVault);
```

### supply

```solidity
function supply(address recipient, uint256, bytes32[] calldata) external pure returns (bytes memory addressesFound);
```

### withdraw

```solidity
function withdraw(address receiverOfUnderlying, uint256) external pure returns (bytes memory addressesFound);
```


# Roles


# Contents

* CrossChain
* AccountantWithRateProviders
* ManagerWithMerkleVerification
* TellerWithMultiAssetSupport


# Cross Chain


# Cross Chain OP Teller With Multi Asset Support


# CrossChainOPTellerWithMultiAssetSupport

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/CrossChainOPTellerWithMultiAssetSupport.sol)

**Inherits:** CrossChainTellerBase

LayerZero implementation of CrossChainTeller

## State Variables

### messenger

```solidity
ICrossDomainMessenger public immutable messenger;
```

### peer

```solidity
address public peer;
```

### maxMessageGas

```solidity
uint32 public maxMessageGas;
```

### minMessageGas

```solidity
uint32 public minMessageGas;
```

### nonce

```solidity
uint128 public nonce;
```

## Functions

### constructor

```solidity
constructor(
    address _owner,
    address _vault,
    address _accountant,
    address _messenger
)
    CrossChainTellerBase(_owner, _vault, _accountant);
```

### setPeer

Callable by OWNER\_ROLE.

```solidity
function setPeer(address _peer) external requiresAuth;
```

**Parameters**

| Name    | Type      | Description     |
| ------- | --------- | --------------- |
| `_peer` | `address` | new peer to set |

### setGasBounds

*Callable by OWNER\_ROLE.*

```solidity
function setGasBounds(uint32 newMinMessageGas, uint32 newMaxMessageGas) external requiresAuth;
```

**Parameters**

| Name               | Type     | Description                 |
| ------------------ | -------- | --------------------------- |
| `newMinMessageGas` | `uint32` | the new minMessageGas bound |
| `newMaxMessageGas` | `uint32` | the new maxMessageGas bound |

### receiveBridgeMessage

Function for OP Messenger to call to receive a message and mint the shares on this chain

```solidity
function receiveBridgeMessage(address receiver, uint256 shareMintAmount, bytes32 messageId) external;
```

**Parameters**

| Name              | Type      | Description              |
| ----------------- | --------- | ------------------------ |
| `receiver`        | `address` | to receive the shares    |
| `shareMintAmount` | `uint256` | amount of shares to mint |
| `messageId`       | `bytes32` |                          |

### \_bridge

the virtual bridge function to execute Optimism messenger sendMessage()

```solidity
function _bridge(uint256 shareAmount, BridgeData calldata data) internal override returns (bytes32 messageId);
```

**Parameters**

| Name          | Type         | Description |
| ------------- | ------------ | ----------- |
| `shareAmount` | `uint256`    |             |
| `data`        | `BridgeData` | bridge data |

**Returns**

| Name        | Type      | Description |
| ----------- | --------- | ----------- |
| `messageId` | `bytes32` | messageId   |

### \_beforeBridge

before bridge hook to check gas bound and revert if someone's paying a fee

```solidity
function _beforeBridge(BridgeData calldata data) internal override;
```

**Parameters**

| Name   | Type         | Description |
| ------ | ------------ | ----------- |
| `data` | `BridgeData` | bridge data |

### \_quote

the virtual function to override to get bridge fees, always zero for OP

```solidity
function _quote(uint256 shareAmount, BridgeData calldata data) internal view override returns (uint256);
```

**Parameters**

| Name          | Type         | Description |
| ------------- | ------------ | ----------- |
| `shareAmount` | `uint256`    | to send     |
| `data`        | `BridgeData` | bridge data |

## Errors

### CrossChainOPTellerWithMultiAssetSupport\_OnlyMessenger

```solidity
error CrossChainOPTellerWithMultiAssetSupport_OnlyMessenger();
```

### CrossChainOPTellerWithMultiAssetSupport\_OnlyPeerAsSender

```solidity
error CrossChainOPTellerWithMultiAssetSupport_OnlyPeerAsSender();
```

### CrossChainOPTellerWithMultiAssetSupport\_NoFee

```solidity
error CrossChainOPTellerWithMultiAssetSupport_NoFee();
```

### CrossChainOPTellerWithMultiAssetSupport\_GasOutOfBounds

```solidity
error CrossChainOPTellerWithMultiAssetSupport_GasOutOfBounds(uint32);
```


# ICrossDomainMessenger

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/CrossChainOPTellerWithMultiAssetSupport.sol)

## Functions

### xDomainMessageSender

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

### sendMessage

```solidity
function sendMessage(address _target, bytes calldata _message, uint32 _gasLimit) external;
```


# Cross Chain Teller Base


# BridgeData

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/CrossChainTellerBase.sol)

```solidity
struct BridgeData {
    uint32 chainSelector;
    address destinationChainReceiver;
    ERC20 bridgeFeeToken;
    uint64 messageGas;
    bytes data;
}
```


# CrossChainTellerBase

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/CrossChainTellerBase.sol)

**Inherits:** TellerWithMultiAssetSupport

Base contract for the CrossChainTeller, includes functions to overload with specific bridge method

## Functions

### constructor

```solidity
constructor(
    address _owner,
    address _vault,
    address _accountant
)
    TellerWithMultiAssetSupport(_owner, _vault, _accountant);
```

### depositAndBridge

function to deposit into the vault AND bridge crosschain in 1 call

```solidity
function depositAndBridge(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint,
    BridgeData calldata data
)
    external
    payable
    requiresAuth
    nonReentrant;
```

**Parameters**

| Name            | Type         | Description                        |
| --------------- | ------------ | ---------------------------------- |
| `depositAsset`  | `ERC20`      | ERC20 to deposit                   |
| `depositAmount` | `uint256`    | amount of deposit asset to deposit |
| `minimumMint`   | `uint256`    | minimum required shares to receive |
| `data`          | `BridgeData` | Bridge Data                        |

### previewFee

Preview fee required to bridge shares in a given feeToken.

```solidity
function previewFee(uint256 shareAmount, BridgeData calldata data) external view returns (uint256 fee);
```

### bridge

bridging code to be done without deposit, for users who already have vault tokens

```solidity
function bridge(
    uint256 shareAmount,
    BridgeData calldata data
)
    public
    payable
    requiresAuth
    returns (bytes32 messageId);
```

**Parameters**

| Name          | Type         | Description |
| ------------- | ------------ | ----------- |
| `shareAmount` | `uint256`    | to bridge   |
| `data`        | `BridgeData` | bridge data |

### \_bridge

the virtual bridge function to be overridden

```solidity
function _bridge(uint256 shareAmount, BridgeData calldata data) internal virtual returns (bytes32);
```

**Parameters**

| Name          | Type         | Description |
| ------------- | ------------ | ----------- |
| `shareAmount` | `uint256`    |             |
| `data`        | `BridgeData` | bridge data |

**Returns**

| Name     | Type      | Description |
| -------- | --------- | ----------- |
| `<none>` | `bytes32` | messageId   |

### \_quote

the virtual function to override to get bridge fees

```solidity
function _quote(uint256 shareAmount, BridgeData calldata data) internal view virtual returns (uint256);
```

**Parameters**

| Name          | Type         | Description |
| ------------- | ------------ | ----------- |
| `shareAmount` | `uint256`    | to send     |
| `data`        | `BridgeData` | bridge data |

### \_beforeBridge

after bridge code, just an emit but can be overridden

the before bridge hook to perform additional checks

```solidity
function _beforeBridge(BridgeData calldata data) internal virtual;
```

**Parameters**

| Name   | Type         | Description |
| ------ | ------------ | ----------- |
| `data` | `BridgeData` | bridge data |

### \_afterBridge

after bridge code, just an emit but can be overridden

```solidity
function _afterBridge(uint256 shareAmount, BridgeData calldata data, bytes32 messageId) internal virtual;
```

**Parameters**

| Name          | Type         | Description                      |
| ------------- | ------------ | -------------------------------- |
| `shareAmount` | `uint256`    | share amount burned              |
| `data`        | `BridgeData` | bridge data                      |
| `messageId`   | `bytes32`    | message id returned when bridged |

### \_beforeReceive

a before receive hook to call some logic before a receive is processed

```solidity
function _beforeReceive() internal virtual;
```

### \_afterReceive

a hook to execute after receiving

```solidity
function _afterReceive(uint256 shareAmount, address destinationChainReceiver, bytes32 messageId) internal virtual;
```

**Parameters**

| Name                       | Type      | Description                     |
| -------------------------- | --------- | ------------------------------- |
| `shareAmount`              | `uint256` | the shareAmount that was minted |
| `destinationChainReceiver` | `address` | the receiver of the shares      |
| `messageId`                | `bytes32` | the message ID                  |

## Events

### MessageSent

```solidity
event MessageSent(bytes32 messageId, uint256 shareAmount, address to);
```

### MessageReceived

```solidity
event MessageReceived(bytes32 messageId, uint256 shareAmount, address to);
```


# MultiChainLayerZeroTellerWithMultiAssetSupport

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainLayerZeroTellerWithMultiAssetSupport.sol)

**Inherits:** MultiChainTellerBase, OAppAuth

LayerZero implementation of MultiChainTeller

## Functions

### constructor

```solidity
constructor(
    address _owner,
    address _vault,
    address _accountant,
    address _endpoint
)
    MultiChainTellerBase(_owner, _vault, _accountant)
    OAppAuth(_endpoint, _owner);
```

### \_quote

function override to return the fee quote

```solidity
function _quote(uint256 shareAmount, BridgeData calldata data) internal view override returns (uint256);
```

**Parameters**

| Name          | Type         | Description             |
| ------------- | ------------ | ----------------------- |
| `shareAmount` | `uint256`    | to be sent as a message |
| `data`        | `BridgeData` | Bridge data             |

### \_lzReceive

Called when data is received from the protocol. It overrides the equivalent function in the parent contract. Protocol messages are defined as packets, comprised of the following parameters.

```solidity
function _lzReceive(
    Origin calldata _origin,
    bytes32 _guid,
    bytes calldata payload,
    address,
    bytes calldata
)
    internal
    override;
```

**Parameters**

| Name      | Type      | Description                                                       |
| --------- | --------- | ----------------------------------------------------------------- |
| `_origin` | `Origin`  | A struct containing information about where the packet came from. |
| `_guid`   | `bytes32` | A global unique identifier for tracking the packet.               |
| `payload` | `bytes`   | Encoded message.                                                  |
| `<none>`  | `address` |                                                                   |
| `<none>`  | `bytes`   |                                                                   |

### \_bridge

bridge override to allow bridge logic to be done for bridge() and depositAndBridge()

```solidity
function _bridge(uint256 shareAmount, BridgeData calldata data) internal override returns (bytes32);
```

**Parameters**

| Name          | Type         | Description              |
| ------------- | ------------ | ------------------------ |
| `shareAmount` | `uint256`    | to be moved across chain |
| `data`        | `BridgeData` | BridgeData               |

## Errors

### MultiChainLayerZeroTellerWithMultiAssetSupport\_InvalidToken

```solidity
error MultiChainLayerZeroTellerWithMultiAssetSupport_InvalidToken();
```


# Multi Chain Teller Base


# Chain

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

```solidity
struct Chain {
    bool allowMessagesFrom;
    bool allowMessagesTo;
    address targetTeller;
    uint64 messageGasLimit;
    uint64 minimumMessageGas;
}
```


# MultiChainTellerBase

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

**Inherits:** CrossChainTellerBase

Base contract for the MultiChainTellers, We've noticed that many bridge options are L1 -> L2 only, which are quite simple IE Optimism Messenger While others like LZ that can contact many bridges, contain lots of additional complexity to manage the configuration for these chains To keep this separated we are using this MultiChain syntax for the > 2 chain messaging while only CrossChain for 2 chain messengers like OP

## State Variables

### selectorToChains

```solidity
mapping(uint32 => Chain) public selectorToChains;
```

## Functions

### constructor

```solidity
constructor(address _owner, address _vault, address _accountant) CrossChainTellerBase(_owner, _vault, _accountant);
```

### addChain

adds an acceptable chain to bridge to

*Callable by OWNER\_ROLE.*

```solidity
function addChain(
    uint32 chainSelector,
    bool allowMessagesFrom,
    bool allowMessagesTo,
    address targetTeller,
    uint64 messageGasLimit,
    uint64 messageGasMin
)
    external
    requiresAuth;
```

**Parameters**

| Name                | Type      | Description                                      |
| ------------------- | --------- | ------------------------------------------------ |
| `chainSelector`     | `uint32`  | chainSelector of chain                           |
| `allowMessagesFrom` | `bool`    | allow messages from this chain                   |
| `allowMessagesTo`   | `bool`    | allow messages to the chain                      |
| `targetTeller`      | `address` | address of the target teller on this chain       |
| `messageGasLimit`   | `uint64`  | to pass to bridge                                |
| `messageGasMin`     | `uint64`  | to require a minimum provided gas for this chain |

### stopMessagesFromChain

block messages from a particular chain

*Callable by OWNER\_ROLE.*

```solidity
function stopMessagesFromChain(uint32 chainSelector) external requiresAuth;
```

**Parameters**

| Name            | Type     | Description |
| --------------- | -------- | ----------- |
| `chainSelector` | `uint32` | of chain    |

### allowMessagesFromChain

allow messages from a particular chain

*Callable by OWNER\_ROLE.*

```solidity
function allowMessagesFromChain(uint32 chainSelector, address targetTeller) external requiresAuth;
```

**Parameters**

| Name            | Type      | Description |
| --------------- | --------- | ----------- |
| `chainSelector` | `uint32`  | of chain    |
| `targetTeller`  | `address` |             |

### removeChain

Remove a chain from the teller.

*Callable by OWNER\_ROLE.*

*Callable by OWNER\_ROLE.*

```solidity
function removeChain(uint32 chainSelector) external requiresAuth;
```

### allowMessagesToChain

Allow messages to a chain.

*Callable by OWNER\_ROLE.*

```solidity
function allowMessagesToChain(
    uint32 chainSelector,
    address targetTeller,
    uint64 messageGasLimit
)
    external
    requiresAuth;
```

### stopMessagesToChain

Stop messages to a chain.

*Callable by OWNER\_ROLE.*

```solidity
function stopMessagesToChain(uint32 chainSelector) external requiresAuth;
```

### setChainGasLimit

Set the gas limit for messages to a chain.

*Callable by OWNER\_ROLE.*

```solidity
function setChainGasLimit(uint32 chainSelector, uint64 messageGasLimit) external requiresAuth;
```

### \_beforeBridge

override beforeBridge to check Chain struct

```solidity
function _beforeBridge(BridgeData calldata data) internal override;
```

**Parameters**

| Name   | Type         | Description |
| ------ | ------------ | ----------- |
| `data` | `BridgeData` | bridge data |

## Events

### ChainAdded

```solidity
event ChainAdded(
    uint256 chainSelector,
    bool allowMessagesFrom,
    bool allowMessagesTo,
    address targetTeller,
    uint64 messageGasLimit,
    uint64 messageGasMin
);
```

### ChainRemoved

```solidity
event ChainRemoved(uint256 chainSelector);
```

### ChainAllowMessagesFrom

```solidity
event ChainAllowMessagesFrom(uint256 chainSelector, address targetTeller);
```

### ChainAllowMessagesTo

```solidity
event ChainAllowMessagesTo(uint256 chainSelector, address targetTeller);
```

### ChainStopMessagesFrom

```solidity
event ChainStopMessagesFrom(uint256 chainSelector);
```

### ChainStopMessagesTo

```solidity
event ChainStopMessagesTo(uint256 chainSelector);
```

### ChainSetGasLimit

```solidity
event ChainSetGasLimit(uint256 chainSelector, uint64 messageGasLimit);
```


# MultiChainTellerBase\_GasLimitExceeded

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

```solidity
error MultiChainTellerBase_GasLimitExceeded();
```


# MultiChainTellerBase\_GasTooLow

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

```solidity
error MultiChainTellerBase_GasTooLow();
```


# MultiChainTellerBase\_MessagesNotAllowedFrom

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

```solidity
error MultiChainTellerBase_MessagesNotAllowedFrom(uint32 chainSelector);
```


# MultiChainTellerBase\_MessagesNotAllowedFromSender

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

```solidity
error MultiChainTellerBase_MessagesNotAllowedFromSender(uint256 chainSelector, address sender);
```


# MultiChainTellerBase\_MessagesNotAllowedTo

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

```solidity
error MultiChainTellerBase_MessagesNotAllowedTo(uint256 chainSelector);
```


# MultiChainTellerBase\_ZeroMessageGasLimit

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/MultiChainTellerBase.sol)

```solidity
error MultiChainTellerBase_ZeroMessageGasLimit();
```


# OAppAuth


# Contents

* OAppAuth
* OAppAuthCore
* OAppAuthReceiver
* OAppAuthSender


# OAppAuth

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/OAppAuth/OAppAuth.sol)

**Inherits:** OAppAuthSender, OAppAuthReceiver

*Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.*

*This Auth version of OAppCore uses solmate's Auth instead of OZ's Ownable for compatibility purposes*

## Functions

### constructor

*Constructor to initialize the OApp with the provided endpoint and owner.*

```solidity
constructor(address _endpoint, address _delegate) OAppAuthCore(_endpoint, _delegate);
```

**Parameters**

| Name        | Type      | Description                                                                |
| ----------- | --------- | -------------------------------------------------------------------------- |
| `_endpoint` | `address` | The address of the LOCAL LayerZero endpoint.                               |
| `_delegate` | `address` | The delegate capable of making OApp configurations inside of the endpoint. |

### oAppVersion

Retrieves the OApp version information.

```solidity
function oAppVersion()
    public
    pure
    virtual
    override(OAppAuthSender, OAppAuthReceiver)
    returns (uint64 senderVersion, uint64 receiverVersion);
```

**Returns**

| Name              | Type     | Description                                         |
| ----------------- | -------- | --------------------------------------------------- |
| `senderVersion`   | `uint64` | The version of the OAppSender.sol implementation.   |
| `receiverVersion` | `uint64` | The version of the OAppReceiver.sol implementation. |


# OAppAuthCore

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/OAppAuth/OAppAuthCore.sol)

**Inherits:** IOAppCore, Auth

*Abstract contract implementing the IOAppCore interface with basic OApp configurations.*

*This Auth version of OAppCore uses solmate's Auth instead of OZ's Ownable for compatibility purposes*

## State Variables

### endpoint

```solidity
ILayerZeroEndpointV2 public immutable endpoint;
```

### peers

```solidity
mapping(uint32 eid => bytes32 peer) public peers;
```

## Functions

### constructor

*Constructor to initialize the OAppCore with the provided endpoint and delegate.*

*The delegate typically should be set as the owner of the contract.*

```solidity
constructor(address _endpoint, address _delegate);
```

**Parameters**

| Name        | Type      | Description                                                                |
| ----------- | --------- | -------------------------------------------------------------------------- |
| `_endpoint` | `address` | The address of the LOCAL Layer Zero endpoint.                              |
| `_delegate` | `address` | The delegate capable of making OApp configurations inside of the endpoint. |

### setPeer

Sets the peer address (OApp instance) for a corresponding endpoint.

this contract replaces the OZ Ownable onlyOwner with Solmate requiresAuth

*Only the owner/admin of the OApp can call this function.*

*Indicates that the peer is trusted to send LayerZero messages to this OApp.*

*Set this to bytes32(0) to remove the peer address.*

*Peer is a bytes32 to accommodate non-evm chains.*

```solidity
function setPeer(uint32 _eid, bytes32 _peer) public virtual requiresAuth;
```

**Parameters**

| Name    | Type      | Description                                                               |
| ------- | --------- | ------------------------------------------------------------------------- |
| `_eid`  | `uint32`  | The endpoint ID.                                                          |
| `_peer` | `bytes32` | The address of the peer to be associated with the corresponding endpoint. |

### \_setPeer

Sets the peer address (OApp instance) for a corresponding endpoint.

*Indicates that the peer is trusted to send LayerZero messages to this OApp.*

*Set this to bytes32(0) to remove the peer address.*

*Peer is a bytes32 to accommodate non-evm chains.*

```solidity
function _setPeer(uint32 _eid, bytes32 _peer) internal virtual;
```

**Parameters**

| Name    | Type      | Description                                                               |
| ------- | --------- | ------------------------------------------------------------------------- |
| `_eid`  | `uint32`  | The endpoint ID.                                                          |
| `_peer` | `bytes32` | The address of the peer to be associated with the corresponding endpoint. |

### \_getPeerOrRevert

Internal function to get the peer address associated with a specific endpoint; reverts if NOT set. ie. the peer is set to bytes32(0).

```solidity
function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32);
```

**Parameters**

| Name   | Type     | Description      |
| ------ | -------- | ---------------- |
| `_eid` | `uint32` | The endpoint ID. |

**Returns**

| Name     | Type      | Description                                                          |
| -------- | --------- | -------------------------------------------------------------------- |
| `<none>` | `bytes32` | peer The address of the peer associated with the specified endpoint. |

### setDelegate

Sets the delegate address for the OApp.

this contract replaces the OZ Ownable onlyOwner with Solmate requiresAuth

*Only the owner/admin of the OApp can call this function.*

*Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.*

```solidity
function setDelegate(address _delegate) public requiresAuth;
```

**Parameters**

| Name        | Type      | Description                            |
| ----------- | --------- | -------------------------------------- |
| `_delegate` | `address` | The address of the delegate to be set. |


# OAppAuthReceiver

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/OAppAuth/OAppAuthReceiver.sol)

**Inherits:** IOAppReceiver, OAppAuthCore

*Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.*

*This Auth version of OAppCore uses solmate's Auth instead of OZ's Ownable for compatibility purposes*

## State Variables

### RECEIVER\_VERSION

```solidity
uint64 internal constant RECEIVER_VERSION = 2;
```

## Functions

### oAppVersion

Retrieves the OApp version information.

*Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented. ie. this is a RECEIVE only OApp.*

*If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.*

```solidity
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion);
```

**Returns**

| Name              | Type     | Description                                   |
| ----------------- | -------- | --------------------------------------------- |
| `senderVersion`   | `uint64` | The version of the OAppSender.sol contract.   |
| `receiverVersion` | `uint64` | The version of the OAppReceiver.sol contract. |

### isComposeMsgSender

Indicates whether an address is an approved composeMsg sender to the Endpoint.

\*\_origin The origin information containing the source endpoint and sender address.

* srcEid: The source chain endpoint ID.
* sender: The sender address on the src chain.
* nonce: The nonce of the message.\*

*\_message The lzReceive payload.*

*Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.*

*The default sender IS the OAppReceiver implementer.*

```solidity
function isComposeMsgSender(Origin calldata, bytes calldata, address _sender) public view virtual returns (bool);
```

**Parameters**

| Name      | Type      | Description         |
| --------- | --------- | ------------------- |
| `<none>`  | `Origin`  |                     |
| `<none>`  | `bytes`   |                     |
| `_sender` | `address` | The sender address. |

**Returns**

| Name     | Type   | Description                 |
| -------- | ------ | --------------------------- |
| `<none>` | `bool` | isSender Is a valid sender. |

### allowInitializePath

Checks if the path initialization is allowed based on the provided origin.

*This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.*

*This defaults to assuming if a peer has been set, its initialized. Can be overridden by the OApp if there is other logic to determine this.*

```solidity
function allowInitializePath(Origin calldata origin) public view virtual returns (bool);
```

**Parameters**

| Name     | Type     | Description                                                               |
| -------- | -------- | ------------------------------------------------------------------------- |
| `origin` | `Origin` | The origin information containing the source endpoint and sender address. |

**Returns**

| Name     | Type   | Description                            |
| -------- | ------ | -------------------------------------- |
| `<none>` | `bool` | Whether the path has been initialized. |

### nextNonce

Retrieves the next nonce for a given source endpoint and sender address.

*\_srcEid The source endpoint ID.*

*\_sender The sender address.*

*The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.*

*Is required by the off-chain executor to determine the OApp expects msg execution is ordered.*

*This is also enforced by the OApp.*

*By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.*

```solidity
function nextNonce(uint32, bytes32) public view virtual returns (uint64 nonce);
```

**Returns**

| Name    | Type     | Description     |
| ------- | -------- | --------------- |
| `nonce` | `uint64` | The next nonce. |

### lzReceive

*Entry point for receiving messages or packets from the endpoint.*

*Entry point for receiving msg/packet from the LayerZero endpoint.*

```solidity
function lzReceive(
    Origin calldata _origin,
    bytes32 _guid,
    bytes calldata _message,
    address _executor,
    bytes calldata _extraData
)
    public
    payable
    virtual;
```

**Parameters**

| Name         | Type      | Description                                                                                                                                                                                         |
| ------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `_origin`    | `Origin`  | The origin information containing the source endpoint and sender address. - srcEid: The source chain endpoint ID. - sender: The sender address on the src chain. - nonce: The nonce of the message. |
| `_guid`      | `bytes32` | The unique identifier for the received LayerZero message.                                                                                                                                           |
| `_message`   | `bytes`   | The payload of the received message.                                                                                                                                                                |
| `_executor`  | `address` | The address of the executor for the received message.                                                                                                                                               |
| `_extraData` | `bytes`   | Additional arbitrary data provided by the corresponding executor.                                                                                                                                   |

### \_lzReceive

*Internal function to implement lzReceive logic without needing to copy the basic parameter validation.*

```solidity
function _lzReceive(
    Origin calldata _origin,
    bytes32 _guid,
    bytes calldata _message,
    address _executor,
    bytes calldata _extraData
)
    internal
    virtual;
```

## Errors

### OnlyEndpoint

```solidity
error OnlyEndpoint(address addr);
```


# OAppAuthSender

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/CrossChain/OAppAuth/OAppAuthSender.sol)

**Inherits:** OAppAuthCore

*Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.*

*This Auth version of OAppCore uses solmate's Auth instead of OZ's Ownable for compatibility purposes*

## State Variables

### SENDER\_VERSION

```solidity
uint64 internal constant SENDER_VERSION = 1;
```

## Functions

### oAppVersion

Retrieves the OApp version information.

*Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented. ie. this is a SEND only OApp.*

*If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions*

```solidity
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion);
```

**Returns**

| Name              | Type     | Description                                   |
| ----------------- | -------- | --------------------------------------------- |
| `senderVersion`   | `uint64` | The version of the OAppSender.sol contract.   |
| `receiverVersion` | `uint64` | The version of the OAppReceiver.sol contract. |

### \_quote

*Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.*

```solidity
function _quote(
    uint32 _dstEid,
    bytes memory _message,
    bytes memory _options,
    bool _payInLzToken
)
    internal
    view
    virtual
    returns (MessagingFee memory fee);
```

**Parameters**

| Name            | Type     | Description                                          |
| --------------- | -------- | ---------------------------------------------------- |
| `_dstEid`       | `uint32` | The destination endpoint ID.                         |
| `_message`      | `bytes`  | The message payload.                                 |
| `_options`      | `bytes`  | Additional options for the message.                  |
| `_payInLzToken` | `bool`   | Flag indicating whether to pay the fee in LZ tokens. |

**Returns**

| Name  | Type           | Description                                                                                                                               |
| ----- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `fee` | `MessagingFee` | The calculated MessagingFee for the message. - nativeFee: The native fee for the message. - lzTokenFee: The LZ token fee for the message. |

### \_lzSend

*Internal function to interact with the LayerZero EndpointV2.send() for sending a message.*

```solidity
function _lzSend(
    uint32 _dstEid,
    bytes memory _message,
    bytes memory _options,
    MessagingFee memory _fee,
    address _refundAddress
)
    internal
    virtual
    returns (MessagingReceipt memory receipt);
```

**Parameters**

| Name             | Type           | Description                                                                                               |
| ---------------- | -------------- | --------------------------------------------------------------------------------------------------------- |
| `_dstEid`        | `uint32`       | The destination endpoint ID.                                                                              |
| `_message`       | `bytes`        | The message payload.                                                                                      |
| `_options`       | `bytes`        | Additional options for the message.                                                                       |
| `_fee`           | `MessagingFee` | The calculated LayerZero fee for the message. - nativeFee: The native fee. - lzTokenFee: The lzToken fee. |
| `_refundAddress` | `address`      | The address to receive any excess fee values sent to the endpoint.                                        |

**Returns**

| Name      | Type               | Description                                                                                                                                                                      |
| --------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `receipt` | `MessagingReceipt` | The receipt for the sent message. - guid: The unique identifier for the sent message. - nonce: The nonce of the sent message. - fee: The LayerZero fee incurred for the message. |

### \_payNative

*Internal function to pay the native fee associated with the message.*

*If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction, this will need to be overridden because msg.value would contain multiple lzFees.*

*Should be overridden in the event the LayerZero endpoint requires a different native currency.*

*Some EVMs use an ERC20 as a method for paying transactions/gasFees.*

*The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.*

```solidity
function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee);
```

**Parameters**

| Name         | Type      | Description                |
| ------------ | --------- | -------------------------- |
| `_nativeFee` | `uint256` | The native fee to be paid. |

**Returns**

| Name        | Type      | Description                         |
| ----------- | --------- | ----------------------------------- |
| `nativeFee` | `uint256` | The amount of native currency paid. |

### \_payLzToken

*Internal function to pay the LZ token fee associated with the message.*

*If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.*

*Any excess sent, is passed back to the specified \_refundAddress in the \_lzSend().*

```solidity
function _payLzToken(uint256 _lzTokenFee) internal virtual;
```

**Parameters**

| Name          | Type      | Description                  |
| ------------- | --------- | ---------------------------- |
| `_lzTokenFee` | `uint256` | The LZ token fee to be paid. |

## Errors

### NotEnoughNative

```solidity
error NotEnoughNative(uint256 msgValue);
```

### LzTokenUnavailable

```solidity
error LzTokenUnavailable();
```


# AccountantWithRateProviders

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/AccountantWithRateProviders.sol)

**Inherits:** Auth, IRateProvider

## State Variables

### accountantState

Store the accountant state in 3 packed slots.

```solidity
AccountantState public accountantState;
```

### rateProviderData

Maps ERC20s to their RateProviderData.

```solidity
mapping(ERC20 => RateProviderData) public rateProviderData;
```

### base

The base asset rates are provided in.

```solidity
ERC20 public immutable base;
```

### decimals

The decimals rates are provided in.

```solidity
uint8 public immutable decimals;
```

### vault

The BoringVault this accountant is working with. Used to determine share supply for fee calculation.

```solidity
BoringVault public immutable vault;
```

### ONE\_SHARE

One share of the BoringVault.

```solidity
uint256 internal immutable ONE_SHARE;
```

## Functions

### constructor

```solidity
constructor(
    address _owner,
    address _vault,
    address payoutAddress,
    uint96 startingExchangeRate,
    address _base,
    uint16 allowedExchangeRateChangeUpper,
    uint16 allowedExchangeRateChangeLower,
    uint32 minimumUpdateDelayInSeconds,
    uint16 managementFee
)
    Auth(_owner, Authority(address(0)));
```

### pause

Pause this contract, which prevents future calls to `updateExchangeRate`, and any safe rate calls will revert.

*Callable by MULTISIG\_ROLE.*

```solidity
function pause() external requiresAuth;
```

### unpause

Unpause this contract, which allows future calls to `updateExchangeRate`, and any safe rate calls will stop reverting.

*Callable by MULTISIG\_ROLE.*

```solidity
function unpause() external requiresAuth;
```

### updateDelay

Update the minimum time delay between `updateExchangeRate` calls.

*There are no input requirements, as it is possible the admin would want the exchange rate updated as frequently as needed.*

*Callable by OWNER\_ROLE.*

```solidity
function updateDelay(uint32 minimumUpdateDelayInSeconds) external requiresAuth;
```

### updateUpper

Update the allowed upper bound change of exchange rate between `updateExchangeRateCalls`.

*Callable by OWNER\_ROLE.*

```solidity
function updateUpper(uint16 allowedExchangeRateChangeUpper) external requiresAuth;
```

### updateLower

Update the allowed lower bound change of exchange rate between `updateExchangeRateCalls`.

*Callable by OWNER\_ROLE.*

```solidity
function updateLower(uint16 allowedExchangeRateChangeLower) external requiresAuth;
```

### updateManagementFee

Update the management fee to a new value.

*Callable by OWNER\_ROLE.*

```solidity
function updateManagementFee(uint16 managementFee) external requiresAuth;
```

### updatePayoutAddress

Update the payout address fees are sent to.

*Callable by OWNER\_ROLE.*

```solidity
function updatePayoutAddress(address payoutAddress) external requiresAuth;
```

### setRateProviderData

Update the rate provider data for a specific `asset`.

*Rate providers must return rates in terms of `base` or an asset pegged to base and they must use the same decimals as `asset`.*

*Callable by OWNER\_ROLE.*

```solidity
function setRateProviderData(ERC20 asset, bool isPeggedToBase, address rateProvider) external requiresAuth;
```

### updateExchangeRate

Updates this contract exchangeRate.

*If new exchange rate is outside of accepted bounds, or if not enough time has passed, this will pause the contract, and this function will NOT calculate fees owed.*

*Callable by UPDATE\_EXCHANGE\_RATE\_ROLE.*

```solidity
function updateExchangeRate(uint96 newExchangeRate) external requiresAuth;
```

### claimFees

Claim pending fees.

*This function must be called by the BoringVault.*

*This function will lose precision if the exchange rate decimals is greater than the feeAsset's decimals.*

```solidity
function claimFees(ERC20 feeAsset) external;
```

### getRate

Get this BoringVault's current rate in the base.

```solidity
function getRate() public view returns (uint256 rate);
```

### getRateSafe

Get this BoringVault's current rate in the base.

*Revert if paused.*

```solidity
function getRateSafe() external view returns (uint256 rate);
```

### getRateInQuote

Get this BoringVault's current rate in the provided quote.

*`quote` must have its RateProviderData set, else this will revert.*

*This function will lose precision if the exchange rate decimals is greater than the quote's decimals.*

```solidity
function getRateInQuote(ERC20 quote) public view returns (uint256 rateInQuote);
```

### getRateInQuoteSafe

Get this BoringVault's current rate in the provided quote.

*`quote` must have its RateProviderData set, else this will revert.*

*Revert if paused.*

```solidity
function getRateInQuoteSafe(ERC20 quote) external view returns (uint256 rateInQuote);
```

### changeDecimals

Used to change the decimals of precision used for an amount.

```solidity
function changeDecimals(uint256 amount, uint8 fromDecimals, uint8 toDecimals) internal pure returns (uint256);
```

## Events

### Paused

```solidity
event Paused();
```

### Unpaused

```solidity
event Unpaused();
```

### DelayInSecondsUpdated

```solidity
event DelayInSecondsUpdated(uint32 oldDelay, uint32 newDelay);
```

### UpperBoundUpdated

```solidity
event UpperBoundUpdated(uint16 oldBound, uint16 newBound);
```

### LowerBoundUpdated

```solidity
event LowerBoundUpdated(uint16 oldBound, uint16 newBound);
```

### ManagementFeeUpdated

```solidity
event ManagementFeeUpdated(uint16 oldFee, uint16 newFee);
```

### PayoutAddressUpdated

```solidity
event PayoutAddressUpdated(address oldPayout, address newPayout);
```

### RateProviderUpdated

```solidity
event RateProviderUpdated(address asset, bool isPegged, address rateProvider);
```

### ExchangeRateUpdated

```solidity
event ExchangeRateUpdated(uint96 oldRate, uint96 newRate, uint64 currentTime);
```

### FeesClaimed

```solidity
event FeesClaimed(address indexed feeAsset, uint256 amount);
```

## Errors

### AccountantWithRateProviders\_\_UpperBoundTooSmall

```solidity
error AccountantWithRateProviders__UpperBoundTooSmall();
```

### AccountantWithRateProviders\_\_LowerBoundTooLarge

```solidity
error AccountantWithRateProviders__LowerBoundTooLarge();
```

### AccountantWithRateProviders\_\_ManagementFeeTooLarge

```solidity
error AccountantWithRateProviders__ManagementFeeTooLarge();
```

### AccountantWithRateProviders\_\_Paused

```solidity
error AccountantWithRateProviders__Paused();
```

### AccountantWithRateProviders\_\_ZeroFeesOwed

```solidity
error AccountantWithRateProviders__ZeroFeesOwed();
```

### AccountantWithRateProviders\_\_OnlyCallableByBoringVault

```solidity
error AccountantWithRateProviders__OnlyCallableByBoringVault();
```

### AccountantWithRateProviders\_\_UpdateDelayTooLarge

```solidity
error AccountantWithRateProviders__UpdateDelayTooLarge();
```

## Structs

### AccountantState

```solidity
struct AccountantState {
    address payoutAddress;
    uint128 feesOwedInBase;
    uint128 totalSharesLastUpdate;
    uint96 exchangeRate;
    uint16 allowedExchangeRateChangeUpper;
    uint16 allowedExchangeRateChangeLower;
    uint64 lastUpdateTimestamp;
    bool isPaused;
    uint32 minimumUpdateDelayInSeconds;
    uint16 managementFee;
}
```

**Properties**

| Name                             | Type      | Description                                                                                                                           |
| -------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `payoutAddress`                  | `address` | the address `claimFees` sends fees to                                                                                                 |
| `feesOwedInBase`                 | `uint128` | total pending fees owed in terms of base                                                                                              |
| `totalSharesLastUpdate`          | `uint128` | total amount of shares the last exchange rate update                                                                                  |
| `exchangeRate`                   | `uint96`  | the current exchange rate in terms of base                                                                                            |
| `allowedExchangeRateChangeUpper` | `uint16`  | the max allowed change to exchange rate from an update                                                                                |
| `allowedExchangeRateChangeLower` | `uint16`  | the min allowed change to exchange rate from an update                                                                                |
| `lastUpdateTimestamp`            | `uint64`  | the block timestamp of the last exchange rate update                                                                                  |
| `isPaused`                       | `bool`    | whether or not this contract is paused                                                                                                |
| `minimumUpdateDelayInSeconds`    | `uint32`  | the minimum amount of time that must pass between exchange rate updates, such that the update won't trigger the contract to be paused |
| `managementFee`                  | `uint16`  | the management fee                                                                                                                    |

### RateProviderData

```solidity
struct RateProviderData {
    bool isPeggedToBase;
    IRateProvider rateProvider;
}
```

**Properties**

| Name             | Type            | Description                                                   |
| ---------------- | --------------- | ------------------------------------------------------------- |
| `isPeggedToBase` | `bool`          | whether or not the asset is 1:1 with the base asset           |
| `rateProvider`   | `IRateProvider` | the rate provider for this asset if `isPeggedToBase` is false |


# ManagerWithMerkleVerification

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/ManagerWithMerkleVerification.sol)

**Inherits:** Auth

## State Variables

### manageRoot

A merkle tree root that restricts what data can be passed to the BoringVault.

*Maps a strategist address to their specific merkle root.*

\*Each leaf is composed of the keccak256 hash of abi.encodePacked {decodersAndSanitizer, target, valueIsNonZero, selector, argumentAddress\_0, ...., argumentAddress\_N} Where:

* decodersAndSanitizer is the address to call to extract packed address arguments from the calldata
* target is the address to make the call to
* valueIsNonZero is a bool indicating whether or not the value is non-zero
* selector is the function selector on target
* argumentAddress is each allowed address argument in that call\*

```solidity
mapping(address => bytes32) public manageRoot;
```

### performingFlashLoan

Bool indicating whether or not this contract is actively performing a flash loan.

*Used to block flash loans that are initiated outside a manage call.*

```solidity
bool internal performingFlashLoan;
```

### flashLoanIntentHash

keccak256 hash of flash loan data.

```solidity
bytes32 internal flashLoanIntentHash = bytes32(0);
```

### isPaused

Used to pause calls to `manageVaultWithMerkleVerification`.

```solidity
bool public isPaused;
```

### vault

The BoringVault this contract can manage.

```solidity
BoringVault public immutable vault;
```

### balancerVault

The balancer vault this contract can use for flash loans.

```solidity
BalancerVault public immutable balancerVault;
```

## Functions

### constructor

```solidity
constructor(address _owner, address _vault, address _balancerVault) Auth(_owner, Authority(address(0)));
```

### setManageRoot

Sets the manageRoot.

*Callable by OWNER\_ROLE.*

```solidity
function setManageRoot(address strategist, bytes32 _manageRoot) external requiresAuth;
```

### pause

Pause this contract, which prevents future calls to `manageVaultWithMerkleVerification`.

*Callable by MULTISIG\_ROLE.*

```solidity
function pause() external requiresAuth;
```

### unpause

Unpause this contract, which allows future calls to `manageVaultWithMerkleVerification`.

*Callable by MULTISIG\_ROLE.*

```solidity
function unpause() external requiresAuth;
```

### manageVaultWithMerkleVerification

Allows strategist to manage the BoringVault.

*The strategist must provide a merkle proof for every call that verifiees they are allowed to make that call.*

*Callable by MANAGER\_INTERNAL\_ROLE.*

*Callable by STRATEGIST\_ROLE.*

*Callable by MICRO\_MANAGER\_ROLE.*

```solidity
function manageVaultWithMerkleVerification(
    bytes32[][] calldata manageProofs,
    address[] calldata decodersAndSanitizers,
    address[] calldata targets,
    bytes[] calldata targetData,
    uint256[] calldata values
)
    external
    requiresAuth;
```

### flashLoan

In order to perform a flash loan,

1. Merkle root must contain the leaf(address(this), this.flashLoan.selector, ARGUMENT\_ADDRESSES ...)
2. Strategist must initiate the flash loan using `manageVaultWithMerkleVerification`
3. balancerVault MUST callback to this contract with the same userData

```solidity
function flashLoan(
    address recipient,
    address[] calldata tokens,
    uint256[] calldata amounts,
    bytes calldata userData
)
    external;
```

### receiveFlashLoan

Add support for balancer flash loans.

*userData can optionally have salt encoded at the end of it, in order to change the intentHash, if a flash loan is exact userData is being repeated, and their is fear of 3rd parties front-running the rebalance.*

```solidity
function receiveFlashLoan(
    address[] calldata tokens,
    uint256[] calldata amounts,
    uint256[] calldata feeAmounts,
    bytes calldata userData
)
    external;
```

### \_verifyCallData

Helper function to decode, sanitize, and verify call data.

```solidity
function _verifyCallData(
    bytes32 currentManageRoot,
    bytes32[] calldata manageProof,
    address decoderAndSanitizer,
    address target,
    uint256 value,
    bytes calldata targetData
)
    internal
    view;
```

### \_verifyManageProof

Helper function to verify a manageProof is valid.

```solidity
function _verifyManageProof(
    bytes32 root,
    bytes32[] calldata proof,
    address target,
    address decoderAndSanitizer,
    uint256 value,
    bytes4 selector,
    bytes memory packedArgumentAddresses
)
    internal
    pure
    returns (bool);
```

## Events

### ManageRootUpdated

```solidity
event ManageRootUpdated(address indexed strategist, bytes32 oldRoot, bytes32 newRoot);
```

### BoringVaultManaged

```solidity
event BoringVaultManaged(uint256 callsMade);
```

### Paused

```solidity
event Paused();
```

### Unpaused

```solidity
event Unpaused();
```

## Errors

### ManagerWithMerkleVerification\_\_InvalidManageProofLength

```solidity
error ManagerWithMerkleVerification__InvalidManageProofLength();
```

### ManagerWithMerkleVerification\_\_InvalidTargetDataLength

```solidity
error ManagerWithMerkleVerification__InvalidTargetDataLength();
```

### ManagerWithMerkleVerification\_\_InvalidValuesLength

```solidity
error ManagerWithMerkleVerification__InvalidValuesLength();
```

### ManagerWithMerkleVerification\_\_InvalidDecodersAndSanitizersLength

```solidity
error ManagerWithMerkleVerification__InvalidDecodersAndSanitizersLength();
```

### ManagerWithMerkleVerification\_\_FlashLoanNotExecuted

```solidity
error ManagerWithMerkleVerification__FlashLoanNotExecuted();
```

### ManagerWithMerkleVerification\_\_FlashLoanNotInProgress

```solidity
error ManagerWithMerkleVerification__FlashLoanNotInProgress();
```

### ManagerWithMerkleVerification\_\_BadFlashLoanIntentHash

```solidity
error ManagerWithMerkleVerification__BadFlashLoanIntentHash();
```

### ManagerWithMerkleVerification\_\_FailedToVerifyManageProof

```solidity
error ManagerWithMerkleVerification__FailedToVerifyManageProof(address target, bytes targetData, uint256 value);
```

### ManagerWithMerkleVerification\_\_Paused

```solidity
error ManagerWithMerkleVerification__Paused();
```

### ManagerWithMerkleVerification\_\_OnlyCallableByBoringVault

```solidity
error ManagerWithMerkleVerification__OnlyCallableByBoringVault();
```

### ManagerWithMerkleVerification\_\_OnlyCallableByBalancerVault

```solidity
error ManagerWithMerkleVerification__OnlyCallableByBalancerVault();
```

### ManagerWithMerkleVerification\_\_TotalSupplyMustRemainConstantDuringManagement

```solidity
error ManagerWithMerkleVerification__TotalSupplyMustRemainConstantDuringManagement();
```


# TellerWithMultiAssetSupport

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/TellerWithMultiAssetSupport.sol)

**Inherits:** Auth, BeforeTransferHook, ReentrancyGuard

## State Variables

### NATIVE

Native address used to tell the contract to handle native asset deposits.

```solidity
address internal constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
```

### MAX\_SHARE\_LOCK\_PERIOD

The maximum possible share lock period.

```solidity
uint256 internal constant MAX_SHARE_LOCK_PERIOD = 3 days;
```

### isSupported

Mapping ERC20s to an isSupported bool.

```solidity
mapping(ERC20 => bool) public isSupported;
```

### depositNonce

The deposit nonce used to map to a deposit hash.

```solidity
uint96 public depositNonce = 1;
```

### shareLockPeriod

After deposits, shares are locked to the msg.sender's address for `shareLockPeriod`.

*During this time all transfers from msg.sender will revert, and deposits are refundable.*

```solidity
uint64 public shareLockPeriod;
```

### isPaused

Used to pause calls to `deposit` and `depositWithPermit`.

```solidity
bool public isPaused;
```

### publicDepositHistory

*Maps deposit nonce to keccak256(address receiver, address depositAsset, uint256 depositAmount, uint256 shareAmount, uint256 timestamp, uint256 shareLockPeriod).*

```solidity
mapping(uint256 => bytes32) public publicDepositHistory;
```

### shareUnlockTime

Maps user address to the time their shares will be unlocked.

```solidity
mapping(address => uint256) public shareUnlockTime;
```

### vault

The BoringVault this contract is working with.

```solidity
BoringVault public immutable vault;
```

### accountant

The AccountantWithRateProviders this contract is working with.

```solidity
AccountantWithRateProviders public immutable accountant;
```

### ONE\_SHARE

One share of the BoringVault.

```solidity
uint256 internal immutable ONE_SHARE;
```

## Functions

### constructor

```solidity
constructor(address _owner, address _vault, address _accountant) Auth(_owner, Authority(address(0)));
```

### pause

Pause this contract, which prevents future calls to `deposit` and `depositWithPermit`.

*Callable by MULTISIG\_ROLE.*

```solidity
function pause() external requiresAuth;
```

### unpause

Unpause this contract, which allows future calls to `deposit` and `depositWithPermit`.

*Callable by MULTISIG\_ROLE.*

```solidity
function unpause() external requiresAuth;
```

### addAsset

Adds this asset as a deposit asset.

*The accountant must also support pricing this asset, else the `deposit` call will revert.*

*Callable by OWNER\_ROLE.*

```solidity
function addAsset(ERC20 asset) external requiresAuth;
```

### removeAsset

Removes this asset as a deposit asset.

*Callable by OWNER\_ROLE.*

```solidity
function removeAsset(ERC20 asset) external requiresAuth;
```

### setShareLockPeriod

Sets the share lock period.

*This not only locks shares to the user address, but also serves as the pending deposit period, where deposits can be reverted.*

*If a new shorter share lock period is set, users with pending share locks could make a new deposit to receive 1 wei shares, and have their shares unlock sooner than their original deposit allows. This state would allow for the user deposit to be refunded, but only if they have not transferred their shares out of there wallet. This is an accepted limitation, and should be known when decreasing the share lock period.*

*Callable by OWNER\_ROLE.*

```solidity
function setShareLockPeriod(uint64 _shareLockPeriod) external requiresAuth;
```

### beforeTransfer

Implement beforeTransfer hook to check if shares are locked.

```solidity
function beforeTransfer(address from) public view;
```

### refundDeposit

Allows DEPOSIT\_REFUNDER\_ROLE to revert a pending deposit.

*Once a deposit share lock period has passed, it can no longer be reverted.*

*It is possible the admin does not setup the BoringVault to call the transfer hook, but this contract can still be saving share lock state. In the event this happens deposits are still refundable if the user has not transferred their shares. But there is no guarantee that the user has not transferred their shares.*

*Callable by STRATEGIST\_MULTISIG\_ROLE.*

```solidity
function refundDeposit(
    uint256 nonce,
    address receiver,
    address depositAsset,
    uint256 depositAmount,
    uint256 shareAmount,
    uint256 depositTimestamp,
    uint256 shareLockUpPeriodAtTimeOfDeposit
)
    external
    requiresAuth;
```

### deposit

Allows users to deposit into the BoringVault, if this contract is not paused.

*Publicly callable.*

```solidity
function deposit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint
)
    external
    requiresAuth
    nonReentrant
    returns (uint256 shares);
```

### depositWithPermit

Allows users to deposit into BoringVault using permit.

*Publicly callable.*

```solidity
function depositWithPermit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external
    requiresAuth
    nonReentrant
    returns (uint256 shares);
```

### bulkDeposit

Allows on ramp role to deposit into this contract.

*Does NOT support native deposits.*

*Callable by SOLVER\_ROLE.*

```solidity
function bulkDeposit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint,
    address to
)
    external
    requiresAuth
    nonReentrant
    returns (uint256 shares);
```

### bulkWithdraw

Allows off ramp role to withdraw from this contract.

*Callable by SOLVER\_ROLE.*

```solidity
function bulkWithdraw(
    ERC20 withdrawAsset,
    uint256 shareAmount,
    uint256 minimumAssets,
    address to
)
    external
    requiresAuth
    returns (uint256 assetsOut);
```

### \_erc20Deposit

Implements a common ERC20 deposit into BoringVault.

```solidity
function _erc20Deposit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint,
    address to
)
    internal
    returns (uint256 shares);
```

### \_afterPublicDeposit

Handle share lock logic, and event.

```solidity
function _afterPublicDeposit(
    address user,
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 shares,
    uint256 currentShareLockPeriod
)
    internal;
```

## Events

### Paused

```solidity
event Paused();
```

### Unpaused

```solidity
event Unpaused();
```

### AssetAdded

```solidity
event AssetAdded(address indexed asset);
```

### AssetRemoved

```solidity
event AssetRemoved(address indexed asset);
```

### Deposit

```solidity
event Deposit(
    uint256 indexed nonce,
    address indexed receiver,
    address indexed depositAsset,
    uint256 depositAmount,
    uint256 shareAmount,
    uint256 depositTimestamp,
    uint256 shareLockPeriodAtTimeOfDeposit
);
```

### BulkDeposit

```solidity
event BulkDeposit(address indexed asset, uint256 depositAmount);
```

### BulkWithdraw

```solidity
event BulkWithdraw(address indexed asset, uint256 shareAmount);
```

### DepositRefunded

```solidity
event DepositRefunded(uint256 indexed nonce, bytes32 depositHash, address indexed user);
```

## Errors

### TellerWithMultiAssetSupport\_\_ShareLockPeriodTooLong

```solidity
error TellerWithMultiAssetSupport__ShareLockPeriodTooLong();
```

### TellerWithMultiAssetSupport\_\_SharesAreLocked

```solidity
error TellerWithMultiAssetSupport__SharesAreLocked();
```

### TellerWithMultiAssetSupport\_\_SharesAreUnLocked

```solidity
error TellerWithMultiAssetSupport__SharesAreUnLocked();
```

### TellerWithMultiAssetSupport\_\_BadDepositHash

```solidity
error TellerWithMultiAssetSupport__BadDepositHash();
```

### TellerWithMultiAssetSupport\_\_AssetNotSupported

```solidity
error TellerWithMultiAssetSupport__AssetNotSupported();
```

### TellerWithMultiAssetSupport\_\_ZeroAssets

```solidity
error TellerWithMultiAssetSupport__ZeroAssets();
```

### TellerWithMultiAssetSupport\_\_MinimumMintNotMet

```solidity
error TellerWithMultiAssetSupport__MinimumMintNotMet();
```

### TellerWithMultiAssetSupport\_\_MinimumAssetsNotMet

```solidity
error TellerWithMultiAssetSupport__MinimumAssetsNotMet();
```

### TellerWithMultiAssetSupport\_\_PermitFailedAndAllowanceTooLow

```solidity
error TellerWithMultiAssetSupport__PermitFailedAndAllowanceTooLow();
```

### TellerWithMultiAssetSupport\_\_ZeroShares

```solidity
error TellerWithMultiAssetSupport__ZeroShares();
```

### TellerWithMultiAssetSupport\_\_Paused

```solidity
error TellerWithMultiAssetSupport__Paused();
```


# helper


# Contents

* ArcticArchitectureLens
* Constants
* Deployer
* GenericRateProvider


# Constants

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/helper/Constants.sol)

### ETH\_PER\_WEETH\_CHAINLINK

```solidity
IPriceFeed constant ETH_PER_WEETH_CHAINLINK = IPriceFeed(0x5c9C449BbC9a6075A2c061dF312a35fd1E05fF22);
```

### ETH\_PER\_EZETH\_CHAINLINK

```solidity
IPriceFeed constant ETH_PER_EZETH_CHAINLINK = IPriceFeed(0x636A000262F6aA9e1F094ABF0aD8f645C44f641C);
```

### ETH\_PER\_RSETH\_CHAINLINK

```solidity
IPriceFeed constant ETH_PER_RSETH_CHAINLINK = IPriceFeed(0x03c68933f7a3F76875C0bc670a58e69294cDFD01);
```

### ETH\_PER\_RSWETH\_CHAINLINK

```solidity
IPriceFeed constant ETH_PER_RSWETH_CHAINLINK = IPriceFeed(0xb613CfebD0b6e95abDDe02677d6bC42394FdB857);
```

### ETH\_PER\_PUFETH\_REDSTONE

```solidity
IPriceFeed constant ETH_PER_PUFETH_REDSTONE = IPriceFeed(0x76A495b0bFfb53ef3F0E94ef0763e03cE410835C);
```


# ArcticArchitectureLens

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/helper/ArcticArchitectureLens.sol)

## Functions

### totalAssets

*Calculates the total assets held in the BoringVault for a given vault and accountant.*

```solidity
function totalAssets(
    BoringVault boringVault,
    AccountantWithRateProviders accountant
)
    external
    view
    returns (ERC20 asset, uint256 assets);
```

**Parameters**

| Name          | Type                          | Description                               |
| ------------- | ----------------------------- | ----------------------------------------- |
| `boringVault` | `BoringVault`                 | The BoringVault contract.                 |
| `accountant`  | `AccountantWithRateProviders` | The AccountantWithRateProviders contract. |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `asset`  | `ERC20`   | The ERC20 asset, `assets` is given in terms of. |
| `assets` | `uint256` | The total assets held in the vault.             |

### previewDeposit

*Calculates the number of shares that will be received for a given deposit amount in the BoringVault.*

```solidity
function previewDeposit(
    ERC20 depositAsset,
    uint256 depositAmount,
    BoringVault boringVault,
    AccountantWithRateProviders accountant
)
    external
    view
    returns (uint256 shares);
```

**Parameters**

| Name            | Type                          | Description                               |
| --------------- | ----------------------------- | ----------------------------------------- |
| `depositAsset`  | `ERC20`                       | The ERC20 asset being deposited.          |
| `depositAmount` | `uint256`                     | The amount of the asset being deposited.  |
| `boringVault`   | `BoringVault`                 | The BoringVault contract.                 |
| `accountant`    | `AccountantWithRateProviders` | The AccountantWithRateProviders contract. |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `shares` | `uint256` | The number of shares that will be received. |

### balanceOf

*Retrieves the balance of shares for a given account in the BoringVault.*

```solidity
function balanceOf(address account, BoringVault boringVault) external view returns (uint256 shares);
```

**Parameters**

| Name          | Type          | Description                 |
| ------------- | ------------- | --------------------------- |
| `account`     | `address`     | The address of the account. |
| `boringVault` | `BoringVault` | The BoringVault contract.   |

**Returns**

| Name     | Type      | Description                            |
| -------- | --------- | -------------------------------------- |
| `shares` | `uint256` | The balance of shares for the account. |

### balanceOfInAssets

*Calculates the balance of a user in terms of asset for a given account in the BoringVault.*

```solidity
function balanceOfInAssets(
    address account,
    BoringVault boringVault,
    AccountantWithRateProviders accountant
)
    external
    view
    returns (uint256 assets);
```

**Parameters**

| Name          | Type                          | Description                               |
| ------------- | ----------------------------- | ----------------------------------------- |
| `account`     | `address`                     | The address of the account.               |
| `boringVault` | `BoringVault`                 | The BoringVault contract.                 |
| `accountant`  | `AccountantWithRateProviders` | The AccountantWithRateProviders contract. |

**Returns**

| Name     | Type      | Description                            |
| -------- | --------- | -------------------------------------- |
| `assets` | `uint256` | The balance of assets for the account. |

### exchangeRate

*Retrieves the current exchange rate from the AccountantWithRateProviders contract.*

```solidity
function exchangeRate(AccountantWithRateProviders accountant) external view returns (uint256 rate);
```

**Parameters**

| Name         | Type                          | Description                               |
| ------------ | ----------------------------- | ----------------------------------------- |
| `accountant` | `AccountantWithRateProviders` | The AccountantWithRateProviders contract. |

**Returns**

| Name   | Type      | Description                |
| ------ | --------- | -------------------------- |
| `rate` | `uint256` | The current exchange rate. |

### checkUserDeposit

*Checks if a user's deposit meets certain conditions.*

```solidity
function checkUserDeposit(
    address account,
    ERC20 depositAsset,
    uint256 depositAmount,
    BoringVault boringVault,
    TellerWithMultiAssetSupport teller
)
    external
    view
    returns (bool);
```

**Parameters**

| Name            | Type                          | Description                               |
| --------------- | ----------------------------- | ----------------------------------------- |
| `account`       | `address`                     | The address of the user.                  |
| `depositAsset`  | `ERC20`                       | The ERC20 asset being deposited.          |
| `depositAmount` | `uint256`                     | The amount of the asset being deposited.  |
| `boringVault`   | `BoringVault`                 | The BoringVault contract.                 |
| `teller`        | `TellerWithMultiAssetSupport` | The TellerWithMultiAssetSupport contract. |

**Returns**

| Name     | Type   | Description                                                      |
| -------- | ------ | ---------------------------------------------------------------- |
| `<none>` | `bool` | A boolean indicating if the user's deposit meets the conditions. |

### checkUserDepositWithPermit

*Checks if a user's deposit (with permit) meets certain conditions.*

```solidity
function checkUserDepositWithPermit(
    address account,
    ERC20 depositAsset,
    uint256 depositAmount,
    TellerWithMultiAssetSupport teller
)
    external
    view
    returns (bool);
```

**Parameters**

| Name            | Type                          | Description                               |
| --------------- | ----------------------------- | ----------------------------------------- |
| `account`       | `address`                     | The address of the user.                  |
| `depositAsset`  | `ERC20`                       | The ERC20 asset being deposited.          |
| `depositAmount` | `uint256`                     | The amount of the asset being deposited.  |
| `teller`        | `TellerWithMultiAssetSupport` | The TellerWithMultiAssetSupport contract. |

**Returns**

| Name     | Type   | Description                                                      |
| -------- | ------ | ---------------------------------------------------------------- |
| `<none>` | `bool` | A boolean indicating if the user's deposit meets the conditions. |

### userUnlockTime

*Retrieves the unlock time for a user's shares in the TellerWithMultiAssetSupport contract.*

```solidity
function userUnlockTime(address account, TellerWithMultiAssetSupport teller) external view returns (uint256 time);
```

**Parameters**

| Name      | Type                          | Description                               |
| --------- | ----------------------------- | ----------------------------------------- |
| `account` | `address`                     | The address of the user.                  |
| `teller`  | `TellerWithMultiAssetSupport` | The TellerWithMultiAssetSupport contract. |

**Returns**

| Name   | Type      | Description                            |
| ------ | --------- | -------------------------------------- |
| `time` | `uint256` | The unlock time for the user's shares. |

### isTellerPaused

Checks if the TellerWithMultiAssetDepositSupport contract is paused.

```solidity
function isTellerPaused(TellerWithMultiAssetSupport teller) external view returns (bool);
```


# Deployer

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/helper/Deployer.sol)

**Inherits:** Auth

## State Variables

### isDeployer

```solidity
mapping(address => bool) public isDeployer;
```

## Functions

### constructor

```solidity
constructor(address _owner, Authority _auth) Auth(_owner, _auth);
```

### deployContract

Deploy some contract to a deterministic address.

*Should be of form: "ContractName Version 0.0" Where the numbers after version are VERSION . SUBVERSION*

```solidity
function deployContract(
    string calldata name,
    bytes memory creationCode,
    bytes calldata constructorArgs,
    uint256 value
)
    external
    requiresAuth
    returns (address);
```

**Parameters**

| Name              | Type      | Description                                                                                       |
| ----------------- | --------- | ------------------------------------------------------------------------------------------------- |
| `name`            | `string`  | string used to derive salt for deployment                                                         |
| `creationCode`    | `bytes`   | the contract creation code to deploy - can be obtained by calling type(contractName).creationCode |
| `constructorArgs` | `bytes`   | the contract constructor arguments if any - must be of form abi.encode(arg1, arg2, ...)           |
| `value`           | `uint256` | non zero if constructor needs to be payable                                                       |

### getAddress

```solidity
function getAddress(string calldata name) external view returns (address);
```

### convertNameToBytes32

```solidity
function convertNameToBytes32(string calldata name) public pure returns (bytes32);
```

## Events

### ContractDeployed

Emitted on `deployContract` calls.

```solidity
event ContractDeployed(string name, address contractAddress, bytes32 creationCodeHash);
```

**Parameters**

| Name               | Type      | Description                                                                                                |
| ------------------ | --------- | ---------------------------------------------------------------------------------------------------------- |
| `name`             | `string`  | string name used to derive salt for deployment                                                             |
| `contractAddress`  | `address` | the newly deployed contract address                                                                        |
| `creationCodeHash` | `bytes32` | keccak256 hash of the creation code - useful to determine creation code is the same across multiple chains |

## Errors

### Deployer\_\_NotADeployer

```solidity
error Deployer__NotADeployer();
```


# GenericRateProvider

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/helper/GenericRateProvider.sol)

**Inherits:** IRateProvider

## State Variables

### target

The address to make rate calls to.

```solidity
address public immutable target;
```

### selector

The selector to call on the target.

```solidity
bytes4 public immutable selector;
```

### staticArgument0

Static arguments to pass to the target.

```solidity
bytes32 public immutable staticArgument0;
```

### staticArgument1

```solidity
bytes32 public immutable staticArgument1;
```

### staticArgument2

```solidity
bytes32 public immutable staticArgument2;
```

### staticArgument3

```solidity
bytes32 public immutable staticArgument3;
```

### staticArgument4

```solidity
bytes32 public immutable staticArgument4;
```

### staticArgument5

```solidity
bytes32 public immutable staticArgument5;
```

### staticArgument6

```solidity
bytes32 public immutable staticArgument6;
```

### staticArgument7

```solidity
bytes32 public immutable staticArgument7;
```

## Functions

### constructor

```solidity
constructor(
    address _target,
    bytes4 _selctor,
    bytes32 _staticArgument0,
    bytes32 _staticArgument1,
    bytes32 _staticArgument2,
    bytes32 _staticArgument3,
    bytes32 _staticArgument4,
    bytes32 _staticArgument5,
    bytes32 _staticArgument6,
    bytes32 _staticArgument7
);
```

### getRate

Get the rate of some generic asset.

*This function only supports selectors that only contain static arguments, dynamic arguments will not be encoded correctly, and calls will likely fail.*

*If staticArgumentN is not used, it can be left as 0.*

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


# interfaces


# BalancerVault

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/BalancerVault.sol)

## Functions

### flashLoan

```solidity
function flashLoan(address, address[] memory tokens, uint256[] memory amounts, bytes calldata userData) external;
```

### swap

```solidity
function swap(
    DecoderCustomTypes.SingleSwap memory singleSwap,
    DecoderCustomTypes.FundManagement memory funds,
    uint256 limit,
    uint256 deadline
)
    external
    returns (uint256 amountCalculated);
```


# AggregationRouterV5

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/AggregationRouterV5.sol)

## Functions

### swap

```solidity
function swap(
    address executor,
    SwapDescription calldata desc,
    bytes calldata permit,
    bytes calldata data
)
    external
    payable
    returns (uint256 returnAmount, uint256 spentAmount);
```

## Structs

### SwapDescription

```solidity
struct SwapDescription {
    ERC20 srcToken;
    ERC20 dstToken;
    address payable srcReceiver;
    address payable dstReceiver;
    uint256 amount;
    uint256 minReturnAmount;
    uint256 flags;
}
```


# BeforeTransferHook

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/BeforeTransferHook.sol)

## Functions

### beforeTransfer

```solidity
function beforeTransfer(address from) external view;
```


# DecoderCustomTypes

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/DecoderCustomTypes.sol)

## Structs

### JoinPoolRequest

```solidity
struct JoinPoolRequest {
    address[] assets;
    uint256[] maxAmountsIn;
    bytes userData;
    bool fromInternalBalance;
}
```

### ExitPoolRequest

```solidity
struct ExitPoolRequest {
    address[] assets;
    uint256[] minAmountsOut;
    bytes userData;
    bool toInternalBalance;
}
```

### SingleSwap

```solidity
struct SingleSwap {
    bytes32 poolId;
    SwapKind kind;
    address assetIn;
    address assetOut;
    uint256 amount;
    bytes userData;
}
```

### FundManagement

```solidity
struct FundManagement {
    address sender;
    bool fromInternalBalance;
    address recipient;
    bool toInternalBalance;
}
```

### MintParams

```solidity
struct MintParams {
    address token0;
    address token1;
    uint24 fee;
    int24 tickLower;
    int24 tickUpper;
    uint256 amount0Desired;
    uint256 amount1Desired;
    uint256 amount0Min;
    uint256 amount1Min;
    address recipient;
    uint256 deadline;
}
```

### IncreaseLiquidityParams

```solidity
struct IncreaseLiquidityParams {
    uint256 tokenId;
    uint256 amount0Desired;
    uint256 amount1Desired;
    uint256 amount0Min;
    uint256 amount1Min;
    uint256 deadline;
}
```

### DecreaseLiquidityParams

```solidity
struct DecreaseLiquidityParams {
    uint256 tokenId;
    uint128 liquidity;
    uint256 amount0Min;
    uint256 amount1Min;
    uint256 deadline;
}
```

### CollectParams

```solidity
struct CollectParams {
    uint256 tokenId;
    address recipient;
    uint128 amount0Max;
    uint128 amount1Max;
}
```

### ExactInputParams

```solidity
struct ExactInputParams {
    bytes path;
    address recipient;
    uint256 deadline;
    uint256 amountIn;
    uint256 amountOutMinimum;
}
```

### MarketParams

```solidity
struct MarketParams {
    address loanToken;
    address collateralToken;
    address oracle;
    address irm;
    uint256 lltv;
}
```

### SwapDescription

```solidity
struct SwapDescription {
    address srcToken;
    address dstToken;
    address payable srcReceiver;
    address payable dstReceiver;
    uint256 amount;
    uint256 minReturnAmount;
    uint256 flags;
}
```

### TokenInput

```solidity
struct TokenInput {
    address tokenIn;
    uint256 netTokenIn;
    address tokenMintSy;
    address pendleSwap;
    SwapData swapData;
}
```

### TokenOutput

```solidity
struct TokenOutput {
    address tokenOut;
    uint256 minTokenOut;
    address tokenRedeemSy;
    address pendleSwap;
    SwapData swapData;
}
```

### ApproxParams

```solidity
struct ApproxParams {
    uint256 guessMin;
    uint256 guessMax;
    uint256 guessOffchain;
    uint256 maxIteration;
    uint256 eps;
}
```

### SwapData

```solidity
struct SwapData {
    SwapType swapType;
    address extRouter;
    bytes extCalldata;
    bool needScale;
}
```

### QueuedWithdrawalParams

```solidity
struct QueuedWithdrawalParams {
    address[] strategies;
    uint256[] shares;
    address withdrawer;
}
```

### Withdrawal

```solidity
struct Withdrawal {
    address staker;
    address delegatedTo;
    address withdrawer;
    uint256 nonce;
    uint32 startBlock;
    address[] strategies;
    uint256[] shares;
}
```

## Enums

### SwapKind

```solidity
enum SwapKind {
    GIVEN_IN,
    GIVEN_OUT
}
```

### SwapType

```solidity
enum SwapType {
    NONE,
    KYBERSWAP,
    ONE_INCH,
    ETH_WETH
}
```


# ICreateX

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/ICreateX.sol)

**Author:** pcaversaccio (<https://web.archive.org/web/20230921103111/https://pcaversaccio.com/>)

## Functions

### deployCreate

```solidity
function deployCreate(bytes memory initCode) external payable returns (address newContract);
```

### deployCreateAndInit

```solidity
function deployCreateAndInit(
    bytes memory initCode,
    bytes memory data,
    Values memory values,
    address refundAddress
)
    external
    payable
    returns (address newContract);
```

### deployCreateAndInit

```solidity
function deployCreateAndInit(
    bytes memory initCode,
    bytes memory data,
    Values memory values
)
    external
    payable
    returns (address newContract);
```

### deployCreateClone

```solidity
function deployCreateClone(address implementation, bytes memory data) external payable returns (address proxy);
```

### computeCreateAddress

```solidity
function computeCreateAddress(address deployer, uint256 nonce) external view returns (address computedAddress);
```

### computeCreateAddress

```solidity
function computeCreateAddress(uint256 nonce) external view returns (address computedAddress);
```

### deployCreate2

```solidity
function deployCreate2(bytes32 salt, bytes memory initCode) external payable returns (address newContract);
```

### deployCreate2

```solidity
function deployCreate2(bytes memory initCode) external payable returns (address newContract);
```

### deployCreate2AndInit

```solidity
function deployCreate2AndInit(
    bytes32 salt,
    bytes memory initCode,
    bytes memory data,
    Values memory values,
    address refundAddress
)
    external
    payable
    returns (address newContract);
```

### deployCreate2AndInit

```solidity
function deployCreate2AndInit(
    bytes32 salt,
    bytes memory initCode,
    bytes memory data,
    Values memory values
)
    external
    payable
    returns (address newContract);
```

### deployCreate2AndInit

```solidity
function deployCreate2AndInit(
    bytes memory initCode,
    bytes memory data,
    Values memory values,
    address refundAddress
)
    external
    payable
    returns (address newContract);
```

### deployCreate2AndInit

```solidity
function deployCreate2AndInit(
    bytes memory initCode,
    bytes memory data,
    Values memory values
)
    external
    payable
    returns (address newContract);
```

### deployCreate2Clone

```solidity
function deployCreate2Clone(
    bytes32 salt,
    address implementation,
    bytes memory data
)
    external
    payable
    returns (address proxy);
```

### deployCreate2Clone

```solidity
function deployCreate2Clone(address implementation, bytes memory data) external payable returns (address proxy);
```

### computeCreate2Address

```solidity
function computeCreate2Address(
    bytes32 salt,
    bytes32 initCodeHash,
    address deployer
)
    external
    pure
    returns (address computedAddress);
```

### computeCreate2Address

```solidity
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external view returns (address computedAddress);
```

### deployCreate3

```solidity
function deployCreate3(bytes32 salt, bytes memory initCode) external payable returns (address newContract);
```

### deployCreate3

```solidity
function deployCreate3(bytes memory initCode) external payable returns (address newContract);
```

### deployCreate3AndInit

```solidity
function deployCreate3AndInit(
    bytes32 salt,
    bytes memory initCode,
    bytes memory data,
    Values memory values,
    address refundAddress
)
    external
    payable
    returns (address newContract);
```

### deployCreate3AndInit

```solidity
function deployCreate3AndInit(
    bytes32 salt,
    bytes memory initCode,
    bytes memory data,
    Values memory values
)
    external
    payable
    returns (address newContract);
```

### deployCreate3AndInit

```solidity
function deployCreate3AndInit(
    bytes memory initCode,
    bytes memory data,
    Values memory values,
    address refundAddress
)
    external
    payable
    returns (address newContract);
```

### deployCreate3AndInit

```solidity
function deployCreate3AndInit(
    bytes memory initCode,
    bytes memory data,
    Values memory values
)
    external
    payable
    returns (address newContract);
```

### computeCreate3Address

```solidity
function computeCreate3Address(bytes32 salt, address deployer) external pure returns (address computedAddress);
```

### computeCreate3Address

```solidity
function computeCreate3Address(bytes32 salt) external view returns (address computedAddress);
```

## Events

### ContractCreation

```solidity
event ContractCreation(address indexed newContract, bytes32 indexed salt);
```

### ContractCreation

```solidity
event ContractCreation(address indexed newContract);
```

### Create3ProxyContractCreation

```solidity
event Create3ProxyContractCreation(address indexed newContract, bytes32 indexed salt);
```

## Errors

### FailedContractCreation

```solidity
error FailedContractCreation(address emitter);
```

### FailedContractInitialisation

```solidity
error FailedContractInitialisation(address emitter, bytes revertData);
```

### InvalidSalt

```solidity
error InvalidSalt(address emitter);
```

### InvalidNonceValue

```solidity
error InvalidNonceValue(address emitter);
```

### FailedEtherTransfer

```solidity
error FailedEtherTransfer(address emitter, bytes revertData);
```

## Structs

### Values

```solidity
struct Values {
    uint256 constructorAmount;
    uint256 initCallAmount;
}
```


# IPriceFeed

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IPriceFeed.sol)

## Functions

### decimals

The precision of the value being returned from the price feed.

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

### latestRoundData

Return oracle data for Chainlink or Redstone price feeds.

```solidity
function latestRoundData()
    external
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
```

### description

```solidity
function description() external view returns (string memory);
```

### getDataFeedId

```solidity
function getDataFeedId() external view returns (bytes32);
```


# PriceRouter

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/PriceRouter.sol)

## Functions

### getValue

```solidity
function getValue(ERC20 baseAsset, uint256 amount, ERC20 quoteAsset) external view returns (uint256 value);
```


# IRateProvider

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IRateProvider.sol)

## Functions

### getRate

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


# INonFungiblePositionManager

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/RawDataDecoderAndSanitizerInterfaces.sol)

## Functions

### ownerOf

```solidity
function ownerOf(uint256 tokenId) external view returns (address);
```

### positions

```solidity
function positions(uint256 tokenId)
    external
    view
    returns (
        uint96 nonce,
        address operator,
        address token0,
        address token1,
        uint24 fee,
        int24 tickLower,
        int24 tickUpper,
        uint128 liquidity,
        uint256 feeGrowthInside0LastX128,
        uint256 feeGrowthInside1LastX128,
        uint128 tokensOwed0,
        uint128 tokensOwed1
    );
```

## Structs

### Position

```solidity
struct Position {
    uint96 nonce;
    address operator;
    uint80 poolId;
    int24 tickLower;
    int24 tickUpper;
    uint128 liquidity;
    uint256 feeGrowthInside0LastX128;
    uint256 feeGrowthInside1LastX128;
    uint128 tokensOwed0;
    uint128 tokensOwed1;
}
```


# Contents

* AggregationRouterV5
* BalancerVault
* BeforeTransferHook
* DecoderCustomTypes
* EtherFiLiquid1
* ICreateX
* IPriceFeed
* IRateProvider
* ISWETH
* ILiquidityPool
* IWithdrawRequestNft
* IWEETH
* ILRTDepositPool
* ISTETH
* IWSTETH
* IUNSTETH
* IRestakeManager
* IStakePoolManager
* IStaderConfig
* IUserWithdrawManager
* IUniswapV3SwapCallback
* IUniswapV3Router
* PriceRouter
* INonFungiblePositionManager


# IStaking


# ILiquidityPool

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### deposit

```solidity
function deposit() external payable returns (uint256);
```

### requestWithdraw

```solidity
function requestWithdraw(address recipient, uint256 amount) external returns (uint256);
```

### amountForShare

```solidity
function amountForShare(uint256 shares) external view returns (uint256);
```

### etherFiAdminContract

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

### addEthAmountLockedForWithdrawal

```solidity
function addEthAmountLockedForWithdrawal(uint128 _amount) external;
```


# ILRTDepositPool

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### depositAsset

```solidity
function depositAsset(
    address asset,
    uint256 depositAmount,
    uint256 minRSETHAmountToReceive,
    string calldata referralId
)
    external;
```


# IRestakeManager

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### depositETH

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


# IStaderConfig

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### getDecimals

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


# IStakePoolManager

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### deposit

```solidity
function deposit(address _receiver) external payable returns (uint256);
```

### getExchangeRate

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


# ISTETH

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### submit

```solidity
function submit(address referral) external payable returns (uint256);
```


# ISWETH

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### deposit

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


# IUNSTETH

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### getWithdrawalStatus

```solidity
function getWithdrawalStatus(uint256[] calldata _requestIds)
    external
    view
    returns (WithdrawalRequestStatus[] memory statuses);
```

### requestWithdrawals

```solidity
function requestWithdrawals(
    uint256[] calldata _amounts,
    address _owner
)
    external
    returns (uint256[] memory requestIds);
```

### claimWithdrawal

```solidity
function claimWithdrawal(uint256 _requestId) external;
```

### claimWithdrawals

```solidity
function claimWithdrawals(uint256[] calldata _requestIds, uint256[] calldata _hints) external;
```

### finalize

```solidity
function finalize(uint256 _lastRequestIdToBeFinalized, uint256 _maxShareRate) external payable;
```

### getRoleMember

```solidity
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
```

### FINALIZE\_ROLE

```solidity
function FINALIZE_ROLE() external view returns (bytes32);
```

### getLastFinalizedRequestId

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

### getLastCheckpointIndex

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

### findCheckpointHints

```solidity
function findCheckpointHints(
    uint256[] memory requestIds,
    uint256 firstIndex,
    uint256 lastIndex
)
    external
    view
    returns (uint256[] memory);
```

### getClaimableEther

```solidity
function getClaimableEther(
    uint256[] memory requestIds,
    uint256[] memory hints
)
    external
    view
    returns (uint256[] memory);
```

## Structs

### WithdrawalRequestStatus

```solidity
struct WithdrawalRequestStatus {
    uint256 amountOfStETH;
    uint256 amountOfShares;
    address owner;
    uint256 timestamp;
    bool isFinalized;
    bool isClaimed;
}
```


# IUserWithdrawManager

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### requestWithdraw

```solidity
function requestWithdraw(uint256 _ethXAmount, address _owner) external returns (uint256);
```

### claim

```solidity
function claim(uint256 _requestId) external;
```

### userWithdrawRequests

```solidity
function userWithdrawRequests(uint256) external view returns (WithdrawRequest memory);
```

### finalizeUserWithdrawalRequest

```solidity
function finalizeUserWithdrawalRequest() external;
```

## Structs

### WithdrawRequest

```solidity
struct WithdrawRequest {
    address owner;
    uint256 ethXAmount;
    uint256 ethExpected;
    uint256 ethFinalized;
    uint256 requestTime;
}
```


# IWEETH

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### wrap

```solidity
function wrap(uint256 amount) external returns (uint256);
```

### unwrap

```solidity
function unwrap(uint256 amount) external returns (uint256);
```

### getRate

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


# IWithdrawRequestNft

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### claimWithdraw

```solidity
function claimWithdraw(uint256 tokenId) external;
```

### getRequest

```solidity
function getRequest(uint256 requestId) external view returns (WithdrawRequest memory);
```

### finalizeRequests

```solidity
function finalizeRequests(uint256 requestId) external;
```

### owner

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

### updateAdmin

```solidity
function updateAdmin(address admin, bool isAdmin) external;
```

## Structs

### WithdrawRequest

```solidity
struct WithdrawRequest {
    uint96 amountOfEEth;
    uint96 shareOfEEth;
    bool isValid;
    uint32 feeGwei;
}
```


# IWSTETH

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IStaking.sol)

## Functions

### wrap

```solidity
function wrap(uint256 amount) external returns (uint256);
```

### unwrap

```solidity
function unwrap(uint256 amount) external returns (uint256);
```


# IUniswap v3 Router


# IUniswapV3Router

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IUniswapV3Router.sol)

**Inherits:** IUniswapV3SwapCallback

Functions for swapping tokens via Uniswap V3

## Functions

### exactInputSingle

Swaps `amountIn` of one token for as much as possible of another token

```solidity
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
```

**Parameters**

| Name     | Type                     | Description                                                                            |
| -------- | ------------------------ | -------------------------------------------------------------------------------------- |
| `params` | `ExactInputSingleParams` | The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata |

**Returns**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `amountOut` | `uint256` | The amount of the received token |

### exactInput

Swaps `amountIn` of one token for as much as possible of another along the specified path

```solidity
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
```

**Parameters**

| Name     | Type               | Description                                                                                |
| -------- | ------------------ | ------------------------------------------------------------------------------------------ |
| `params` | `ExactInputParams` | The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata |

**Returns**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `amountOut` | `uint256` | The amount of the received token |

### exactOutputSingle

Swaps as little as possible of one token for `amountOut` of another token

```solidity
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
```

**Parameters**

| Name     | Type                      | Description                                                                             |
| -------- | ------------------------- | --------------------------------------------------------------------------------------- |
| `params` | `ExactOutputSingleParams` | The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata |

**Returns**

| Name       | Type      | Description                   |
| ---------- | --------- | ----------------------------- |
| `amountIn` | `uint256` | The amount of the input token |

### exactOutput

Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)

```solidity
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
```

**Parameters**

| Name     | Type                | Description                                                                                 |
| -------- | ------------------- | ------------------------------------------------------------------------------------------- |
| `params` | `ExactOutputParams` | The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata |

**Returns**

| Name       | Type      | Description                   |
| ---------- | --------- | ----------------------------- |
| `amountIn` | `uint256` | The amount of the input token |

## Structs

### ExactInputSingleParams

```solidity
struct ExactInputSingleParams {
    address tokenIn;
    address tokenOut;
    uint24 fee;
    address recipient;
    uint256 deadline;
    uint256 amountIn;
    uint256 amountOutMinimum;
    uint160 sqrtPriceLimitX96;
}
```

### ExactInputParams

```solidity
struct ExactInputParams {
    bytes path;
    address recipient;
    uint256 deadline;
    uint256 amountIn;
    uint256 amountOutMinimum;
}
```

### ExactOutputSingleParams

```solidity
struct ExactOutputSingleParams {
    address tokenIn;
    address tokenOut;
    uint24 fee;
    address recipient;
    uint256 deadline;
    uint256 amountOut;
    uint256 amountInMaximum;
    uint160 sqrtPriceLimitX96;
}
```

### ExactOutputParams

```solidity
struct ExactOutputParams {
    bytes path;
    address recipient;
    uint256 deadline;
    uint256 amountOut;
    uint256 amountInMaximum;
}
```


# IUniswapV3SwapCallback

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/interfaces/IUniswapV3Router.sol)

Any contract that calls IUniswapV3PoolActions#swap must implement this interface

## Functions

### uniswapV3SwapCallback

Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.

*In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.*

```solidity
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
```

**Parameters**

| Name           | Type     | Description                                                                                                                                                                             |
| -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount0Delta` | `int256` | The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool. |
| `amount1Delta` | `int256` | The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool. |
| `data`         | `bytes`  | Any data passed through by the caller via the IUniswapV3PoolActions#swap call                                                                                                           |


# micro-managers


# Contents

* DexAggregatorUManager
* DexSwapperUManager
* UManager


# DexSwapperUManager

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/micro-managers/DexSwapperUManager.sol)

**Inherits:** UManager

Required Merkle Root Leaves

* ERC20 approves with `router` spender.
* IUniswapV3Router.exactInput(params), with all desired paths.

## State Variables

### MAX\_SLIPPAGE

```solidity
uint256 internal constant MAX_SLIPPAGE = 0.1e4;
```

### allowedSlippage

Slippage check enforced after swaps.

```solidity
uint16 public allowedSlippage = 0.0005e4;
```

### router

The UniswapV3 Router.

```solidity
IUniswapV3Router internal immutable router;
```

### balancerVault

The BalancerVault this uManager works with.

```solidity
BalancerVault internal immutable balancerVault;
```

### priceRouter

The PriceRouter contract used to check slippage.

```solidity
PriceRouter internal immutable priceRouter;
```

## Functions

### constructor

```solidity
constructor(
    address _owner,
    address _manager,
    address _boringVault,
    address _router,
    address _balancerVault,
    address _priceRouter
)
    UManager(_owner, _manager, _boringVault);
```

### setAllowedSlippage

Sets the maximum allowed slippage during a swap.

*Callable by MULTISIG\_ROLE.*

```solidity
function setAllowedSlippage(uint16 _allowedSlippage) external requiresAuth;
```

### swapWithUniswapV3

Performs a swap using the UniswapV3 Router, and enforces a slippage check.

*Callable by STRATEGIST\_ROLE.*

```solidity
function swapWithUniswapV3(
    bytes32[][] calldata manageProofs,
    address[] calldata decodersAndSanitizers,
    ERC20[] memory path,
    uint24[] memory fees,
    uint256 amountIn,
    uint256 amountOutMinimum,
    uint256 deadline
)
    external
    requiresAuth
    enforceRateLimit;
```

**Parameters**

| Name                    | Type          | Description                                                                                                            |
| ----------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `manageProofs`          | `bytes32[][]` | 2 manage proofs, the first one for the ERC20 approval, and the second for the router exactInput call                   |
| `decodersAndSanitizers` | `address[]`   | 2 DecodersAndSanitizers one that implements ERC20 approve, and one that implements IUniswapV3Router.exactInput(params) |
| `path`                  | `ERC20[]`     | the ERC20 token swap path                                                                                              |
| `fees`                  | `uint24[]`    | the fees to specify which pools to swap with                                                                           |
| `amountIn`              | `uint256`     | the amount of path\[0] to swap                                                                                         |
| `amountOutMinimum`      | `uint256`     | the minimum amount of path\[path.length - 1] to get out from the swap                                                  |
| `deadline`              | `uint256`     | the swap deadline                                                                                                      |

### swapWithBalancerV2

Performs a swap using the BalancerV2 Vault, and enforces a slippage check.

*Callable by STRATEGIST\_ROLE.*

```solidity
function swapWithBalancerV2(
    bytes32[][] calldata manageProofs,
    address[] calldata decodersAndSanitizers,
    DecoderCustomTypes.SingleSwap calldata singleSwap,
    DecoderCustomTypes.FundManagement calldata funds,
    uint256 limit,
    uint256 deadline
)
    external
    requiresAuth
    enforceRateLimit;
```

**Parameters**

| Name                    | Type                                | Description                                                                                             |
| ----------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `manageProofs`          | `bytes32[][]`                       | 2 manage proofs, the first one for the ERC20 approval, and the second for the swap                      |
| `decodersAndSanitizers` | `address[]`                         | 2 DecodersAndSanitizers one that implements ERC20 approve, and one that implements BalancerV2Vault.swap |
| `singleSwap`            | `DecoderCustomTypes.SingleSwap`     | the swap data                                                                                           |
| `funds`                 | `DecoderCustomTypes.FundManagement` | the fund management data                                                                                |
| `limit`                 | `uint256`                           | the maximum amount of assetIn to swap, or the minimum amount of assets out to receive                   |
| `deadline`              | `uint256`                           | the swap deadline                                                                                       |

### swapWithCurve

Performs a swap using a Curve pool, and enforces a slippage check.

*Callable by STRATEGIST\_ROLE.*

```solidity
function swapWithCurve(
    bytes32[][] memory manageProofs,
    address[] memory decodersAndSanitizers,
    CurveInfo memory info,
    uint256 i,
    uint256 j,
    uint256 dx,
    uint256 min_dy
)
    external
    requiresAuth
    enforceRateLimit;
```

**Parameters**

| Name                    | Type          | Description                                                                                           |
| ----------------------- | ------------- | ----------------------------------------------------------------------------------------------------- |
| `manageProofs`          | `bytes32[][]` | 2 manage proofs, the first one for the ERC20 approval, and the second for the swap                    |
| `decodersAndSanitizers` | `address[]`   | 2 DecodersAndSanitizers one that implements ERC20 approve, and one that implements CurvePool.exchange |
| `info`                  | `CurveInfo`   | the Curve pool info                                                                                   |
| `i`                     | `uint256`     | the index of the token to swap from                                                                   |
| `j`                     | `uint256`     | the index of the token to swap to                                                                     |
| `dx`                    | `uint256`     | the amount of token i to swap                                                                         |
| `min_dy`                | `uint256`     | the minimum amount of token j to receive                                                              |

## Events

### SlippageUpdated

```solidity
event SlippageUpdated(uint16 oldSlippage, uint16 newSlippage);
```

## Errors

### DexSwapperUManager\_\_Slippage

```solidity
error DexSwapperUManager__Slippage();
```

### DexSwapperUManager\_\_NewSlippageTooLarge

```solidity
error DexSwapperUManager__NewSlippageTooLarge();
```

### DexSwapperUManager\_\_UniswapV3BadPathOrFees

```solidity
error DexSwapperUManager__UniswapV3BadPathOrFees();
```

## Structs

### CurveInfo

Data needed to swap in a Curve pool

*This was made into a struct to prevent stack too deep errors.*

```solidity
struct CurveInfo {
    address pool;
    ERC20 assetIn;
    ERC20 assetOut;
    bytes4 selector;
}
```


# DexAggregatorUManager

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/micro-managers/DexAggregatorUManager.sol)

**Inherits:** UManager

Required Merkle Root Leaves

* ERC20 approves with `router` spender.
* AggregationRouterV5.swap, with all desired addresses.

## State Variables

### MAX\_SLIPPAGE

```solidity
uint256 internal constant MAX_SLIPPAGE = 0.1e4;
```

### allowedSlippage

Slippage check enforced after swaps.

```solidity
uint16 public allowedSlippage = 0.0005e4;
```

### router

The 1Inch Router.

```solidity
AggregationRouterV5 internal immutable router;
```

### priceRouter

The PriceRouter contract used to check slippage.

```solidity
PriceRouter internal immutable priceRouter;
```

## Functions

### constructor

```solidity
constructor(
    address _owner,
    address _manager,
    address _boringVault,
    address _router,
    address _priceRouter
)
    UManager(_owner, _manager, _boringVault);
```

### setAllowedSlippage

Sets the maximum allowed slippage during a swap.

*Callable by MULTISIG\_ROLE.*

```solidity
function setAllowedSlippage(uint16 _allowedSlippage) external requiresAuth;
```

### swapWith1Inch

Performs a swap using the 1inch Router, and enforces a slippage check.

*Callable by STRATEGIST\_ROLE.*

```solidity
function swapWith1Inch(
    bytes32[][] calldata manageProofs,
    address[] calldata decodersAndSanitizers,
    ERC20 tokenIn,
    uint256 amountIn,
    ERC20 tokenOut,
    bytes calldata data
)
    external
    requiresAuth
    enforceRateLimit;
```

**Parameters**

| Name                    | Type          | Description                                                                                                 |
| ----------------------- | ------------- | ----------------------------------------------------------------------------------------------------------- |
| `manageProofs`          | `bytes32[][]` | 2 manage proofs, the first one for the ERC20 approval, and the second for the router swap call              |
| `decodersAndSanitizers` | `address[]`   | 2 DecodersAndSanitizers one that implements ERC20 approve, and one that implements AggregationRouterV5.swap |
| `tokenIn`               | `ERC20`       |                                                                                                             |
| `amountIn`              | `uint256`     |                                                                                                             |
| `tokenOut`              | `ERC20`       |                                                                                                             |
| `data`                  | `bytes`       |                                                                                                             |

## Events

### SlippageUpdated

```solidity
event SlippageUpdated(uint16 oldSlippage, uint16 newSlippage);
```

## Errors

### DexAggregatorUManager\_\_Slippage

```solidity
error DexAggregatorUManager__Slippage();
```

### DexAggregatorUManager\_\_NewSlippageTooLarge

```solidity
error DexAggregatorUManager__NewSlippageTooLarge();
```


# UManager

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/micro-managers/UManager.sol)

**Inherits:** Auth

## State Variables

### period

The period in seconds for the rate limit.

```solidity
uint16 public period;
```

### allowedCallsPerPeriod

The number of calls allowed per period.

```solidity
uint16 public allowedCallsPerPeriod;
```

### callCountPerPeriod

The number of calls made in the current period.

```solidity
mapping(uint256 => uint256) public callCountPerPeriod;
```

### manager

The ManagerWithMerkleVerification this uManager works with.

```solidity
ManagerWithMerkleVerification internal immutable manager;
```

### boringVault

The BoringVault this uManager works with.

```solidity
address internal immutable boringVault;
```

## Functions

### enforceRateLimit

```solidity
modifier enforceRateLimit();
```

### constructor

```solidity
constructor(address _owner, address _manager, address _boringVault) Auth(_owner, Authority(address(0)));
```

### setPeriod

Sets the duration of the period.

*Callable by MULTISIG\_ROLE.*

```solidity
function setPeriod(uint16 _period) external requiresAuth;
```

### setAllowedCallsPerPeriod

Sets the number of calls allowed per period.

*Callable by MULTISIG\_ROLE.*

```solidity
function setAllowedCallsPerPeriod(uint16 _allowedCallsPerPeriod) external requiresAuth;
```

### revokeTokenApproval

Allows auth to set token approvals to zero.

*Callable by STRATEGIST\_ROLE.*

```solidity
function revokeTokenApproval(
    bytes32[][] calldata manageProofs,
    address[] calldata decodersAndSanitizers,
    ERC20[] calldata tokens,
    address[] calldata spenders
)
    external
    requiresAuth;
```

## Events

### PeriodUpdated

```solidity
event PeriodUpdated(uint16 oldPeriod, uint16 newPeriod);
```

### AllowedCallsPeriodUpdated

```solidity
event AllowedCallsPeriodUpdated(uint16 oldAllowance, uint16 newAllowance);
```

## Errors

### UManager\_\_CallCountExceeded

```solidity
error UManager__CallCountExceeded();
```


# migration


# Contents

* CellarMigrationAdaptor


# CellarMigrationAdaptor

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/migration/CellarMigrationAdaptor.sol)

## State Variables

### boringVault

```solidity
BoringVault internal immutable boringVault;
```

### accountant

```solidity
AccountantWithRateProviders internal immutable accountant;
```

### teller

```solidity
TellerWithMultiAssetSupport internal immutable teller;
```

## Functions

### constructor

```solidity
constructor(address _boringVault, address _accountant, address _teller);
```

### identifier

*Identifier unique to this adaptor for a shared registry. Normally the identifier would just be the address of this contract, but this Identifier is needed during Cellar Delegate Call Operations, so getting the address of the adaptor is more difficult.*

```solidity
function identifier() public pure virtual returns (bytes32);
```

### deposit

Function Cellars call to deposit users funds into holding position.

```solidity
function deposit(uint256, bytes memory, bytes memory) public virtual;
```

### withdraw

Function Cellars call to withdraw funds from positions to send to users.

```solidity
function withdraw(uint256 assets, address receiver, bytes memory, bytes memory configurationData) public virtual;
```

**Parameters**

| Name                | Type      | Description                                     |
| ------------------- | --------- | ----------------------------------------------- |
| `assets`            | `uint256` | in terms of accountant's base asset             |
| `receiver`          | `address` | the address that should receive withdrawn funds |
| `<none>`            | `bytes`   |                                                 |
| `configurationData` | `bytes`   |                                                 |

### balanceOf

Function Cellars use to determine `assetOf` balance of an adaptor position.

```solidity
function balanceOf(bytes memory) public view virtual returns (uint256);
```

**Returns**

| Name     | Type      | Description                                  |
| -------- | --------- | -------------------------------------------- |
| `<none>` | `uint256` | assets of the position in terms of `assetOf` |

### withdrawableFrom

Functions Cellars use to determine the withdrawable balance from an adaptor position.

accepts adaptorData and configurationData

*Debt positions MUST return 0 for their `withdrawableFrom`*

```solidity
function withdrawableFrom(bytes memory, bytes memory configurationData) public view virtual returns (uint256);
```

**Returns**

| Name     | Type      | Description                                                |
| -------- | --------- | ---------------------------------------------------------- |
| `<none>` | `uint256` | withdrawable balance of the position in terms of `assetOf` |

### assetOf

Function Cellars use to determine the underlying ERC20 asset of a position.

```solidity
function assetOf(bytes memory) public view virtual returns (ERC20);
```

**Returns**

| Name     | Type    | Description                              |
| -------- | ------- | ---------------------------------------- |
| `<none>` | `ERC20` | the underlying ERC20 asset of a position |

### assetsUsed

When positions are added to the Registry, this function can be used in order to figure out what assets this adaptor needs to price, and confirm pricing is properly setup.

```solidity
function assetsUsed(bytes memory adaptorData) public view virtual returns (ERC20[] memory assets);
```

### isDebt

Functions Registry/Cellars use to determine if this adaptor reports debt values.

*returns true if this adaptor reports debt values.*

```solidity
function isDebt() public view virtual returns (bool);
```

### deposit

Allows strategist to perform a bulkDeposit into Teller.

```solidity
function deposit(ERC20 depositAsset, uint256 depositAmount, uint256 minimumMint) external;
```

### withdraw

Allows strategist to perform a bulkWithdraw from Teller.

```solidity
function withdraw(ERC20 withdrawAsset, uint256 shareAmount, uint256 minimumAssets) external;
```

### \_maxAvailable

Helper function that allows adaptor calls to use the max available of an ERC20 asset by passing in type(uint256).max

```solidity
function _maxAvailable(ERC20 token, uint256 amount) internal view virtual returns (uint256);
```

**Parameters**

| Name     | Type      | Description                                                                                                          |
| -------- | --------- | -------------------------------------------------------------------------------------------------------------------- |
| `token`  | `ERC20`   | the ERC20 asset to work with                                                                                         |
| `amount` | `uint256` | when `type(uint256).max` is used, this function returns `token`s `balanceOf` otherwise this function returns amount. |

### \_revokeExternalApproval

Helper function that checks if `spender` has any more approval for `asset`, and if so revokes it.

```solidity
function _revokeExternalApproval(ERC20 asset, address spender) internal;
```

### \_externalReceiverCheck

Helper function that validates external receivers are allowed.

```solidity
function _externalReceiverCheck(address receiver) internal view;
```

## Errors

### CellarMigrationAdaptor\_\_ExternalReceiverBlocked

Attempted to specify an external receiver during a Cellar `callOnAdaptor` call.

```solidity
error CellarMigrationAdaptor__ExternalReceiverBlocked();
```

### CellarMigrationAdaptor\_\_UserDepositsNotAllowed

Attempted to deposit to a position where user deposits were not allowed.

```solidity
error CellarMigrationAdaptor__UserDepositsNotAllowed();
```

### CellarMigrationAdaptor\_\_UserWithdrawsNotAllowed

Attempted to withdraw from a position where user withdraws were not allowed.

```solidity
error CellarMigrationAdaptor__UserWithdrawsNotAllowed();
```




---

[Next Page](/llms-full.txt/1)

