# Deprecation Guide

## Ion Protocol — Deprecation Guide

Ion Protocol is being deprecated. This document explains how to fully exit each type of position without using the frontend application. All transactions can be executed directly through a block explorer such as [Basescan](https://basescan.org).

***

### Contract Addresses

All deployed contract addresses can be found in [Deployed Contracts](/devs/deployed-contracts)

The examples in this guide use the weETH/WETH market on Base.

| Contract             | Address                                                                                                                 |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| IonPool (weETH/WETH) | [`0x00000000000fA8e0FD26b4554d067CF1856De7F5`](https://basescan.org/address/0x00000000000fA8e0FD26b4554d067CF1856De7F5) |
| Handler              | [`0x2A010d84933c9fe7c1d336Fa991FE23743e38EC9`](https://basescan.org/address/0x2A010d84933c9fe7c1d336Fa991FE23743e38EC9) |
| GemJoin              | [`0xe21ae2d45dEDF8dEE2D854774a904d33b8700E78`](https://basescan.org/address/0xe21ae2d45dEDF8dEE2D854774a904d33b8700E78) |
| Ion LRT Vault        | [`0x0000000000895f1D9e978788C6367d47127dd218`](https://basescan.org/address/0x0000000000895f1D9e978788C6367d47127dd218) |
| Liquidation          | [`0x00000000009229776762B5e6b865a06afeB4444c`](https://basescan.org/address/0x00000000009229776762B5e6b865a06afeB4444c) |

***

### 1. How to Exit a Borrow Position

A borrow position consists of:

* **Collateral** deposited into IonPool (weETH in this market)
* **Debt** denominated in the pool's base asset (WETH in this market)

> **Important**: The dust minimum debt value is set to zero. This means you must repay the **entire loan in one transaction** — partial repayments are not supported. The recommended path is to use the `repayFullAndWithdraw` function on the Handler contract, which handles the accruing interest rate calculation for you automatically.

#### Step 1 — Look up your current position

Go to Basescan and open the **IonPool** contract at [`0x00000000000fA8e0FD26b4554d067CF1856De7F5`](https://basescan.org/address/0x00000000000fA8e0FD26b4554d067CF1856De7F5). Navigate to the **Read Contract** tab and call:

* `collateral(ilkIndex, yourAddress)` — returns your locked collateral amount in WAD (18 decimals).
  * `ilkIndex` should be `0`.
* `normalizedDebt(ilkIndex, yourAddress)` — returns your normalized (principal-only) debt in WAD.
  * `ilkIndex` should be `0`.

#### Step 2 — Identify the base asset you need to repay

The base asset is the token you originally borrowed. To look it up on-chain:

1. Go to the **IonPool** contract on Basescan and navigate to the **Read Contract** tab.
2. Call `underlying()` — this returns the ERC-20 address of the base asset (WETH on Base at `0x4200000000000000000000000000000000000006`).
3. Open that token contract on Basescan to confirm the symbol (e.g. "WETH"). This is the token you must hold in your wallet in order to repay.

#### Step 3 — Approve the Handler to spend your base asset

The Handler will pull the repayment amount from your wallet. You must first grant it an allowance.

1. Open the WETH token contract at [`0x4200000000000000000000000000000000000006`](https://basescan.org/address/0x4200000000000000000000000000000000000006) on Basescan.
2. Go to the token's **Write Contract** tab.
3. Call `approve(spender, amount)`:
   * `spender`: `0x2A010d84933c9fe7c1d336Fa991FE23743e38EC9` (Handler address)
   * `amount`: Use `115792089237316195423570985008687907853269984665640564039457584007913129639935` (max uint256) to avoid needing to calculate the exact amount with interest.

#### Step 4 — Call `repayFullAndWithdraw` on the Handler

1. Go to Basescan and open the **Handler** contract at [`0x2A010d84933c9fe7c1d336Fa991FE23743e38EC9`](https://basescan.org/address/0x2A010d84933c9fe7c1d336Fa991FE23743e38EC9).
2. Navigate to the **Write Contract** tab.
3. Call `repayFullAndWithdraw(collateralToWithdraw)`:
   * `collateralToWithdraw`: The collateral amount you noted in Step 1. This must be in WAD (18 decimal units). For example, 1 weETH = `1000000000000000000`.

What this function does atomically:

1. Fetches your current `normalizedDebt` and the live `rate` from IonPool.
2. Calculates the exact repayment amount (rounding up to avoid dust).
3. Pulls the WETH repayment from your wallet and repays all debt on IonPool.
4. Withdraws the specified collateral from IonPool's internal accounting.
5. Calls `GemJoin.exit` to transfer the weETH collateral tokens back to your wallet.

After this transaction confirms, your vault in IonPool will have zero debt and zero collateral.

***

### 2. How to Exit a Lender Position

A lender position consists of interest-bearing tokens held in your wallet, minted when you called `supply` on IonPool. Your balance automatically grows every block as borrowers pay interest.

#### Step 1 — Identify the base asset you will receive

When you withdraw, you receive the pool's base asset back in your wallet. To confirm what that token is:

1. Go to the **IonPool** contract at [`0x00000000000fA8e0FD26b4554d067CF1856De7F5`](https://basescan.org/address/0x00000000000fA8e0FD26b4554d067CF1856De7F5) on Basescan and navigate to the **Read Contract** tab.
2. Call `underlying()` — this returns the ERC-20 address of the base asset (WETH on Base at `0x4200000000000000000000000000000000000006`).

#### Step 2 — Check your current balance

On the same **IonPool** Read Contract tab, call:

* `balanceOf(yourAddress)` — returns the current underlying asset value of your position in WAD. This is the amount of WETH you can withdraw right now, including all accrued interest.

#### Step 3 — Call `withdraw` on IonPool

1. Stay on the **IonPool** contract page.
2. Navigate to the **Write Contract** tab.
3. Call `withdraw(receiverOfUnderlying, amount)`:
   * `receiverOfUnderlying`: The address that should receive the WETH (typically your own address).
   * `amount`: The amount of WETH to withdraw in WAD. Use the value from `balanceOf` in Step 2 to fully exit. You may want to use a slightly smaller value to account for any rounding in the final block before your transaction lands.

After this transaction confirms, your interest-bearing token balance on IonPool will be zero and you will have received WETH in your wallet.

***

### 3. How to Exit a Vault Position

The Ion LRT Vault is an ERC-4626 vault that holds WETH and supplies it across multiple underlying Ion Protocol lending markets on Base. Your position is represented as vault shares in your wallet.

#### Step 1 — Check your shares and underlying value

Go to Basescan and open the **Ion LRT Vault** contract at [`0x0000000000895f1D9e978788C6367d47127dd218`](https://basescan.org/address/0x0000000000895f1D9e978788C6367d47127dd218). On the **Read Contract** tab, call:

* `balanceOf(yourAddress)` — returns your vault share balance.
* `convertToAssets(shares)` — returns the WETH value of your shares at the current exchange rate.
* `maxRedeem(yourAddress)` — returns the maximum shares you can currently redeem given available liquidity.

#### Step 2 — Call `redeem` on the Vault

1. Navigate to the **Write Contract** tab on the Ion LRT Vault.
2. Call `redeem(shares, receiver, owner)`:
   * `shares`: The number of vault shares you want to burn (use your full `balanceOf` to fully exit).
   * `receiver`: The address that should receive the WETH (typically your own address).
   * `owner`: Your own address (the address holding the shares).

Alternatively, if you want to specify an exact WETH amount rather than a share amount, use `withdraw(assets, receiver, owner)` instead.

#### Step 3 — If the transaction reverts with `NotEnoughLiquidityToWithdraw`

The vault iterates through a `withdrawQueue` of underlying Ion lending markets. If the underlying liquidity in those markets has been fully borrowed out, there may not be enough free liquidity to fulfill your withdrawal.

In this situation:

* **Wait**: As borrowers repay their loans or are liquidated, liquidity returns to the markets and becomes available for withdrawal.
* **Check available liquidity**: On the **IonPool** contract(s) supported by the vault, call `liquidity()` on the **Read Contract** tab to see how much WETH is currently available. When liquidity is sufficient to cover your withdrawal amount, retry the transaction.
* You can also call `maxWithdraw(yourAddress)` on the Vault to see the maximum amount currently withdrawable given available liquidity.

> The protocol liquidation contract is at [`0x00000000009229776762B5e6b865a06afeB4444c`](https://basescan.org/address/0x00000000009229776762B5e6b865a06afeB4444c). Liquidations will free up collateral and return liquidity to the lending pools over time.


# Welcome to Ion Protocol

The Lending Platform for Staked & Restaked Assets

<div data-full-width="true"><figure><img src="/files/q9oKmGFw7i7agJ6atLGq" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
**Ion Protocol Tip:** If you want to skip to the fun and read the docs later, head right over to  [ionprotocol.io ](https://ionprotocol.io/)
{% endhint %}

## Welcome!

Ion Protocol is a price-agnostic lending platform built to support staked and restaked assets. It allows users to participate in lending markets of all kinds, ranging from leveraged staking yields to points multiplier pools and more. Ion focuses on bringing staking-based mechanisms to DeFi, creating an enhanced lending and borrowing experience for users to earn more while risking less.

In Ion's first phase of its launch, it will specifically be focusing on supporting isolated markets that enable stakers to lend LSTs to enhance their staking yield while rest. At the same time, restakers can borrow with their LRTs to multiply their EigenLayer and LRT returns.&#x20;

* **Lenders** will earn the highest ETH on ETH returns available without leverage!
* **Borrowers** can multiply their exposure to ongoing points and incentives campaigns and future restaking yield, while keeping their ETH upside!

If there is any additional info you'd like us to clarify or can't find within the documentation, join the Discord community [here](https://discord.com/invite/CjQqUgPA6Y) and drop a question!

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

## Why Use Ion?

### **You Want to Increase Your Restaking Rewards**

Borrowers in Ion Protocol can boost their points exposure by up to 10x+. By utilizing Ion's out-of-the-box earn strategies, users can leverage flash loans to maximize their exposure to restaking, without any concerns about oracle pricing risk.

*This is the simplest and most secure method for borrowers to maximize their restaking rewards.*

### You're Early to Restaking

In addition to increased restaking-related points currently, borrowers will lock-in their position to be first in line to multiply their restaking yield as long as they can maintain their borrow position once AVSs are live and LRTs begin generating a return.

*Ion Protocol will be the premiere platform to scale restaking and optimize risk-adjusted boosted restaking yields.*

<figure><img src="/files/3M0ThfFgMCHnGhfQKQfQ" alt=""><figcaption></figcaption></figure>

### **You're a Lender Who Wants to Earn ETH Yield**

Ion Protocol prioritizes properly compensating lenders for supplying markets with lender-side liquidity in the form of LSTs. Since our markets are isolated, lenders can select the desired risk profile of the market they supply. This makes it possible for them to earn staking returns + yield paid by borrowers + any additional incentives with zero exposure to risks from other collateral assets.&#x20;

*We cater to lenders, the lifeblood of a lending protocol - providing them with the most sustainable ETH-denominated yield for lenders' liquidity in the market.*&#x20;

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

## Ion's Core Architecture - Making It All Possible

All loan positions in Ion are price-agnostic, and their parameters (interest rates, LTVs, position health, etc.) are determined by consensus layer data and secured with ZK data systems.

* This means liquidations are triggered by consensus layer state changes, not price oracles. &#x20;
* This verifiable [Proof-of-Reserve](/borrowing/borrowing-mechanisms/zk-proof-of-reserve) system is enabled by a network of oracles and our [ZKML](/lending/lending-mechanisms/zkml-supported-risk-underwriting) (zero-knowledge machine learning) framework, which allows trustless verification of consensus layer state and validator credit ratings. &#x20;

Users in Ion can deposit any combination of the following [collateral types](/supported-collateral/lsts) into the protocol's markets once it expands past LRTs.

1. LSTs
2. LST LP Positions
3. Bespoke Re-staking Positions
4. Fixed Rate Positions (e.g. Pendle's PT Tokens)
5. Staked LST LP Positions (e.g. Aura Finance’s ERC-4626 positions)
6. LST Index Products (e.g. IndexCoop’s dsETH, UnshETH, and more)

## Getting Started

{% content-ref url="/pages/PlXIHaRdv7dwSsDQZEmm" %}
[Understanding the Staking and Restaking Ecosystem](/overview/understanding-the-staking-and-restaking-ecosystem)
{% endcontent-ref %}

{% content-ref url="/pages/7MiQ8AJ8lVxeDfdvxWds" %}
[How Ion Works](/ion-protocol/how-ion-works)
{% endcontent-ref %}

{% content-ref url="/pages/muK7J3FDIBj9ozc5vDTT" %}
[FAQ](/overview/faq)
{% endcontent-ref %}


# Understanding the Staking and Restaking Ecosystem

A comprehensive overview of the staking ecosystem on Ethereum.

## The Shift from PoW to PoS

Consensus mechanisms serve as the bedrock of any crypto network. They are designed to ensure network safety, provide transaction validity, and facilitate coordination among network participants for state transitions. Ethereum's consensus protocol aims to make the blockchain more expensive to destroy or disrupt than to use or maintain.

Ethereum's transition from PoW to PoS solved three significant problems:

1. PoS offers more security for the same cost than PoW.
2. Malicious actors on the network are easier to disincentivize.
3. It’s easier to encourage decentralization.

We believe in the inherent value of security and are building for the future, making re-staked value composable with on-chain markets. By participating in Ion, holders of any validator-backed asset can participate in DeFi without sacrificing composability.

***

## Deposits and Withdrawals in Ethereum Proof of Stake

As mentioned above, Ethereum has transitioned from PoW to PoS, which provides an effective security mechanism for the blockchain. In PoS, stakers are required to deposit 32 ETH to become a validator, and these validators are randomly assigned as proposers (responsible for producing blocks) or attestors (responsible for submitting attestations).

Validator balances increase due to deposits and rewards and decrease due to withdrawals and penalties. Ethereum has also transitioned from a monolithic blockchain to a modular one, comprising the consensus layer (CL) and the execution layer (EL). These two layers communicate through the Engine API.

Deposits and withdrawals play a crucial role in Ethereum's consensus layer. They ensure that the blockchain operates smoothly and securely. Here's how these mechanisms work:

#### Deposits

In Ethereum's PoS, there are two types of deposits:

1. Initial deposits, used to create a validator
2. Top-up deposits, required when a validator balance falls below the maximum effective balance.

A user deposits to the Ethereum Deposit Contract (EDC), and this transaction is verified by the consensus layer. This deposit mechanism is quite straightforward.

#### Withdrawals

Unlike deposits, withdrawals are a more recent development that require a closer look. There are two types of withdrawals:

1. Partial withdrawals: If a validator's balance exceeds 32 ETH, the excess is transferred to the execution layer (EL). This happens automatically and allows the validator to continue their responsibilities.
2. Full withdrawals: If you exit from the validator set, all your ETH is transferred to the EL. This action has to be done manually and it involves unlocking the entire validator balance, effectively causing the validator to stop participating in the beacon chain.

The withdrawal mechanism enhances the resiliency of the Ethereum network while allowing stakers to claim their rewards and exit the network at their own will. The introduction of withdrawals was initially met with skepticism. However, Ethereum has proven its robustness in securing the network and significantly de-risking ETH staking. As a result, the network has seen a significant increase in the number of validators.

By facilitating validator diversity, capital flow, and composability, the withdrawal mechanism enhances Ethereum's security and versatility. These attributes align with Ion's features, particularly the diversity in supported collateral types, integration of reward distribution, and validator risk underwriting.

In essence, this mechanism enables Ion Protocol to unlock the value of validator staked capital.&#x20;

***

## Liquid Staking x DeFi

Liquid Staking DeFi, also referred to as LSTfi, is a rapidly evolving sector within the broader decentralized finance ecosystem.

LSTFi protocols build innovative financial instruments on Liquid Staking Tokens (LSTs). This strategy is designed to boost capital efficiency, diversify provider incentives, and expand access to yield strategies.

LSTs have sparked a revolution in the staking landscape by democratizing access to staking, preserving on-chain liquidity, and enabling more interoperability between validator-backed assets. This growth has been amplified by the entrance of new liquid staking providers like Frax Finance, Swell Protocol, and more.

However, the introduction of LSTs and the strategic flexibility they provide for validator collateral are not without risks. These include slashing risks, LST pricing risks, smart contract risks, and validator infrastructure risks.

We are adopting a risk-first approach to support these LSTs and the diverse strategies associated with them as collateral. We have devised a unique method for quantifying risk within our collateral vaults and isolating risk exposure for users on a provider-by-provider basis.

Our approach enables us to build innovative primitives for a new asset class entering the ecosystem: re-staking positions. Protocols like EigenLayer are developing platforms for re-staking validator capital, and within Ion, users can utilize these re-staking positions as collateral.

***

## Staking Mechanisms: Rewards, Penalties, and Slashings

To understand slashing, we first have to comprehend the reasons behind the existence of rewards and penalties for validators. Validators stake their claim in Ethereum's security, pledging to follow certain rules. This commitment invites rewards if rules are followed and penalties if violated, serving as the basis for providing security via proof of stake.

The two pillars that underpin the PoS consensus on Ethereum are safety and liveness. Safety ensures no conflicting blocks in the canonical chain, while liveness guarantees the chain grows plausibly and probabilistically without interruption.

These principles led to the creation of Gasper, a fusion of Casper FFG, a finality tool, and LMD GHOST, a fork-choice rule.

Validators are expected to perform certain predetermined actions that allow them to contribute to the network’s consensus:

* Attesting for a source, target checkpoint, and head block
* Signing off on blocks in the sync committees
* Proposing blocks

The most common and rewarding duty is attestation, while sync committee and proposer duties are assigned randomly. Each duty has respective weights reflecting their importance within the protocol.

To measure time in Ethereum's consensus protocol, epochs made of 32 slots are used. Active validators must attest once per epoch. Their rewards are distributed in a weighted manner according to their performance concerning specific duties in the form of newly minted ETH.

{% hint style="info" %}
Epochs are made of 32 slots

1 slot = 12 secs

1 epoch = 6 mins 24 secs
{% endhint %}

Bad behavior doesn't go unpunished. The beacon chain disincentivizes inappropriate behavior through penalties and slashing. Validators can be penalized for missed votes, equal to their potential reward. Slashing, however, is an irreversible punishment for validators who make attestations or proposals that contradict Gasper's consensus rules. It deducts a percentage of the offender's stake, leading to a steady loss of ETH over time.

Certain conditions can lead to slashing, including:

* Proposing and signing two different blocks for the same slot
* Attesting to a block that "surrounds" another one
* "Double voting" by attesting to two candidates for the same block

A slashing penalty is comprised of:

An initial slashing penalty upon confirming a slashable condition and a collusion-based penalty experienced halfway through the withdrawal period.

At Ion, we view the validator's effective balance as the standard of health for a validator. If a validator's balance decreases due to slashing, their health declines too. A slashed validator impacts the health of the entire validator set since they're forcibly exited from the beacon chain.

Although the risk of slashing is generally low, we anticipate the complexity of validator risk profiles to increase as more liquid staking and re-staking providers join the market. At Ion, we're gearing up for this future, striving to create an ecosystem with a variety of providers and re-staking platforms to increase options and decentralization for stakers across the ecosystem.

***

## Extending Ethereum’s POS Security

Ethereum’s PoS consensus mechanism offers a unique advantage: it's programmable and scalable security via cryptoeconomic value. This security, intrinsic to Ethereum, extends seamlessly to all of the protocols that are secured by the underlying continuity of the beacon chain as a byproduct. This is a diverse array of smart contract protocols, ranging from decentralized exchanges (DEXs) to NFT marketplaces. However, until recently, this robust security framework didn't wasn’t able to innately extend itself to other applications or distributed systems such as bridges, sequencers, data availability layers, or other blockchains that required some other form of consensus. Systems like these have traditionally been tasked with bootstrapping their own consensus mechanisms to safeguard their operations, a challenge exemplified by platforms like Axelar and its native PoS network.&#x20;

#### Restaking: Bridging the Security Gap

Addressing this gap in extendability of security provisioning led to the inception of restaking—a pioneering concept that allows staked assets on Ethereum to bolster the security of arbitrary distributed systems. [EigenLayer](https://www.eigenlayer.xyz/), the first restaking protocol, coined the term "Programmable Trust" to describe this mechanism. More intriguingly, the distributed systems benefiting from this trust mechanism are termed Actively Validated Services (AVSs).

#### EigenLayer: Amplifying Commitments and Security

At its core, [EigenLayer operates as an amalgamation of smart contracts and off-chain software](https://docs.eigenlayer.xyz/overview/readme), amplifying the commitments a validator or other external node operator can undertake. This enhancement enables validators to engage with AVSs, requiring them to run supplementary software.&#x20;

Concurrently, the EigenLayer smart contracts introduce new slashing conditions on the restaked Ethereum, predicated on the specifications of the chosen AVS. In exchange, these restakers are able to earn rewards for providing security to these systems. These conditions are agnostic to whether Ethereum is staked directly or via LSTs from an affiliated liquid staking provider. This makes it easier for distributed systems to build a security model without having to worry about bootstrapping security providers–stakers. Restakers can opt-in to multiple AVSs, exposing their stake to multiple slashing conditions and earning rewards from multiple AVSs. Ultimately, EigenLayer pools security through restaking instead of fragmenting it. Pooling security is what enables multiple parties to combine their resources to provide greater security for the entire restaking ecosystem.

#### Unveiling EigenLayer’s Potential: AVSs and New Yield Opportunities

The emergence of AVSs that can harness programmable trust heralds a transformative phase for distributed systems. Not only do they offer unprecedented access to inherited security, but they also unlock a myriad of additional yield opportunities for stakers. By providing security to these services, stakers can tap into innovative avenues for rewards while maintaining alignment with [Ethereum’s long term goals](https://vitalik.eth.limo/general/2021/12/06/endgame.html) and supporting the services they desire.

***

## Potential Limitations of Restaking

#### Introduction to Potential Limitations

While restaking brings an enticing opportunity for stakers to amplify their returns, it's not devoid of [challenges](https://vitalik.eth.limo/general/2023/05/21/dont_overload.html). The added slashing conditions introduced by platforms like EigenLayer lead to augmented rewards for stakers, compensating for the heightened risk. Yet, the architectural constraints of EigenLayer hint at potential composability issues with restaking positions, notably due to the intricate risk profiles that arise. This complexity mirrors the challenges that PoS grappled with during its early stages.

#### Future Scenarios for Restaking in DeFi

Broadly, there are two potential trajectories for the integration of restaking positions into the DeFi landscape:

**Scenario 1: Governance-Gated Risk Management**

Liquid staking providers might decide to mitigate some of the inherent risks of restaking strategies by implementing governance-based selections. Here, the strategies deemed appropriate for their users' risk tolerance are permitted. Consequently, this could lead providers to segment their offerings, targeting specific risk demographics. For instance, a platform like Lido, aspiring to be perceived as a 'safety-first' provider, may renounce users with a higher risk appetite, as they'll be more inclined to seek providers promising greater yields through aggressive restaking strategies.

**Scenario 2: Non-Fungibility and the Push to LST Users**

Should situations arise where dominant platforms like EigenLayer experience significant slashing events or there's a widespread erosion of trust in providers, it may become infeasible for liquid staking providers to endorse restaking at the node operator level. Instead, the decision-making may shift to LST users. Here, EigenLayer restaking positions could become the predominant staked asset representation. However, due to their distinctive risk profiles, these assets are inherently non-fungible. This poses challenges in assimilating them into the broader DeFi ecosystem since most protocols are parameterized based on price-based dependencies. Restaking positions would find trouble here due to their intrinsic scarcity of liquidity and limited price discovery.

#### The Conundrum of Staked Asset Financialization

While EigenLayer and similar platforms seek to fortify PoS networks through innovative staking models, the escalating complexities in validator risk profiles inadvertently spawn secondary challenges. Both aforementioned scenarios hint at a landscape where staked and restaked assets become fragmented and illiquid. This dynamic severely hampers the feasibility of leveraging restaking positions within the DeFi ecosystem.

***

## Liquid Restaking Tokens (LRTs) Explored

#### Definition and Overview

Liquid Restaking Tokens, or LRTs, are the derivative representations of restaking positions. Analogous to LSTs, LRTs have emerged to grant broader and more intuitive access to restaking positions. Numerous protocols are championing this initiative, though the frontrunner is yet to emerge. Before delving into these protocols and distinguishing their attributes, it's essential to appraise the pros and cons of LRTs.

#### The Differences Between a Liquid Staking Provider and LRT Provider

Liquid staking providers and LRT providers have similar end goals, which is to provide stakers or restakers respectively with a liquid representation of their underlying position. However, they reach this end by different means. The liquid staking provider is solely focused on providing depositors with a means of connecting with a reliable node operator so that they can spin up validators and provide receipt tokens for staking positions. They help match capital to hardware operators. On the other hand, LRT providers must also account for the risk profile of AVSs which they opt-in to and further expose their LRT holders to.  Liquid restaking helps manage capital delegation between yield opportunities as a form of portfolio management. Their goal is to return the user upside while minimizing risk exposure. Identifying an appropriate risk to reward framework which characterizes the LRT is one of the primary objectives of an LRT’s governance mechanism, whereas the governance mechanism for liquid staking providers is less objective.&#x20;

#### Advantages of LRTs

LRTs facilitate more seamless integrations between restaking and DeFi. This aligns closely with the first potential future for restaked assets we previously discussed. That is, LST providers create liquid representations of restaking positions and manage them through governance-gating. This could enable LST providers to create well-defined risk profiles, enabling users to properly manage their portfolio of restaked assets and relish enhanced versatility. This approach enables restakers to participate in DeFi while still gaining the benefits of restaking.

#### Considerations for Users

While the benefits of LRTs are apparent, potential users should remain cognizant of their constraints. As described in the first scenario, many upcoming LRTs incorporate some form of governance oversight. This can restrict the flexibility of LRT holders to express their risk appetite and support their desired AVSs. This governance model raises pertinent questions about the motivations underpinning LRT providers' endorsements of specific AVSs and their ability to create a well justified risk to reward model. A transparent exploration of these motives in governance forums will be crucial for maintaining trust and transparency.

#### Challenges in Underwriting LRTs

The task of underwriting LRTs presents its own set of complexities. It might be equally, if not more, challenging than underwriting LSTs, given the nuanced risk profiles and unique pricing dynamics of LRTs. Addressing these challenges mandates protocols to adopt a more asset-specific approach towards creating markets for which LRTs can be sustainably supported. A deep understanding of the underlying mechanics of Ethereum core infrastructure, PoS, AVS design, and LRT design will be crucial.


# Official Links

#### Website:[ ](https://ionprotocol.io/)<https://www.ionprotocol.io/>

#### Web App: <https://www.app.ionprotocol.io/>

#### Docs: [https://www.docs.ionprotocol.io](#docs-https-www.docs.ionprotocol.io)

#### Twitter: <https://twitter.com/ionprotocol>

#### Discord: [discord.gg/CjQqUgPA6Y](https://t.co/A3LBmSZet1)

#### Galxe: <https://app.galxe.com/quest/ionprotocol?hideFooter&id=32213>

#### Github: <https://github.com/Ion-Protocol/ion-protocol>


# FAQ

## What is Ion Protocol?

Ion Protocol is a price-agnostic lending platform built to support staked and restaked assets. Using provable validator data, Ion allows users to borrow LSTs 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 and secured with ZK data systems.
* This means liquidations are triggered by **changes in consensus layer state, not by price oracles.**
* This verifiable Proof-of-Reserve system is enabled by a network of oracles running our ZKML (zero-knowledge machine learning) framework which enables trustless verification of consensus layer state and robust validator credit ratings.

The above investments in trustless infrastructure enable us to support a wide plethora of assets without sacrificing on capital efficiency.

## How do I gain access to the whitelist?

During Ion's multi-phase mainnet launch, the first users to interact with the protocol will be whitelisted to minimize the risk within the platform while providing an opportunity for early users to take advantage of Ion's product offerings.

To join the whitelist, provide active feedback on the product, interface, and interact with the community in our Discord!

## How do I interact with Ion?

The mainnet release will showcase multiple LST/LRT Markets and a rewards tracker.

* Deposit Liquid Staking Tokens (LSTs) into asset-specific vaults.
  * Select any combination of markets to deposit into, or deposit into all markets.&#x20;
  * By selecting a combination of markets, lenders can specify their desired risk profile.&#x20;
  * Once you've selected the market for you, deposit your LST and passively earn rewards in ETH.
* Deposit Liquid Restaking Tokens (LRTs) into vaults that compound your restaking reward exposure.

  * Deposit your preferred LRT.
  * Choose the designated multiplier for your position.
  * View and manage your position all from the Ion interface.

## What can I do on Ion?

* Lenders - Earn the staking yield + borrow yield + additional LRT + yield rewards
* Borrowers - Boost your restaking rewards (EigenLayer Points + Collateral Provider Points) and lock in your position for boosted restaking yield once AVSs reach the market.

  * Borrowers should ensure their ability to make interest repayments to maintain their boosted restaking rewards.

## What are the risks of Ion?

* Smart contract risk - Smart contract risk is common in any DeFi protocol. We've taken all the necessary preventative measures and more including thorough audits with top auditors, audit competitions, and  formal verification.
* Liquidation risk - Borrowers on Ion are only exposed to liquidation risks in the event of a large correlated slashing that significantly reduces the ETH reserves of a provider's validator set. Or if they do not make interest payments on time.

## **Is Ion a liquid re-staking provider?**&#x20;

Nope! We're a lending platform aimed at allowing people to borrow against validator-backed assets such as LRTs. We love chatting with providers though and recommend to reach out to us on [Twitter ](https://twitter.com/ionprotocol)if you're interested in pursuing an integration.&#x20;

## **How can I provide feedback and stay updated on Ion Protocol developments?**&#x20;

You can join the Ion Protocol Discord community to provide feedback and follow Ion Protocol on Twitter for updates.

* In our Discord make sure to leave your feedback.
* Feel free to share your experience with others as well!

## **How long will it take me to earn a ref link?**

Anyone who gains access to Ion via referral link can generate a referral link of their own after earning 120 Ion Points. Given that our points accrue at 1 Ion Point per ETH deposited per hour deposited, 120 Ion Points can be earned with 5 ETH of value in Ion in 1 day.

## **If I earn Ion Points via an integration, what does this mean for me?**

Anyone who earns Ion Points via an integration can create a referral code to enter Ion. If they have already earned 120 Ion Points, then they will immediately be able to generate a referral link.

## How does using a referral code contribute to my Ion Point earnings?

| Number of Referrals | % Increase in Points Earnings from User Deposits |
| ------------------- | ------------------------------------------------ |
| 1                   | 1.5%                                             |
| 5                   | 3%                                               |
| 10                  | 8%                                               |
| 15                  | 10%                                              |
| 20                  | 12%                                              |
| 25                  | 15%                                              |
| 30                  | 20%                                              |
| 50-100              | 25%                                              |
| 100+                | 30%                                              |

**For borrowers:**

$$
24(debtValue\*(1 + (percentIncrease / 100)))
$$

**For lenders:**

$$
240(depositValue \*(1 + (percentIncrease / 100)))
$$

## What is the math behind Ion Points?

**Lender Side: 10 points per ETH per hour deposited:**

$$
exchangeRate \* supplyDepositAmount \* hoursDeposited
$$

**Borrow Side: 1 point per ETH per hour of collateral:**

$$
exchangeRate \* collateralDepositAmount \* hoursDeposited \* leverageMultiplier
$$

$$
leverage Multiplier = \frac{1}{1 - LTV}
$$


# How Ion Works

A high-level technical overview of the architecture underlying Ion Protocol.

## **Ion Protocol Serves A Two-Sided Market**

* **Lenders** are DeFi users looking to deposit into Ion Protocol and earn sustainable ETH-on-ETH yields. They can select any combination of available markets to deposit into, choosing the counterparty assets that fit their ideal risk profile and yield outcomes.
* **Borrowers** are stakers or restakers who are seeking increased exposure to yield and points. Ion Protocol was specifically designed to provide a more secure and capital-efficient environment for borrowers of staked & restaked collateral. All loan positions are price-agnostic, and their parameters (interest rates, LTVs, position health, etc.) are determined by consensus layer data and secured with ZK data systems.

## Ion's Core Components

Ion Protocol can be broken down into three core components: Lending, Borrowing, and Liquidations. Though at the core of many lending platforms, within Ion, these mechanisms were all designed with optimizing the DeFi experience for staked & restaked assets in mind. Rather than designing the protocol with price-based dependencies like the rest of DeFi, Ion Protocol was designed to underwrite ETH-denominated yield and Ethereum-based infrastructure risks specifically.

***

### Lending-specific Mechanisms

* **Composable Markets:** Ion inherits the composability of being able to create distinct isolated markets as well as markets of multiple collateral types. This modularity allows users to better minimize systemic collateral risk in the protocol and mitigate negative second-order effects that can arise from including more risk-on collateral. This market flexibility allows markets to have more granularity on the tailoring of risk parameters to the specific characteristics of each collateral asset, such as adjusting LTV ratios and interest rates. Composable markets also offer the protocol more control over newly listed assets to assess their performance and risk profile before considering the inclusion of more risk-on asset types in a single shared pool.

{% content-ref url="/pages/NTO11rYfJmHahvz9E6WB" %}
[Composable Markets](/lending/lending-mechanisms/composable-markets)
{% endcontent-ref %}

* **ZKML-Supported Risk Underwriting:** Ion Protocol uses a risk analysis engine, **Clarity**, powered by ZKML that generates validator credit ratings to analyze the propensity of validator subgroups to be slashed. This enables us to properly monitor the state of many validators on the beacon chain. By monitoring this activity, Clarity aggregates provider metrics to better underwrite staked and restaked asset markets to better inform parameterization around staked asset slashing risk.

{% content-ref url="/pages/UrNIRhVO41xDDwy8rg8o" %}
[ZKML-Supported Risk Underwriting](/lending/lending-mechanisms/zkml-supported-risk-underwriting)
{% endcontent-ref %}

***

### Borrowing-specific Mechanisms&#x20;

* **Flash Leverage:** Ion Protocol possesses automated flash loan enabled borrowing strategies that minimizes user friction to access rewards multiples on their collateral. Users automatically source additional collateral via flash loans and swaps and repay debts in the same transaction by borrowing from Ion. The system supports multiple strategies for leveraging or deleveraging, equipped with slippage tolerance for risk management, and the interface helps users identify the most cost-efficient transaction paths.

{% content-ref url="/pages/UtYDxRCZUTHSDsULkqyh" %}
[Flash Leverage](/borrowing/borrowing-mechanisms/flash-leverage)
{% endcontent-ref %}

* **Yield Reactive Interest Rates:** Traditional DeFi interest rate models are set according to specific utilization rates of the supply asset and adjusted via governance in reaction to market dynamics. However, in Ion Protocol's markets, each collateral asset receives a uniquely parameterized interest rate model, regardless if the asset being borrowed is the same. In addition, these markets are specifically designed to support validator-backed assets like LSTs and LRTs which generate yield. For collateral assets that earn substantial returns, Ion's interest rate maturation curves reacts to the yield changes of the underlying collateral to enable borrowers to minimize the fluctuations in their costs while allowing lenders to capture any return to the upside.

{% content-ref url="/pages/kLwWtjn0qTf2wA9RQ6XC" %}
[Interest Rates](/borrowing/borrowing-mechanisms/interest-rates)
{% endcontent-ref %}

* **Solvency-Based Underwriting:** Ion introduces a novel approach to underwriting validator-backed assets. Ion quantifies the solvency of a LRTs and other staked and restaked assets based on the ETH in its provider’s validator reserves instead of depending on price oracles or AMM counterparty liquidity. This mechanism removes volatility and asset de-pegging from being a risk that borrowers are exposed to. In Ion Protocol, borrowers only get liquidated after serious slashing events or if they don't pay their interest, greatly decreasing the risk profile of being a borrower in DeFi.

{% hint style="success" %}
This means liquidations are triggered by changes in ***consensus layer state***, not by price oracles.&#x20;
{% endhint %}

{% content-ref url="/pages/Fphvvu28XOQHgngkW3bd" %}
[ZK Proof-of-Reserve](/borrowing/borrowing-mechanisms/zk-proof-of-reserve)
{% endcontent-ref %}

### Liquidations

* **Staking-specific Liquidations (AKA price-agnostic):** Liquidations on Ion Protocol consider the underlying value of ETH present in validators that back a representative staked or restaked asset mapped to the validators’ balance. This enables Ion to liquidate positions by assessing changes in the underlying balances of the validators backing a collateral vault rather than by volatile price action. Additionally, because slashing events are inherently more discrete than price decreases, they tend not to cascade quickly (except for correlated slashing events under network-wide collusion). Ion opens Dutch auctions against liquidatable positions to liquidate only the amount of borrower collateral necessary to bring back the vault to a target health ratio, enabling safer loans with minimized liquidation impact for borrowers.

{% content-ref url="/pages/WVGqvsz5tUMHc4rrfCUy" %}
[Liquidation Mechanism](/liquidations/liquidation-mechanism)
{% endcontent-ref %}


# Referrals

Ion Protocol's referral program lets users benefit from referring users who become active with the protocol by lending or borrowing.

{% hint style="info" %}
Before reading on about referrals, check out the [points](/ion-protocol/ion-points) section of the docs.
{% endhint %}

## The rules are simple:

1. Anyone can mint a referral code after earning 240 Ion Points.
2. Anyone who uses a referral link gets a referral link after earning 120 points.

Once a user has a referral code they can start increasing their Ion Points earning potential by referring more users.

| Number of Referred | % Increase in Collateral |
| ------------------ | ------------------------ |
| 1                  | 1.5%                     |
| 5                  | 3%                       |
| 10                 | 8%                       |
| 15                 | 10%                      |
| 20                 | 12%                      |
| 25                 | 15%                      |
| 30                 | 20%                      |
| 50-100             | 25%                      |
| 100+               | 30%                      |

## Referral math for borrowers:

$$
hours Borrowing\*(debtValue\*exchangeRate(1 + (percentIncrease / 100)))
$$

## For lenders:

$$
hoursLending\*(depositValue\*exchangeRate \*(1 + (percentIncrease / 100)))
$$


# Ion Points

## Borrow Side: 1 point per ETH per hour of debt

***

### Math

$$
exchangeRate \* debtAmount\* hoursDeposited\*leverageMultiplier
$$

$$
leverageMultiplier = \frac{1}{1-LTV}
$$

### Breakdown

* daily points per 1 ETH deposited: 24
* weekly points per 1 ETH deposited: 168
* monthly points per 1 ETH deposited: 720
* Borrowers can lever up in which case these amounts would be multiplied by a leverage multiplier greater than 1

## Lender Side: 10 points per ETH per hour deposited

***

$$
exchangeRate \* lenderDepositAmount\*hoursDeposited
$$

### Breakdown

* daily points per 1 ETH deposited: 240
* weekly points per 1 ETH deposited: 1680
* monthly points per 1 ETH deposited: 7200
* After 100 M TVL lenders get 2x points


# How To Lend On Ion

## Depositing

***

### 1. Select lend

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

### 2. Select a market

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

### 3. Select deposit

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

### 4. Enter the amount to supply and press the deposit button

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

## Withdrawing

***

### 1. Select withdraw&#x20;

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

## 2. Enter the amount to withdraw and press the withdraw button

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


# ETH-on-ETH Yield

Ion Protocol utilizes a lending market design that provides the optionality to isolate each market's risks, allowing lenders to earn higher yields by supplying LSTs to borrowers who collateralize LRTs and other staked/restaked assets. This model mitigates the centralized lending risk associated with pooled lending, offering a more well-defined and secure lending environment. Ion's first market is designed to support the demand for EigenLayer and LRT rewards, promising lenders ETH-based yields for depositing LSTs to lend to borrowers.

## Key Features

* **Composable Markets:** Ion's markets are composable, enabling lenders to tailor their DeFi strategies according to their risk preferences. Unlike traditional pooled lending protocols, Ion allows lenders to focus on specific collateral assets or subgroups of collateral assets, reducing exposure to insolvency risks from other markets.
* **ZKML Supported Risk Underwriting:** Ion employs a validator-based risk analysis approach, leveraging zero-knowledge machine learning to assess the risk of slashing based on validator metrics, enabling off-chain data analysis that's verifiable on-chain for cost-effective complex computations. This assists in facilitating Ion's dynamic interest rate adjustments based on the analyzed risk.
* **Enhanced Earnings:** By supporting LST lending and LRT collateralization, Ion redefines earning for lenders, enabling lender returns to include: Staking Yield + Borrowing Yield + Additional Incentives.

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

## Why Choose Ion?

Ion Protocol focuses on maximizing lender exposure to ETH-on-ETH yields and supporting specific demands within the DeFi ecosystem, providing a unique opportunity for stakers to earn more with their LSTs securely and sustainably.


# Lending Mechanisms

{% content-ref url="/pages/NTO11rYfJmHahvz9E6WB" %}
[Composable Markets](/lending/lending-mechanisms/composable-markets)
{% endcontent-ref %}

{% content-ref url="/pages/UrNIRhVO41xDDwy8rg8o" %}
[ZKML-Supported Risk Underwriting](/lending/lending-mechanisms/zkml-supported-risk-underwriting)
{% endcontent-ref %}


# Composable Markets

Since Ion is targeted at supporting validator-backed assets, supply-side liquidity in the lending markets can comprise of any staked or restaked asset. Ion's first markets accept wstETH as the underlying lending asset, providing wstETH holders access to additional passive yield without exposing themselves entirely to the trust assumptions and risks of restaking.

## **Understanding Market Composability**

Market composability refers to Ion's ability to segment lending pools within the protocol, each with their own distinct set of assets, risk parameters, and interest rates. This segmentation ensures that the risks associated with one market do not spill over into others, safeguarding the protocol and its users from systemic failures. By segmenting markets, Ion Protocol can accommodate many assets, including emerging or more volatile tokens, without exposing the entire market to undue risk.

## **Features of Composable Markets**

* **Risk Management:** Composable markets allow for precise risk management by adjusting the parameters such as collateralization ratios and interest rates based on asset risk profiles.
* **Enhanced Security:** By segmenting collateral asset subgroups, any adverse events affecting one market have minimal impact on others, thereby enhancing the overall security of the protocol.
* **Innovation & Efficiency:** Isolated markets provide a testing ground for new assets and strategies, fostering innovation while maintaining platform integrity.
* **Customization:** Lenders and borrowers benefit from more tailored financial products, as each market can offer conditions suited to the specific needs and risk appetites of its participants.

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

## **How It Works: Lending LSTs**

In the context of Ion Protocol, composable markets facilitate transactions where lenders supply LSTs and other ETH-backed assets like wstETH, and borrowers use liquid restaking tokens as collateral to borrow the wstETH. Here's how it works:

1. **Supplying LSTs:** Lenders contribute their LST to an isolated market, or a  combination of isolated markets. In return, they receive interest payments based on the market's borrow rates, which are determined by the supply and demand dynamics within that isolated market. This is in addition to maintaining their staking yield.
2. **Benefiting from the collateral's yield:** In markets that are profitable for borrowers, the borrow rate mo with reacts to the collateral's underlying yield because of Ion Protocol's [interest rate model](/borrowing/borrowing-mechanisms/interest-rates). The interest rate model incorporates a minimum interest rate curve to create a floor, with an uncapped upside. So if the collateral's yield increases, lenders can earn additional revenue.
3. **Collateral Specific Incentives:** Lenders will also be eligible to receive any additional incentives provided by the collateral's provider for the markets they supply to.

Isolated markets within Ion Protocol represent a significant advancement in DeFi lending, offering a balanced approach to innovation, security, and risk management. By allowing lenders to supply staked and restaked assets and borrowers to leverage liquid restaking tokens as collateral, Ion Protocol not only broadens access to capital and additional yield for stakers and restakers but also introduces a safer, more adaptable framework for generalized lending and borrowing activities.

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


# ZKML-Supported Risk Underwriting

Ion Protocol 's lending market internalizes validator demographic data via direct validator risk underwriting to determine variables such as interest rates, LTVs, and more.

## Overview

Based on the type of asset being used for slashable security, Ion uses a trustless risk engine that intakes many different variables surrounding a given validator group's historical performance and uses zero-knowledge machine learning to determine the relative associated risk of slashing attributable to the asset connected to the group.

This is facilitated within a zero-knowledge circuit, designed in collaboration with Modulus Labs, enabling the data analysis to occur off-chain but be completely verifiable on-chain. This allows Ion to execute complex compute without having to incur the gas costs associated with doing so on-chain, which are prohibitive to machine learning-based operations.

ZKML frameworks also enable the protocol to create verifiable inferences, allowing any external actor to verify that the outputted risk rating of a collateral type was correctly generated using a pre-committed model and input data.&#x20;

{% hint style="info" %}
Modulus Labs: <https://www.modulus.xyz/>

Modulus x Ion Clarity Dashboard: Coming Soon!
{% endhint %}

This risk engine allows Ion Protocol to trustlessly create dynamic interest rates that react to the changing characteristics of the validator set over time, allowing for more robust protocol health across different market conditions and more performant lending outcomes for its users.

## The Model

### Data Origin

The majority of the data was retrieved from [Beaconcha.in](https://beaconcha.in/). This consisted of income, performance, and activation historical data.

### Preprocessing

* Several oversampling techniques were used such as ADASYN, SMOTETomek, SMOTE, and SMOTEENN on the minority class (i.e. slashed validators).&#x20;
* Additionally, grid search was utilized to narrow down the best decision boundary when prioritizing AUROC. This helped to generalize the decision boundary to future test sets to test the performance of our model on the AUROC metric.&#x20;

### Training&#x20;

The model was trained over the history of the beacon chain, verifying the performance by backtesting on historical data.

### Post-Processing

After the model in production runs, it returns the probabilities of being slashed for each validator in a validator group. Then the mean of the probabilities for each protocol is taken and its average probability of slashing is found for the entire subgroup. Ion Protocol internalizes these probabilities from each provider to inform the interest rate module and parameterize the market for each collateral.


# How To Borrow On Ion

## Creating a borrow position

***

### 1. Select borrow

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

### 2. Select a market

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

### 3. Enter the deposit amount, the leverage multiplier, the max slippage. Then press the deposit button

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

## Managing a borrow position

***

### 1. Select manage position

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

### Leveraging&#x20;

***

#### 1. Select Leverage

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

#### 2. Move the leverage multiplier up to the desired multiple, select the max slippage, and click the            deposit button

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

### Deleveraging

***

### 2. Select add/manage capital

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

### Depositing additional collateral

***

#### 1. Select deposit

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

#### 2. Enter the amount to deposit then click the deposit button

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

### Repaying and Withdrawing

***

#### 1. Select repay & withdraw

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

#### 2. Enter the amount to repay, the amount to withdraw, or both then press the repay & withdraw button

#### 3. To close the entire position press the close position button

<figure><img src="/files/40fzqueBrlHd66oGoKx4" alt=""><figcaption></figcaption></figure>


# Multiplying Rewards

## Benefiting As A Borrower

One of Ion Protocol's most compelling initial use cases is its ability to enable capital efficient leveraged staking and restaking. From the beginning, borrowers in Ion Protocol will be able to collateralize their LRTs and multiply their exposure to their underlying collateral's yield and points. By removing price volatility from the equation for borrowers through the use of staking-specific underwriting, the major risks associated with compounding rewards are reduced, making it safer *and* cheaper for borrowers to increase their exposure to their collateral.

## Key Features

* **Flash Leverage:** Creates a leveraged borrowing position or deleverages a position in one-step process instead of requiring manual recursive transactions.&#x20;
* **Interest Rates:** Interest rates within Ion are parameterized via collateral type, providing each collateral asset a uniquely parameterized interest rate model. These interest rates are additionally reflexive to the yield of the underlying asset being used as collateral to minimize cost variability for borrower.
* **ZK Proof of Reserve:** Ion quantifies the creditworthiness of a collateral asset by internalizing the solvency of the asset by viewing the underlying validator reserves of the asset instead of depending on price oracles or AMM counterparty liquidity to facilitate pricinThis methodology removes volatility and price depegging as risk factors for borrowers.

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


# Borrowing Mechanisms

{% content-ref url="/pages/UtYDxRCZUTHSDsULkqyh" %}
[Flash Leverage](/borrowing/borrowing-mechanisms/flash-leverage)
{% endcontent-ref %}

{% content-ref url="/pages/Fphvvu28XOQHgngkW3bd" %}
[ZK Proof-of-Reserve](/borrowing/borrowing-mechanisms/zk-proof-of-reserve)
{% endcontent-ref %}

{% content-ref url="/pages/kLwWtjn0qTf2wA9RQ6XC" %}
[Interest Rates](/borrowing/borrowing-mechanisms/interest-rates)
{% endcontent-ref %}


# Flash Leverage

## Overview

Flash Leverage enables users to create or deleverage a borrow position in a single transaction, bypassing the need for multiple, manual recursive transactions. This mechanism leverages the concept of flash loans and swaps to provide users with a powerful tool for executing complex financial operations with unprecedented efficiency and flexibility.

### Flash Loans

Flash loans are a subtype of transactions that enable users to borrow an indeterminate amount of assets from a source of liquidity, as long as the asset is returned at the end of the transaction. If the transaction would not be able to do so, the transaction cannot execute. These transactions do not require collateral, and therefore enable novel products that improve gas efficiency and capital efficiency for users.

### Feeless Flash Loans

Ion enables users to take feeless flash loans from the protocol to effectively take uncollateralized borrows that can then be leveraged to perform complex operations (while supporting some internal products) such as position rebalancing, leveraged yield generation, and more. Because fees on borrows are only charged on a per-block basis and there is no additional fee charge incurred by the protocol, flash loans are completely free on Ion and incur no cost to the user (outside of network costs).

## Design Decisions

**Sourcing Collateral and Paying Off Debt**

1. **Leverage Creation**:
   * Collateral can be sourced via flash loans or flash swaps, either by borrowing the collateral directly or by borrowing another asset and converting it to the collateral asset.
   * Debt repayment is facilitated by borrowing from Ion, ensuring a seamless transaction process.
2. **Deleveraging**:
   * Involves sourcing the borrowed asset to repay debt and withdrawing collateral from the vault to pay it back.
   * Collateral conversion can be achieved through swaps or direct redemption with a liquid staking or restaking provider.
3. **Path Flexibility**:
   * Multiple paths are available for both leverage and deleverage strategies, allowing users to select the most efficient route based on their specific needs and market conditions.

#### Slippage Control

Slippage control mechanisms are integral to the Flash Leverage feature, ensuring that transactions are executed within acceptable risk parameters. These controls include `maxResultingDebt`, `maxCollateralToRemove`,  `sqrtPriceLimitX96`, and `maxResultingAdditionalDebt`, among others, providing users with safeguards against unfavorable market movements during the leverage or deleverage process.


# Interest Rates

## Overview

Many lending platforms currently use static governance-controlled interest rate models to determine the rate of borrowing, the lending rate, and reserve requirements. These rates are generally functions of supply and demand, reacting only to market conditions within the protocol, remaining generally unaware of any external variables related to the risk profile or unique characteristics of the deposited assets in the market.&#x20;

Such a system works well with robust and active parameterization, accommodating for a large swath of various assets. However, for validator-backed assets, certain inefficiencies can arise that lead to unideal outcomes for borrowers and lenders.

## Ion's Interest Rate Module

### Staking-sensitive Interest Rates

To minimize inefficiencies of lending rates for assets earning validator-correlated staking yield, Ion's interest rate curves are bounded relative to the current staking rate of the underlying collateral assets. Effectively, this enables borrowers who are looking to leverage on the yield of their staked assets to earn a more predictable rate while lenders can be assured that they are earning the most competitive yields possible, given the demand for the collateral asset.

<div data-full-width="false"><figure><img src="/files/3MnjSK7XCKeh1WtWHlIn" alt="" width="563"><figcaption><p>Staking-sensitive Interest Rates</p></figcaption></figure></div>

<figure><img src="/files/FZnZpH2fbCoEjIHf9P0D" alt="" width="563"><figcaption><p>Visualization of min borrow rate</p></figcaption></figure>

### Collateral-specific Interest Rates

Most lending markets currently dictate the cost of borrowing an asset based on the type of asset that is borrowed (i.e. If one deposits $USDC on Aave and borrows ETH, they will pay a different interest rate than if they were borrowing $WBTC). Since all collateral assets on Ion can only borrow ETH against their deposits, interest rates are instead priced by the type of collateral that is deposited, reflecting the risk profile of the underlying validator-backed asset.

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

### Reserve Bolstering Mechanism

Each market on Ion has a characteristic piecewise linear curve that dictates the borrow and supply rate of participants in the market. It is bounded by the staking rate of the given asset. The spread between the borrow and supply rate is what we determine as the "reserve spread." This reserve spread is used to generate a risk premium that can be used by the protocol to shore up any shortfall events that may befall the market from exogenous black swan phenomena.

## Interest Rate Math

***

### **Minimum Borrow Rate**

**minBaseRate:** one of the two points that define the slope of the minimum borrow rate curve. The y-intercept of the minimum borrow rate curve. \[per second]

**minKinkRate:** one of the two points that define the slope of the minimum borrow rate curve. \[per second]

**minAboveKinkSlope:** the slope for the minimum borrow rate curve past the optimal utilization rate.

### **Adjusted Borrow Rate**

**adjBaseRate:** one of the two points that define the slope of the adjusted borrow rate curve. The y-intercept of the adjusted borrow rate curve. \[per-second]

**adjKinkRate:** one of the two points that define the slope of the adjusted borrow rate curve. The adjusted borrow rate at the optimal utilization rate. Calculated as the APY minus the adjProfitMargin. \[per-second].

**adjAboveKinkSlope:** the slope for the adjusted borrow rate curve past the optimal utilization rate.

**adjProfitMargin:** the amount subtracted from the APY to determine the adjKinkRate. \[per-second]

### **Globals**

**reserveFactor:** The amount that determines how much of the borrow rate goes to the protocol to cover shortfall events.

**Optimal Utilization:** the utilization rate at which the collateral’s adjBorrowRate equals the adjKinkRate and where the collateral’s minBorrowRate equals the minKinkRate.

**distributionFactor:** part of calculating the utilization rate of a collateral. Defines how much of the total lender ETH supplied should be allocated to a collateral when considering the collateral’s utilization rate.

**APY:** yield of the underlying collateral that is fed in by the `YieldOracle` to allow the borrow rate to be adjusted based on the underlying staking yield. Should be **per-second** value despite the name.

**Generalized Below Kink Borrow Rate Formula**

$$
borrowRate = slope \* U\_c + baseRate
$$

**Collateral Specific Interest Rate Scales By Collateral Specific Utilization**

$$
U\_c = \frac{totalDebt}{totalETHSupply}
$$

**Adjusted Borrow Rate**

$$
adjBorrowRate = \frac{APY-adjProfitMargin-adjBaseRate}{U\_{opt}}\*U\_C + adjBaseRate
$$

**Minimum Borrow Rate**

$$
minBorrowRate = \frac{minKinkRate-minBaseRate}{U\_{opt}}\* U\_c + minBaseRate
$$

**Current Borrow Rate**

$$
realBorrowRate = max(adjBorrowRate, minBorrowRate)
$$


# ZK Proof-of-Reserve

Ion Protocol uses zero-knowledge proofs to track the balance of validators (and slashing events) directly from Ethereum's consensus layer to determine loan health.

## ZK State Proof Architecture

Ion Protocol uses ZK state proofs (proofs that trustlessly communicate information within blockchain state) to query information directly from Ethereum's consensus layer. This information is used to enable the below features:

* Price Agnostic Liquidations
* Smarter LTV Tracking
* ZKML-Supported Risk Underwriting

## Smarter LTV Tracking

On Ion, loan positions and their respective health are determined by information derived from the consensus layer. Ion uses ZK-proofs to track the balance of the validators within each different liquid staking provider or re-staking platform that is supported within the market. These balances determine the "value" that is secured within each asset deposited into the protocol.

This enables users to be assured that:

* Their LTVs won't shift as a byproduct of the secondary market price of their staked/re-staked asset.
* Their LTVs will be more representative of the value (in ETH) that their staked/re-staked asset represents.
* We can enable higher LTVs in the markets without exposing them to market manipulation attack vectors.

## Price Agnostic Liquidations

Liquidations on Ion Protocol are caused by changes in the underlying balances of the validators backing a collateral vault rather than by volatile price action.

1. Ion's Proof-of-Reserve system will monitor the relevant validators that belong to a given provider of the collateral asset that is supplied.
2. The liquidation engine is attached to feeds of beacon chain state data that update regularly, providing verifiable proofs of changes in the consensus layer state.&#x20;
3. These updates generate a proof-of-reserve for each of the collateral types in our system, which dictate the health of loans in the protocol.&#x20;
4. A loan position can only be considerable at risk of liquidation when the consensus layer balance of the validators underlying the collateral decreases (i.e. from slashing).&#x20;
5. When a loan position is liquidated, a dutch auction is initiated that scales the liquidation bonus over time, enabling a more MEV-resistant liquidation market.

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


# Liquidation Mechanism

## Liquidations

A borrower on Ion becomes liquidateable when the value of their liabilities supersedes the value of the collateral that their position is mapped to on the consensus layer (i.e. the Health Factor (HF), the ratio of the value of debt to the value of the collateral, becomes less than 1).&#x20;

$$
1 > \frac{collateralValue}{debtValue} = HF
$$

Liquidations occur in a manner mostly traditional to the status quo, where the liability is shored up by an external party and the collateral is then purchased at a discount by said party. To find out more about them go to the [Keepers](/liquidations/keepers) page in the documentation.

### Proof-of-Reserve Backed Liquidations

All liquidations within Ion occur completely independent to the secondary market price of the collateral that is deposited. Liquidations on Ion are instead initiated by changes in the underlying balances of the validators within the beacon chain. If the quantity of the underlying collateral that supports a collateral asset in the beacon chain decreases such that positions exceed their liquidation threshold, those positions will be liquidated. [See ZK-Enabled  Proof-of-Reserve](broken://pages/OUTVgkPFzJ7ELy9AOh8T) for more information about this mechanism.

It's important to note that liquidators may continue to operate on market price since they are looking for atomic profit. A position can be liquidatable on Ion (because of a sufficiently large slashing event), but the liquidation is unprofitable because the market price has fallen even further. *This is something expected and something that is OK.* This liquidation module serves as a nice-to-have where if liquidations are possible on market price, Ion will allow them.

**But the true solvency maintenance can happen deterministically.** Ion protocol, given data from the beacon chain can seize unhealthy vaults, redeem the collateral into the beacon chain, and repay the unbacked debt itself. This is possible because Ion operates on the assumption that **liquidations are not time-sensitive** the way they would be with price-based liquidations.

Once one slashing event has happened, it is unlikely that another will take place within a short time (other than the correlated slashing penalty 18 days later).

### Partial Liquidations

Unlike many lending protocols that exercise a fixed discount rate for liquidators to shore up debt in a marketplace, Ion leverages a scaling discount rate and partial liquidation mechanism that allows the reward of a liquidation to scale in accordance with the decreasing health of a position and creates a softer upper bound to the extent in which a position's collateral can be bought. This upper bound is meant to allow liquidators to pay back only the amount necessary to bring a liquidate-able position to safety without incurring additional losses for the borrower (i.e. as debt is paid back, the health factor increases). This safe level is indicated by:

$$
HF \geq 1.10
$$

### **Discount -** The benefit to the liquidator.

This represents price discrimination - in a way, it represents a pseudo dutch auction. As the health factor of the CDP decreases the discount increases.

$$
1.10 - \frac{1}{1-maxDiscount} = 0
$$

Max discount is reached at 0.091 which would mean that a position reached a 0.91 health factor.

$$
maxDiscount = 0.091
$$

## Liquidation Scenarios

1. The vault is not in a liquidatable state (healthy vault). This would lead to the liquidation failing

Then, 3 different types of liquidations depending on how unhealthy the vault is (This will be a high-level summary. See [**Deriving the Three Potential Cases** ](https://www.notion.so/Deriving-the-Three-Potential-Cases-6d017815902b4ba1b7cbdf1b5d6d2846?pvs=21)for a more detailed derivation of the math)

2. **Partial Liquidation -** There is enough collateral within the vault when sold at the current discount rate to reach the target health ratio.
3. **Dust Liquidation - While t**here is enough collateral within the vault when sold at the current discount rate to reach the target health ratio, the amount of debt being paid off would result in the total debt being below the `dust` or the smallest amount possible in a position.  In this case, force a liquidation of the full position.
4. **Protocol Liquidation -** There is not enough collateral within the vault when sold at the current discount rate to reach the target health ratio. *Assuming MEV searchers only execute profitable transactions, it's never expected for this scenario to be executed.*


# Keepers

Keepers are the lifeblood of Ion Protocol.

Keepers play a crucial role in maintaining the health of Ion Protocol by acting as incentivized parties who take advantage of arbitrage opportunities to boost the overall health of the protocol.&#x20;

Ion's mechanisms are designed to economically align the financial incentives of the keepers and the health of the protocol.&#x20;

{% hint style="info" %}
"Incentivized Parties" can include anyone from individual users to institutions who want to maintain and operate off-chain programs that target profitable on-chain opportunities.&#x20;
{% endhint %}

***

## Liquidations

When the Loan-to-Value ratio of a lending position exceeds the liquidation threshold of a given asset, a keeper can trigger its liquidation process and also participate in the auction if they wish.&#x20;

Ion Protocol takes a fixed liquidation bonus approach, meaning that all liquidators will be able to transparently preview the benefit of bringing the position's LTV back to a predefined target.

Keepers can interact with the on-chain priority queue maintained per collateral asset to effectively monitor for loans that are close to liquidation.&#x20;

Promptly triggering and participating in liquidations allows the keeper to outcompete other incentivized parties. It also helps the protocol prevent potential accumulation of bad debt in a black swan event.  &#x20;

{% hint style="info" %}
It's important to note that the value of collateral in Ion Protocol is not measured by DEX/CEX prices, but rather by the full redemption value assessed by Proof-of-Reserve Oracles that monitor the consensus layer state.&#x20;

This means liquidations do not become possible by volatile price action but rather by consensus layer slashings and penalties. See more details on the [Proof-of-Reserve Mechanism](broken://pages/OUTVgkPFzJ7ELy9AOh8T).
{% endhint %}


# LSTs

## Short Tail LSTs&#x20;

While stETH and rETH have enough liquidity to be integrated to existing lending markets, their capital efficiency is limited by the volatility of the LST price action due to external factors which are unrelated to the fundamentals of the validator set underlying the provider itself. Since Ion Protocol focuses on the validator reserves and their effectiveness in the consensus layer, a loan position's health in Ion's system is agnostic of temporary swings in price action and is not subject to noise other than that of the validator fundamentals. This goes for both the borow side of the market as well as the lender side of the market.

### Short Tail LSTs In Ion

Currently, short-tail LSTs can be used to lend in Ion's LRT/LST market. By lending in this market, lenders gain exposure to restaking without having to undertake the additional risks associated with depositing into EigenLayer and LRTs. Lenders will retain access to their staking yield while gaining access to additional yield from borrowers and additional potential liquid restaking provider incentives.

<figure><img src="/files/wfdSIWB4mu8kMYgqI7MF" alt=""><figcaption><p>Lender deposit actions.</p></figcaption></figure>

Ion can create additional markets for short-tail LSTs as well. An example of such a market would be one where lenders deposit ETH and borrowers collateralize their short-tail LSTs to borrow ETH.

## Long-Tail LSTs &#x20;

Long-tail LSTs are staked ETH tokens with low market capitalization and liquidity.&#x20;

Existing lending markets are not able to integrate these long-tail LSTs since their liquidations are entirely reliant on price oracles. With smaller liquidity comes weaker price discoverability which means price oracles can report a volatile range of prices susceptible to market manipulations. This means liquidations can occur unexpectedly, making it difficult for the lending market to protect itself from bad debt.&#x20;

However, since Ion relies on consensus layer reserves and validator activities, we can integrate LSTs regardless of their market cap, as long as their validator fundamentals are sound.&#x20;

This means Ion Protocol prioritizes liquid staking providers with differentiated technologies—ranging from distributed validator technology (DVT) to trusted execution environment (TEEs) guarantees of hardware setups—when integrating LSTs to offer stakers the unique advantage of being able to utilize long tail LSTs in DeFi.&#x20;

{% hint style="info" %}
The types of providers that Ion Protocol is able to support is also constrained by the transparency of the provider's validator set.&#x20;
{% endhint %}

### Long-Tail LSTs In Ion

It's important to note that because of Ion's composable markets, these markets could be deployed without putting the rest of the protocol at any additional risk.

### Listed Assets

<table><thead><tr><th width="284">Asset</th><th>Address</th></tr></thead><tbody><tr><td>stETH</td><td>0x35fA164735182de50811E8e2E824cFb9B6118ac2</td></tr><tr><td>wstETH</td><td>0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee</td></tr><tr><td>ETHx (Coming Soon!)</td><td>0xA35b1B31Ce002FBF2058D22F30f95D405200A15b</td></tr><tr><td>swETH (Coming Soon!)</td><td>0xf951E335afb289353dc249e82926178EaC7DEd78</td></tr></tbody></table>


# LRTs

Currently, there are no fully functional re-staking services with a complete ecosystem of re-stakers, node operators, and AVSs. However, the demand for slashable security to bootstrap other forms of Proof-of-Stake networks exists, continuously attracting more mindshare. In addition to EigenLayer, other re-staking protocols are entering the market.&#x20;

Ion Protocol offers a set of advantages to this new profile of stakers by leveraging our consensus layer risk framework to integrate restaked assets as collateral.&#x20;

## Liquid Re-staking Tokens (LRTs)&#x20;

LRTs with underlying deposits that are being restaked into similar node operator groups, validating similar AVS's, would be fungible between each other. In other words if LRTs share a similar risk profile, they can be swapped. This common risk profile is defined by the AVS's design choices as it relates to slashing + penalty rules and reward distribution logic.

Ion's risk infrastructure, designed for monitoring consensus layer activity can underwrite the complex risk and reward of restaked deposits.&#x20;

Restakers will be able to deposit their LRTs into Ion Protocol and borrow stETH and other staked and restaked assets to participate in the broader DeFi ecosystem while retaining their exposure to diverse sets of staking yield originating from AVS's. &#x20;

## LRTs In Ion

LRTs can be used as collateral on Ion to borrow. By providing LRTs as collateral, borrowers can boost their exposure to EigenLayer Points, liquid restaking provider points, and secure their position in Ion to earn boosted restaking yield once AVSs go live.&#x20;

## Listed Assets

<table><thead><tr><th width="284">Asset</th><th>Address</th></tr></thead><tbody><tr><td>eETH</td><td>0x35fA164735182de50811E8e2E824cFb9B6118ac2</td></tr><tr><td>weETH</td><td>0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee</td></tr><tr><td>rsETH</td><td>0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7</td></tr><tr><td>rswETH</td><td>0xFAe103DC9cf190eD75350761e95403b7b8aFa6c0</td></tr><tr><td>ezETH (Coming Soon)</td><td>0xbf5495Efe5DB9ce00f80364C8B423567e58d2110</td></tr><tr><td>pufETH (Coming Soon)</td><td>0xD9A442856C234a39a81a089C06451EBAa4306a72</td></tr></tbody></table>


# Exotic ETH-Backed Assets

Ion Protocol was designed to support any ETH-backed asset and value it accordingly as long as it has provable and retrievable ETH reserves. These include, but are not limited to:

* Pendle positions represented by YT, PT,  or LP tokens. Respectively, YT buyers receive underlying floating yields and points, PT buyers receive a fixed yield in exchange for foregoing all floating yields and points, and liquidity providers (LPs) receive additional yields from swap fees and Pendle incentives while retaining all points exposure.
* EigenPie isolated restaking positions where the risk is segregated to individual LSTs deposited into EigenLayer.
* Index-based LSTs catered for creating a diversified exposure to staking yield like unshETH or IndexCoop's dsETH, each backed by a basket of LST assets.&#x20;
* LP tokens backed by LSTs and ETH, including Curve and Balancer 80/20 LP tokens.&#x20;
* And more...

## Supported Exotic ETH-Backed Assets

<table><thead><tr><th width="284">Asset</th><th>Address</th></tr></thead><tbody><tr><td>Pendle (Coming Soon!)</td><td></td></tr><tr><td>EigenPie (Coming Soon!)</td><td></td></tr></tbody></table>


# Smart Contract Architecture

The team of Ion Protocol prioritizes transparency and security. View our natspec ahead which specifies the behavior and functioning of the core protocol infrastructure.


# Home

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

### [Ion Protocol](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#ion-protocol" id="ion-protocol"></a>

Ion Protocol is a decentralized money market purpose-built for all types of staked and restaked assets. Ion protocol unlocks capital efficiency for yield-bearing staking collaterals using reactive interest rates, collateral-specific utilization, and price-agnostic liquidations. Borrowers can collateralize their yield-bearing staking assets to borrow WETH, and lenders can gain exposure to the boosted staking yield generated by borrower collateral.

### [Documentation](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#documentation" id="documentation"></a>

To learn more about Ion Protocol without code, please visit:

* [Our website](https://ionprotocol.io/)
* [User Docs](https://docs.ionprotocol.io/)

To learn more about the protocol's technical details, please visit:

* [Audit Docs for Security Researchers](https://ionprotocol.notion.site/Ion-Protocol-Audit-Docs-c871ff178bf54447bd28018cd5a88f75?pvs=74)

### [Audits](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#audits" id="audits"></a>

> Please report any white hat findings for potential vulnerabilities to <security@molecularlabs.io>

* OpenZeppelin Audit December 2023
  * [Open Zepplin Audit Report](https://blog.openzeppelin.com/ion-protocol-audit)
* [Hats Finance January 2024](https://app.hats.finance/audit-competitions)
  * Regular Audit and Formal Verification Competition with Certora
  * \[Competition Completed]

To engage in conversations around Ion Protocol and the staking/restaking ecosystem, please join the [Discord](https://t.co/6np4WvIx70) channel or follow [@ionprotocol](https://twitter.com/ionprotocol) on X.

### [Usage](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#usage" id="usage"></a>

#### [Installing Dependencies](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#installing-dependencies" id="installing-dependencies"></a>

Install Bun

```
curl -fsSL https://bun.sh/install | bash
```

Run Bun install for javascript dependencies

```
bun install
```

Install jq

```
brew install jq
```

#### [Environmental Variables](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#environmental-variables" id="environmental-variables"></a>

Copy .env.example to .env and add environmental variables.

```
MAINNET_RPC_URL=https://mainnet.infura.io/v3/
MAINNET_ARCHIVE_RPC_URL= # Archive node used for creating fork environments
MAINNET_ETHERSCAN_URL=https://api.etherscan.io/api
ETHERSCAN_API_KEY=
RPC_URL= # RPC of the desired testnet used in deployment scripts
```

#### [Test](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#test" id="test"></a>

1. The test suite includes fork tests that require foundry ffi.
2. Add RPC\_URLs to the .env and run forge test with the --ffi flag.

```
forge test --ffi
```

#### [Testnet Setup](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#testnet-setup" id="testnet-setup"></a>

1. Set up anvil as a mainnet fork.

   * For the contracts using mainnet contract addresses as constants to work properly, the testnet needs to be a fork of a mainnet environment.

   ```
   anvil --fork-url $MAINNET_ARCHIVE_RPC_URL --chain-id 31337
   ```
2. Set anvil as the target RPC for the deployment script in `.env`

   ```
   # ...other environmental variables
   RPC_URL=http://localhost:8545

   ```
3. Run the testnet deployment script

   ```
   bash node.sh
   ```
4. Run the foundry script to verify that the contracts are working properly.

   ```
   forge script script/__TestFlashLeverage.s.sol --rpc-url $RPC_URL
   ```

#### [Format](broken://pages/mNviLao2U37WZ9kMMbiB) <a href="#format" id="format"></a>

```
$ forge fmt
```


# Admin


# ProxyAdmin

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/admin/ProxyAdmin.sol)

**Inherits:** Ownable2Step

Copy OpenZeppelin's `ProxyAdmin` that uses `Ownable2Step` instead of `Ownable`

*This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.*

### [State Variables](broken://pages/tXeivOIjaSmNJ7i50yT1) <a href="#state-variables" id="state-variables"></a>

#### [UPGRADE\_INTERFACE\_VERSION](broken://pages/tXeivOIjaSmNJ7i50yT1) <a href="#upgrade_interface_version" id="upgrade_interface_version"></a>

*The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address)` and `upgradeAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, while `upgradeAndCall` will invoke the `receive` function if the second argument is the empty byte string. If the getter returns `"5.0.0"`, only `upgradeAndCall(address,bytes)` is present, and the second argument must be the empty byte string if no function should be called, making it impossible to invoke the `receive` function during an upgrade.*

```
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
```

### [Functions](broken://pages/tXeivOIjaSmNJ7i50yT1) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/tXeivOIjaSmNJ7i50yT1) <a href="#constructor" id="constructor"></a>

*Sets the initial owner who can perform upgrades.*

```
constructor(address initialOwner) Ownable(initialOwner);
```

#### [upgradeAndCall](broken://pages/tXeivOIjaSmNJ7i50yT1) <a href="#upgradeandcall" id="upgradeandcall"></a>

\*Upgrades `proxy` to `implementation` and calls a function on the new implementation. See [TransparentUpgradeableProxy-\_dispatchUpgradeToAndCall](about:/src/admin/TransparentUpgradeableProxy.sol/contract.TransparentUpgradeableProxy.html#_dispatchupgradetoandcall). Requirements:

* This contract must be the admin of `proxy`.
* If `data` is empty, `msg.value` must be zero.\*

```
function upgradeAndCall(
    ITransparentUpgradeableProxy proxy,
    address implementation,
    bytes memory data
)
    public
    payable
    virtual
    onlyOwner;
```


# TransparentUpgradeableProxy

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/admin/TransparentUpgradeableProxy.sol)

**Inherits:** ERC1967Proxy

\*This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance. To avoid <https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357\\[proxy> selector clashing], which can potentially be used in an attack, this contract uses the <https://blog.openzeppelin.com/the-transparent-proxy-pattern/\\[transparent> proxy pattern]. This pattern implies two things that go hand in hand:

1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself.
2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating the proxy admin cannot fallback to the target implementation. These properties mean that the admin account can only be used for upgrading the proxy, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. For this reason, the proxy deploys an instance of {ProxyAdmin} and allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership. NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not inherit from that interface, and instead `upgradeToAndCall` is implicitly implemented using a custom dispatch mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to fully implement transparency without decoding reverts caused by selector clashes between the proxy and the implementation. NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract. IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an undesirable state where the admin slot is different from the actual admin. WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler will not check that there are no selector conflicts, due to the note above. A selector clash between any new function and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could render the `upgradeToAndCall` function inaccessible, preventing upgradeability and compromising transparency.\*

### [State Variables](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#state-variables" id="state-variables"></a>

#### [ADMIN](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#admin" id="admin"></a>

```
address private immutable ADMIN;
```

### [Functions](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#constructor" id="constructor"></a>

*Initializes an upgradeable proxy managed by an instance of a {ProxyAdmin} with an `initialOwner`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.*

```
constructor(address _logic, address initialOwner, bytes memory _data) ERC1967Proxy(_logic, _data);
```

#### [\_proxyAdmin](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#proxyadmin" id="proxyadmin"></a>

*Returns the admin of this proxy.*

```
function _proxyAdmin() internal virtual returns (address);
```

#### [\_fallback](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#fallback" id="fallback"></a>

*If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior.*

```
function _fallback() internal virtual override;
```

#### [\_dispatchUpgradeToAndCall](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#dispatchupgradetoandcall" id="dispatchupgradetoandcall"></a>

\*Upgrade the implementation of the proxy. See [ERC1967Utils-upgradeToAndCall](about:/lib/openzeppelin-contracts-upgradeable/contracts/mocks/proxy/ClashingImplementationUpgradeable.sol/contract.ClashingImplementationUpgradeable.html#upgradetoandcall). Requirements:

* If `data` is empty, `msg.value` must be zero.\*

```
function _dispatchUpgradeToAndCall() private;
```

### [Errors](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#errors" id="errors"></a>

#### [ProxyDeniedAdminAccess](broken://pages/VCPlIOjfi7XkXZYuwHxI) <a href="#proxydeniedadminaccess" id="proxydeniedadminaccess"></a>

*The proxy caller is the current admin, and can't fallback to the proxy target.*

```
error ProxyDeniedAdminAccess();
```


# ITransparentUpgradeableProxy

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/admin/TransparentUpgradeableProxy.sol)

**Inherits:** IERC1967

Copy of OpenZeppelin's `TransparentUpgradeableProxy` that uses alternative `ProxyAdmin`

*Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy} does not implement this interface directly, and its upgradeability mechanism is implemented by an internal dispatch mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not include them in the ABI so this interface must be used to interact with it.*

### [Functions](broken://pages/LijVYgtZJg87QLcMmKC8) <a href="#functions" id="functions"></a>

#### [upgradeToAndCall](broken://pages/LijVYgtZJg87QLcMmKC8) <a href="#upgradetoandcall" id="upgradetoandcall"></a>

```
function upgradeToAndCall(address, bytes calldata) external payable;
```


# Flash


# LRT


# RsEthHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/lrt/RsEthHandler.sol)

**Inherits:** UniswapFlashswapDirectMintHandler

Handler for the rsETH/wstETH market.

### [Functions](broken://pages/cS7qzNRI2OENrysmfg6r) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/cS7qzNRI2OENrysmfg6r) <a href="#constructor" id="constructor"></a>

Creates a new `RsEthHandler` instance.

```
constructor(
    uint8 _ilkIndex,
    IonPool _ionPool,
    GemJoin _gemJoin,
    Whitelist _whitelist,
    IUniswapV3Pool _wstEthUniswapPool
)
    IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist)
    UniswapFlashswapDirectMintHandler(_wstEthUniswapPool, WETH_ADDRESS);
```

**Parameters**

| Name                 | Type             | Description                                          |
| -------------------- | ---------------- | ---------------------------------------------------- |
| `_ilkIndex`          | `uint8`          | Ilk index of the pool.                               |
| `_ionPool`           | `IonPool`        | address.                                             |
| `_gemJoin`           | `GemJoin`        | address.                                             |
| `_whitelist`         | `Whitelist`      | address.                                             |
| `_wstEthUniswapPool` | `IUniswapV3Pool` | address of the wstETH/WETH Uniswap pool (0.01% fee). |

#### [\_mintCollateralAsset](broken://pages/cS7qzNRI2OENrysmfg6r) <a href="#mintcollateralasset" id="mintcollateralasset"></a>

Deposits the mint asset into the provider's collateral-asset deposit contract.

```
function _mintCollateralAsset(uint256 amountWeth) internal override returns (uint256);
```

**Parameters**

| Name         | Type      | Description |
| ------------ | --------- | ----------- |
| `amountWeth` | `uint256` |             |

#### [\_getAmountInForCollateralAmountOut](broken://pages/cS7qzNRI2OENrysmfg6r) <a href="#getamountinforcollateralamountout" id="getamountinforcollateralamountout"></a>

Calculates the amount of mint asset required to receive `amountLrt`.

*Calculates the amount of mint asset required to receive `amountLrt`.*

```
function _getAmountInForCollateralAmountOut(uint256 amountOut) internal view override returns (uint256);
```

**Parameters**

| Name        | Type      | Description |
| ----------- | --------- | ----------- |
| `amountOut` | `uint256` |             |

**Returns**

| Name     | Type      | Description                                           |
| -------- | --------- | ----------------------------------------------------- |
| `<none>` | `uint256` | Amount mint asset required for desired output. \[WAD] |


# EzEthHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/lrt/EzEthHandler.sol)

**Inherits:** UniswapFlashswapDirectMintHandlerWithDust

Handler for the ezETH collateral.

### [Functions](broken://pages/wYZsHkUN2dJEtDU9FZP3) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/wYZsHkUN2dJEtDU9FZP3) <a href="#constructor" id="constructor"></a>

Creates a new `EzEthHandler` instance.

```
constructor(
    uint8 _ilkIndex,
    IonPool _ionPool,
    GemJoin _gemJoin,
    Whitelist _whitelist,
    IUniswapV3Pool _wstEthUniswapPool
)
    IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist)
    UniswapFlashswapDirectMintHandlerWithDust(_wstEthUniswapPool, WETH_ADDRESS);
```

**Parameters**

| Name                 | Type             | Description                                          |
| -------------------- | ---------------- | ---------------------------------------------------- |
| `_ilkIndex`          | `uint8`          | Ilk index of the pool.                               |
| `_ionPool`           | `IonPool`        | address.                                             |
| `_gemJoin`           | `GemJoin`        | address.                                             |
| `_whitelist`         | `Whitelist`      | address.                                             |
| `_wstEthUniswapPool` | `IUniswapV3Pool` | address of the wstETH/WETH Uniswap pool (0.01% fee). |

#### [\_mintCollateralAsset](broken://pages/wYZsHkUN2dJEtDU9FZP3) <a href="#mintcollateralasset" id="mintcollateralasset"></a>

Deposits the mint asset into the provider's collateral-asset deposit contract.

```
function _mintCollateralAsset(uint256 amountWeth) internal override returns (uint256);
```

**Parameters**

| Name         | Type      | Description |
| ------------ | --------- | ----------- |
| `amountWeth` | `uint256` |             |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `<none>` | `uint256` | Amount of collateral asset received. \[WAD] |

#### [\_getAmountInForCollateralAmountOut](broken://pages/wYZsHkUN2dJEtDU9FZP3) <a href="#getamountinforcollateralamountout" id="getamountinforcollateralamountout"></a>

Calculates the amount of mint asset required to receive `amountLrt`.

*Calculates the amount of mint asset required to receive `amountLrt`.*

```
function _getAmountInForCollateralAmountOut(uint256 amountOut) internal view override returns (uint256 ethAmountIn);
```

**Parameters**

| Name        | Type      | Description |
| ----------- | --------- | ----------- |
| `amountOut` | `uint256` |             |

**Returns**

| Name          | Type      | Description                                           |
| ------------- | --------- | ----------------------------------------------------- |
| `ethAmountIn` | `uint256` | Amount mint asset required for desired output. \[WAD] |


# RswEthHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/lrt/RswEthHandler.sol)

**Inherits:** UniswapFlashswapDirectMintHandler

Handler for the rswETH/wstETH market.

### [Functions](broken://pages/6v3A8oKFJVfXeTsMMflN) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/6v3A8oKFJVfXeTsMMflN) <a href="#constructor" id="constructor"></a>

Creates a new `RswEthHandler` instance.

```
constructor(
    uint8 _ilkIndex,
    IonPool _ionPool,
    GemJoin _gemJoin,
    Whitelist _whitelist,
    IUniswapV3Pool _wstEthUniswapPool
)
    IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist)
    UniswapFlashswapDirectMintHandler(_wstEthUniswapPool, WETH_ADDRESS);
```

**Parameters**

| Name                 | Type             | Description                                          |
| -------------------- | ---------------- | ---------------------------------------------------- |
| `_ilkIndex`          | `uint8`          | Ilk index of the pool.                               |
| `_ionPool`           | `IonPool`        | address.                                             |
| `_gemJoin`           | `GemJoin`        | address.                                             |
| `_whitelist`         | `Whitelist`      | address.                                             |
| `_wstEthUniswapPool` | `IUniswapV3Pool` | address of the wstETH/WETH Uniswap pool (0.01% fee). |

#### [\_mintCollateralAsset](broken://pages/6v3A8oKFJVfXeTsMMflN) <a href="#mintcollateralasset" id="mintcollateralasset"></a>

Deposits the mint asset into the provider's collateral-asset deposit contract.

```
function _mintCollateralAsset(uint256 amountWeth) internal override returns (uint256);
```

**Parameters**

| Name         | Type      | Description |
| ------------ | --------- | ----------- |
| `amountWeth` | `uint256` |             |

#### [\_getAmountInForCollateralAmountOut](broken://pages/6v3A8oKFJVfXeTsMMflN) <a href="#getamountinforcollateralamountout" id="getamountinforcollateralamountout"></a>

Calculates the amount of mint asset required to receive `amountLrt`.

*Calculates the amount of mint asset required to receive `amountLrt`.*

```
function _getAmountInForCollateralAmountOut(uint256 amountOut) internal view override returns (uint256);
```

**Parameters**

| Name        | Type      | Description |
| ----------- | --------- | ----------- |
| `amountOut` | `uint256` |             |

**Returns**

| Name     | Type      | Description                                           |
| -------- | --------- | ----------------------------------------------------- |
| `<none>` | `uint256` | Amount mint asset required for desired output. \[WAD] |

#### [getEthAmountInForLstAmountOut](broken://pages/6v3A8oKFJVfXeTsMMflN) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH needed to mint the given amount of rswETH.

```
function getEthAmountInForLstAmountOut(uint256 lstAmount) external view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `lstAmount` | `uint256` | Desired output amount. \[WAD] |

#### [getLstAmountOutForEthAmountIn](broken://pages/6v3A8oKFJVfXeTsMMflN) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

Returns the amount of ETH needed to mint the given amount of rswETH.

```
function getLstAmountOutForEthAmountIn(uint256 ethAmount) external view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |


# WeEthHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/lrt/WeEthHandler.sol)

**Inherits:** UniswapFlashswapDirectMintHandler

Handler for the weETH collateral.

### [Functions](broken://pages/j4P39ZQsDZPo1SlDYIEj) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/j4P39ZQsDZPo1SlDYIEj) <a href="#constructor" id="constructor"></a>

Creates a new `WeEthHandler` instance.

```
constructor(
    uint8 _ilkIndex,
    IonPool _ionPool,
    GemJoin _gemJoin,
    Whitelist _whitelist,
    IUniswapV3Pool _wstEthUniswapPool
)
    IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist)
    UniswapFlashswapDirectMintHandler(_wstEthUniswapPool, WETH_ADDRESS);
```

**Parameters**

| Name                 | Type             | Description                                          |
| -------------------- | ---------------- | ---------------------------------------------------- |
| `_ilkIndex`          | `uint8`          | Ilk index of the pool.                               |
| `_ionPool`           | `IonPool`        | address.                                             |
| `_gemJoin`           | `GemJoin`        | address.                                             |
| `_whitelist`         | `Whitelist`      | address.                                             |
| `_wstEthUniswapPool` | `IUniswapV3Pool` | address of the wstETH/WETH Uniswap pool (0.01% fee). |

#### [\_mintCollateralAsset](broken://pages/j4P39ZQsDZPo1SlDYIEj) <a href="#mintcollateralasset" id="mintcollateralasset"></a>

Deposits the mint asset into the provider's collateral-asset deposit contract.

```
function _mintCollateralAsset(uint256 amountWeth) internal override returns (uint256);
```

**Parameters**

| Name         | Type      | Description |
| ------------ | --------- | ----------- |
| `amountWeth` | `uint256` |             |

#### [\_getAmountInForCollateralAmountOut](broken://pages/j4P39ZQsDZPo1SlDYIEj) <a href="#getamountinforcollateralamountout" id="getamountinforcollateralamountout"></a>

Calculates the amount of mint asset required to receive `amountLrt`.

*Calculates the amount of mint asset required to receive `amountLrt`.*

```
function _getAmountInForCollateralAmountOut(uint256 amountOut) internal view override returns (uint256);
```

**Parameters**

| Name        | Type      | Description |
| ----------- | --------- | ----------- |
| `amountOut` | `uint256` |             |

**Returns**

| Name     | Type      | Description                                           |
| -------- | --------- | ----------------------------------------------------- |
| `<none>` | `uint256` | Amount mint asset required for desired output. \[WAD] |


# LST


# SwEthHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/lst/SwEthHandler.sol)

**Inherits:** UniswapFlashswapHandler, BalancerFlashloanDirectMintHandler

Handler for the swETH collateral.

### [Functions](broken://pages/wnUqrsVg9BBwbQNMF0Hc) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/wnUqrsVg9BBwbQNMF0Hc) <a href="#constructor" id="constructor"></a>

Creates a new `SwEthHandler` instance.

```
constructor(
    uint8 _ilkIndex,
    IonPool _ionPool,
    GemJoin _gemJoin,
    Whitelist _whitelist,
    IUniswapV3Pool _swEthPool
)
    IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist)
    UniswapFlashswapHandler(_swEthPool, true);
```

**Parameters**

| Name         | Type             | Description                                       |
| ------------ | ---------------- | ------------------------------------------------- |
| `_ilkIndex`  | `uint8`          | of swETH.                                         |
| `_ionPool`   | `IonPool`        | `IonPool` contract address.                       |
| `_gemJoin`   | `GemJoin`        | `GemJoin` contract address associated with swETH. |
| `_whitelist` | `Whitelist`      | Address of the `Whitelist` contract.              |
| `_swEthPool` | `IUniswapV3Pool` | Address of the swETH/ETH Uniswap V3 pool.         |

#### [\_depositWethForLst](broken://pages/wnUqrsVg9BBwbQNMF0Hc) <a href="#depositwethforlst" id="depositwethforlst"></a>

Unwraps weth into eth and deposits into lst contract.

*Unwraps weth into eth and deposits into lst contract.*

```
function _depositWethForLst(uint256 amountWeth) internal override returns (uint256);
```

**Parameters**

| Name         | Type      | Description                        |
| ------------ | --------- | ---------------------------------- |
| `amountWeth` | `uint256` | The WETH amount to deposit. \[WAD] |

**Returns**

| Name     | Type      | Description                    |
| -------- | --------- | ------------------------------ |
| `<none>` | `uint256` | Amount of lst received. \[WAD] |

#### [\_getEthAmountInForLstAmountOut](broken://pages/wnUqrsVg9BBwbQNMF0Hc) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Calculates the amount of eth required to receive `amountLst`.

*Calculates the amount of eth required to receive `amountLst`.*

```
function _getEthAmountInForLstAmountOut(uint256 amountLst) internal view override returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `amountLst` | `uint256` | Desired output amount. \[WAD] |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `<none>` | `uint256` | Eth required for desired lst output. \[WAD] |


# EthXHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/lst/EthXHandler.sol)

**Inherits:** UniswapFlashloanBalancerSwapHandler, UniswapFlashswapHandler, BalancerFlashloanDirectMintHandler

Handler for the ETHx collateral.

### [State Variables](broken://pages/Oi4RbFOEG60SbEtglfdT) <a href="#state-variables" id="state-variables"></a>

#### [STADER\_DEPOSIT](broken://pages/Oi4RbFOEG60SbEtglfdT) <a href="#stader_deposit" id="stader_deposit"></a>

```
IStaderStakePoolsManager public immutable STADER_DEPOSIT;
```

### [Functions](broken://pages/Oi4RbFOEG60SbEtglfdT) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/Oi4RbFOEG60SbEtglfdT) <a href="#constructor" id="constructor"></a>

Creates a new `EthXHandler` instance.

```
constructor(
    uint8 _ilkIndex,
    IonPool _ionPool,
    GemJoin _gemJoin,
    IStaderStakePoolsManager _staderDeposit,
    Whitelist _whitelist,
    IUniswapV3Pool _wstEthUniswapPool,
    IUniswapV3Pool _ethXUniswapPool,
    bytes32 _balancerPoolId
)
    UniswapFlashloanBalancerSwapHandler(_wstEthUniswapPool, _balancerPoolId)
    IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist)
    UniswapFlashswapHandler(_ethXUniswapPool, false);
```

**Parameters**

| Name                 | Type                       | Description                                      |
| -------------------- | -------------------------- | ------------------------------------------------ |
| `_ilkIndex`          | `uint8`                    | of ETHx.                                         |
| `_ionPool`           | `IonPool`                  | `IonPool` contract address.                      |
| `_gemJoin`           | `GemJoin`                  | `GemJoin` contract address associated with ETHx. |
| `_staderDeposit`     | `IStaderStakePoolsManager` | Address for the Stader deposit contract.         |
| `_whitelist`         | `Whitelist`                | Address of the `Whitelist` contract.             |
| `_wstEthUniswapPool` | `IUniswapV3Pool`           | Address of the WSTETH/ETH Uniswap V3 pool.       |
| `_ethXUniswapPool`   | `IUniswapV3Pool`           | Address of the ETHx/ETH Uniswap V3 pool.         |
| `_balancerPoolId`    | `bytes32`                  | Balancer pool ID for the ETHx/ETH pool.          |

#### [\_depositWethForLst](broken://pages/Oi4RbFOEG60SbEtglfdT) <a href="#depositwethforlst" id="depositwethforlst"></a>

Unwraps weth into eth and deposits into lst contract.

*Unwraps weth into eth and deposits into lst contract.*

```
function _depositWethForLst(uint256 amountWeth) internal override returns (uint256);
```

**Parameters**

| Name         | Type      | Description                        |
| ------------ | --------- | ---------------------------------- |
| `amountWeth` | `uint256` | The WETH amount to deposit. \[WAD] |

**Returns**

| Name     | Type      | Description                    |
| -------- | --------- | ------------------------------ |
| `<none>` | `uint256` | Amount of lst received. \[WAD] |

#### [\_getEthAmountInForLstAmountOut](broken://pages/Oi4RbFOEG60SbEtglfdT) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Calculates the amount of eth required to receive `amountLst`.

*Calculates the amount of eth required to receive `amountLst`.*

```
function _getEthAmountInForLstAmountOut(uint256 amountLst) internal view override returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `amountLst` | `uint256` | Desired output amount. \[WAD] |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `<none>` | `uint256` | Eth required for desired lst output. \[WAD] |


# WstEthHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/lst/WstEthHandler.sol)

**Inherits:** UniswapFlashswapHandler, BalancerFlashloanDirectMintHandler

Handler for the wstETH collateral.

### [State Variables](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#state-variables" id="state-variables"></a>

#### [STETH](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#steth" id="steth"></a>

```
IERC20 constant STETH = IERC20(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84);
```

### [Functions](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#constructor" id="constructor"></a>

Creates a new `WstEthHandler` instance.

```
constructor(
    uint8 _ilkIndex,
    IonPool _ionPool,
    GemJoin _gemJoin,
    Whitelist _whitelist,
    IUniswapV3Pool _wstEthUniswapPool
)
    IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist)
    UniswapFlashswapHandler(_wstEthUniswapPool, false);
```

**Parameters**

| Name                 | Type             | Description                                        |
| -------------------- | ---------------- | -------------------------------------------------- |
| `_ilkIndex`          | `uint8`          | of wstETH.                                         |
| `_ionPool`           | `IonPool`        | `IonPool` contract address.                        |
| `_gemJoin`           | `GemJoin`        | `GemJoin` contract address associated with wstETH. |
| `_whitelist`         | `Whitelist`      | Address of the `Whitelist` contract.               |
| `_wstEthUniswapPool` | `IUniswapV3Pool` | Address of the wstETH/ETH Uniswap V3 pool.         |

#### [\_depositWethForLst](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#depositwethforlst" id="depositwethforlst"></a>

Unwraps weth into eth and deposits into lst contract.

*Unwraps weth into eth and deposits into lst contract.*

```
function _depositWethForLst(uint256 amountWeth) internal override returns (uint256);
```

**Parameters**

| Name         | Type      | Description                        |
| ------------ | --------- | ---------------------------------- |
| `amountWeth` | `uint256` | The WETH amount to deposit. \[WAD] |

**Returns**

| Name     | Type      | Description                    |
| -------- | --------- | ------------------------------ |
| `<none>` | `uint256` | Amount of lst received. \[WAD] |

#### [\_getEthAmountInForLstAmountOut](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Calculates the amount of eth required to receive `amountLst`.

*Calculates the amount of eth required to receive `amountLst`.*

```
function _getEthAmountInForLstAmountOut(uint256 amountLst) internal view override returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `amountLst` | `uint256` | Desired output amount. \[WAD] |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `<none>` | `uint256` | Eth required for desired lst output. \[WAD] |

#### [zapDepositAndBorrow](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#zapdepositandborrow" id="zapdepositandborrow"></a>

```
function zapDepositAndBorrow(
    uint256 stEthAmount,
    uint256 amountToBorrow,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof);
```

#### [zapFlashLeverageCollateral](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#zapflashleveragecollateral" id="zapflashleveragecollateral"></a>

```
function zapFlashLeverageCollateral(
    uint256 initialDeposit,
    uint256 resultingAdditionalStEthCollateral,
    uint256 maxResultingAdditionalDebt,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof);
```

#### [zapFlashLeverageWeth](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#zapflashleverageweth" id="zapflashleverageweth"></a>

```
function zapFlashLeverageWeth(
    uint256 initialDeposit,
    uint256 resultingAdditionalStEthCollateral,
    uint256 maxResultingAdditionalDebt,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof);
```

#### [zapFlashswapLeverage](broken://pages/kt8uc4W54N2PpSjXFeCG) <a href="#zapflashswapleverage" id="zapflashswapleverage"></a>

```
function zapFlashswapLeverage(
    uint256 initialDeposit,
    uint256 resultingAdditionalStEthCollateral,
    uint256 maxResultingAdditionalDebt,
    uint160 sqrtPriceLimitX96,
    uint256 deadline,
    bytes32[] calldata proof
)
    external
    checkDeadline(deadline)
    onlyWhitelistedBorrowers(proof);
```


# BalancerFlashloanDirectMintHandler constants

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/BalancerFlashloanDirectMintHandler.sol)

#### [VAULT](broken://pages/HIzSGFVsm6FdcHz3iG4v) <a href="#vault" id="vault"></a>

```
IVault constant VAULT = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
```


# BalancerFlashloanDirectMintHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/BalancerFlashloanDirectMintHandler.sol)

**Inherits:** IonHandlerBase, IFlashLoanRecipient

This contract allows for easy creation of leverage positions through Balancer flashloans and LST mints through the LST provider.

*There are a couple things to consider here from a security perspective. The first one is that the flashloan callback must only be callable from the Balancer vault. This ensures that nobody can pass arbitrary data to the callback. The second one is that the flashloan must only be initialized from this contract. This is a trickier one to enforce since Balancer flashloans are not EIP-3156 compliant and do not pass on the initiator through the callback. To get around this, an inverse reentrancy lock of sorts is used. The lock is set to 2 when a flashloan is initiated and set to 1 once the callback execution terminates. If the lock is not 2 when the callback is called, then the flashloan was not initiated by this contract and the tx is reverted. This contract currently deposits directly into LST contract 1:1. It should be noted that a more favorable trade could be possible via DEXs.*

### [State Variables](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#state-variables" id="state-variables"></a>

#### [flashloanInitiated](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#flashloaninitiated" id="flashloaninitiated"></a>

```
uint256 private flashloanInitiated = 1;
```

### [Functions](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#functions" id="functions"></a>

#### [flashLeverageCollateral](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#flashleveragecollateral" id="flashleveragecollateral"></a>

Transfer collateral from user + flashloan collateral from balancer -> deposit all collateral into `IonPool` -> borrow WETH from `IonPool` -> mint collateral using WETH -> repay Balancer flashloan.

*Code assumes Balancer flashloans remain free.*

```
function flashLeverageCollateral(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof);
```

**Parameters**

| Name                            | Type        | Description                                                                                                                                                                                                                                                             |
| ------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `initialDeposit`                | `uint256`   | in collateral terms. \[WAD]                                                                                                                                                                                                                                             |
| `resultingAdditionalCollateral` | `uint256`   | in collateral terms. \[WAD]                                                                                                                                                                                                                                             |
| `maxResultingDebt`              | `uint256`   | in WETH terms. While it is unlikely that the exchange rate changes from when a transaction is submitted versus when it is executed, it is still possible so we want to allow for a bound here, even though it doesn't pose the same level of threat as slippage. \[WAD] |
| `proof`                         | `bytes32[]` | used to validate the user is whitelisted.                                                                                                                                                                                                                               |

#### [\_flashLeverageCollateral](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#flashleveragecollateral" id="flashleveragecollateral"></a>

*Assumes that the caller has already transferred the deposit asset. Can be called internally by a wrapper that needs additional logic to obtain the LST. Ex) Zapping stEth to wstETH.*

```
function _flashLeverageCollateral(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt
)
    internal;
```

#### [flashLeverageWeth](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#flashleverageweth" id="flashleverageweth"></a>

Transfer collateral from user + flashloan WETH from balancer -> mint collateral using WETH -> deposit all collateral into `IonPool` -> borrow WETH from `IonPool` -> repay Balancer flashloan.

*Code assumes Balancer flashloans remain free.*

```
function flashLeverageWeth(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt,
    bytes32[] calldata proof
)
    external
    payable
    onlyWhitelistedBorrowers(proof);
```

**Parameters**

| Name                            | Type        | Description                                                                                                                                                                                                                                                             |
| ------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `initialDeposit`                | `uint256`   | in collateral terms. \[WAD]                                                                                                                                                                                                                                             |
| `resultingAdditionalCollateral` | `uint256`   | in collateral terms. \[WAD]                                                                                                                                                                                                                                             |
| `maxResultingDebt`              | `uint256`   | in WETH terms. While it is unlikely that the exchange rate changes from when a transaction is submitted versus when it is executed, it is still possible so we want to allow for a bound here, even though it doesn't pose the same level of threat as slippage. \[WAD] |
| `proof`                         | `bytes32[]` | used to validate the user is whitelisted.                                                                                                                                                                                                                               |

#### [\_flashLeverageWeth](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#flashleverageweth" id="flashleverageweth"></a>

*Assumes that the caller has already transferred the deposit asset. Can be called internally by a wrapper that needs additional logic to obtain the LST. Ex) Zapping stEth to wstETH.*

```
function _flashLeverageWeth(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt
)
    internal;
```

#### [receiveFlashLoan](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#receiveflashloan" id="receiveflashloan"></a>

This function is never intended to be called directly.

*Code assumes Balancer flashloans remain free. This function is intended to never be called directly. It should only be called by the Balancer VAULT during a flashloan initiated by this contract. This callback logic only handles the creation of leverage positions by minting. Since atomic withdrawals are not possible, deleveraging with a flashloan directly through an LST provider is not possible.*

```
function receiveFlashLoan(
    IERC20Balancer[] memory tokens,
    uint256[] memory amounts,
    uint256[] memory,
    bytes memory userData
)
    external
    override;
```

**Parameters**

| Name       | Type               | Description                                         |
| ---------- | ------------------ | --------------------------------------------------- |
| `tokens`   | `IERC20Balancer[]` | Array of tokens flashloaned.                        |
| `amounts`  | `uint256[]`        | Amounts flashloaned.                                |
| `<none>`   | `uint256[]`        |                                                     |
| `userData` | `bytes`            | Arbitrary data passed from initiator of flash loan. |

#### [\_depositWethForLst](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#depositwethforlst" id="depositwethforlst"></a>

Unwraps weth into eth and deposits into lst contract.

*Unwraps weth into eth and deposits into lst contract.*

```
function _depositWethForLst(uint256 amountWeth) internal virtual returns (uint256);
```

**Parameters**

| Name         | Type      | Description                        |
| ------------ | --------- | ---------------------------------- |
| `amountWeth` | `uint256` | The WETH amount to deposit. \[WAD] |

**Returns**

| Name     | Type      | Description                    |
| -------- | --------- | ------------------------------ |
| `<none>` | `uint256` | Amount of lst received. \[WAD] |

#### [\_getEthAmountInForLstAmountOut](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Calculates the amount of eth required to receive `amountLst`.

*Calculates the amount of eth required to receive `amountLst`.*

```
function _getEthAmountInForLstAmountOut(uint256 amountLst) internal view virtual returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `amountLst` | `uint256` | Desired output amount. \[WAD] |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `<none>` | `uint256` | Eth required for desired lst output. \[WAD] |

### [Errors](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#errors" id="errors"></a>

#### [ReceiveCallerNotVault](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#receivecallernotvault" id="receivecallernotvault"></a>

```
error ReceiveCallerNotVault(address unauthorizedCaller);
```

#### [FlashLoanedTooManyTokens](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#flashloanedtoomanytokens" id="flashloanedtoomanytokens"></a>

```
error FlashLoanedTooManyTokens(uint256 amountTokens);
```

#### [FlashloanedInvalidToken](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#flashloanedinvalidtoken" id="flashloanedinvalidtoken"></a>

```
error FlashloanedInvalidToken(address tokenAddress);
```

#### [ExternalBalancerFlashloanNotAllowed](broken://pages/jjlGw7th4hq2Dh0KVwV0) <a href="#externalbalancerflashloannotallowed" id="externalbalancerflashloannotallowed"></a>

```
error ExternalBalancerFlashloanNotAllowed();
```


# PtHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/PtHandler.sol)

**Inherits:** IonHandlerBase, IPMarketSwapCallback

This contract allows for easy creation of leverage positions for PT collateralized Ion markets.

### [State Variables](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#state-variables" id="state-variables"></a>

#### [MARKET](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#market" id="market"></a>

```
IPMarketV3 public immutable MARKET;
```

#### [SY](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#sy" id="sy"></a>

```
IStandardizedYield public immutable SY;
```

#### [PT](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#pt" id="pt"></a>

```
IERC20 public immutable PT;
```

#### [YT](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#yt" id="yt"></a>

```
IERC20 public immutable YT;
```

#### [flashswapInitiated](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#flashswapinitiated" id="flashswapinitiated"></a>

```
uint256 private flashswapInitiated = 1;
```

### [Functions](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#constructor" id="constructor"></a>

Creates a new `PtHandler` instance

```
constructor(
    IonPool pool,
    GemJoin join,
    Whitelist whitelist,
    IPMarketV3 _market
)
    IonHandlerBase(0, pool, join, whitelist);
```

**Parameters**

| Name        | Type         | Description                |
| ----------- | ------------ | -------------------------- |
| `pool`      | `IonPool`    | The related IonPool.       |
| `join`      | `GemJoin`    | The related GemJoin.       |
| `whitelist` | `Whitelist`  | The whitelist contract.    |
| `_market`   | `IPMarketV3` | The related Pendle market. |

#### [ptLeverage](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#ptleverage" id="ptleverage"></a>

Allows a borrower to create a leveraged position on Ion Protocol

*Transfer PT from user -> Flashswap PT token -> Deposit all PT into IonPool -> Borrow base asset -> Mint SY using base asset -> Repay Flashswap with SY.*

```
function ptLeverage(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt,
    uint256 deadline,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof)
    checkDeadline(deadline);
```

#### [swapCallback](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#swapcallback" id="swapcallback"></a>

This function should never be called directly.

*On small enough swaps, the SY to send back can be 0. This function can only be called by the market. This function can only be called by market if the swap was initiated by this contract.*

```
function swapCallback(int256 ptToAccount, int256 syToAccount, bytes calldata data) external;
```

**Parameters**

| Name          | Type     | Description                                                                                                           |
| ------------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
| `ptToAccount` | `int256` | Amount of PT sent from the perspective of the pool (negative means pool is sending, positive means user is receiving) |
| `syToAccount` | `int256` | Amount of SY sent from the perspective of the pool (negative means pool is sending, positive means user is receiving) |
| `data`        | `bytes`  | Arbitrary data passed by the market                                                                                   |

### [Errors](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#errors" id="errors"></a>

#### [InvalidGemJoin](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#invalidgemjoin" id="invalidgemjoin"></a>

```
error InvalidGemJoin(address invalidJoin);
```

#### [MarketMustBeCaller](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#marketmustbecaller" id="marketmustbecaller"></a>

```
error MarketMustBeCaller(address caller);
```

#### [ExternalFlashswapNotAllowed](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#externalflashswapnotallowed" id="externalflashswapnotallowed"></a>

```
error ExternalFlashswapNotAllowed();
```

#### [InvalidSwapDirection](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#invalidswapdirection" id="invalidswapdirection"></a>

```
error InvalidSwapDirection();
```

#### [UnexpectedSyOut](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#unexpectedsyout" id="unexpectedsyout"></a>

```
error UnexpectedSyOut(uint256 amountSyOut, uint256 expectedSyOut);
```

#### [FlashswapTooExpensive](broken://pages/JEMAIzpUvknk4JMMfRz2) <a href="#flashswaptooexpensive" id="flashswaptooexpensive"></a>

```
error FlashswapTooExpensive(uint256 amountSyIn, uint256 maxResultingDebt);
```


# IonHandlerBase

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/IonHandlerBase.sol)

The base handler contract for simpler interactions with the `IonPool` core contract. It combines various individual interactions into one compound interaction to facilitate reaching user end-goals in atomic fashion.

*To actually borrow from `IonPool`, a user must submit a "normalized" borrow amount. This contract is designed to be user-intuitive and, thus, allows a user to submit a standard desired borrow amount, which this contract will then convert into to the appropriate "normalized" borrow amount.*

### [State Variables](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#state-variables" id="state-variables"></a>

#### [BASE](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#base" id="base"></a>

```
IERC20 public immutable BASE;
```

#### [WETH](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#weth" id="weth"></a>

```
IWETH9 public immutable WETH;
```

#### [ILK\_INDEX](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#ilk_index" id="ilk_index"></a>

```
uint8 public immutable ILK_INDEX;
```

#### [POOL](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#pool" id="pool"></a>

```
IonPool public immutable POOL;
```

#### [JOIN](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#join" id="join"></a>

```
GemJoin public immutable JOIN;
```

#### [LST\_TOKEN](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#lst_token" id="lst_token"></a>

```
IERC20 public immutable LST_TOKEN;
```

#### [WHITELIST](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#whitelist" id="whitelist"></a>

```
Whitelist public immutable WHITELIST;
```

### [Functions](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#functions" id="functions"></a>

#### [checkDeadline](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#checkdeadline" id="checkdeadline"></a>

Checks if the tx is being executed before the designated deadline for execution.

*This is used to prevent txs that have sat in the mempool for too long from executing at unintended prices.*

```
modifier checkDeadline(uint256 deadline);
```

#### [onlyWhitelistedBorrowers](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#onlywhitelistedborrowers" id="onlywhitelistedborrowers"></a>

Checks if `msg.sender` is on the whitelist.

*This contract will be on the `protocolControlledWhitelist`. As such, it will validate that users are on the whitelist itself and be able to bypass the whitelist check on `IonPool`.*

```
modifier onlyWhitelistedBorrowers(bytes32[] calldata proof);
```

**Parameters**

| Name    | Type        | Description                      |
| ------- | ----------- | -------------------------------- |
| `proof` | `bytes32[]` | to validate the whitelist check. |

#### [constructor](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#constructor" id="constructor"></a>

Creates a new instance of `IonHandlerBase`

```
constructor(uint8 _ilkIndex, IonPool _ionPool, GemJoin _gemJoin, Whitelist _whitelist);
```

**Parameters**

| Name         | Type        | Description                                                    |
| ------------ | ----------- | -------------------------------------------------------------- |
| `_ilkIndex`  | `uint8`     | of the ilk for which this instance is associated with.         |
| `_ionPool`   | `IonPool`   | address of `IonPool` core contract.                            |
| `_gemJoin`   | `GemJoin`   | the `GemJoin` associated with the `ilkIndex` of this contract. |
| `_whitelist` | `Whitelist` | the `Whitelist` module address.                                |

#### [depositAndBorrow](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#depositandborrow" id="depositandborrow"></a>

Combines gem-joining and depositing collateral and then borrowing into one compound action.

```
function depositAndBorrow(
    uint256 amountCollateral,
    uint256 amountToBorrow,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof);
```

**Parameters**

| Name               | Type        | Description                                                                                  |
| ------------------ | ----------- | -------------------------------------------------------------------------------------------- |
| `amountCollateral` | `uint256`   | Amount of collateral to deposit. \[WAD]                                                      |
| `amountToBorrow`   | `uint256`   | Amount of WETH to borrow. Due to rounding, true borrow amount might be slightly less. \[WAD] |
| `proof`            | `bytes32[]` | that the user is whitelisted.                                                                |

#### [\_depositAndBorrow](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#depositandborrow" id="depositandborrow"></a>

Handles all logic to gem-join and deposit collateral, followed by a borrow. It is also possible to use this function simply to gem-join and deposit collateral atomically by setting `amountToBorrow` to 0.

```
function _depositAndBorrow(
    address vaultHolder,
    address receiver,
    uint256 amountCollateral,
    uint256 amountToBorrow,
    AmountToBorrow amountToBorrowType
)
    internal;
```

**Parameters**

| Name                 | Type             | Description                                                                                                                                                                                                                                        |
| -------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `vaultHolder`        | `address`        | The user who will be responsible for repaying debt.                                                                                                                                                                                                |
| `receiver`           | `address`        | The user who receives the borrowed funds.                                                                                                                                                                                                          |
| `amountCollateral`   | `uint256`        | to move into vault. \[WAD]                                                                                                                                                                                                                         |
| `amountToBorrow`     | `uint256`        | out of the vault. \[WAD]                                                                                                                                                                                                                           |
| `amountToBorrowType` | `AmountToBorrow` | Whether the `amountToBorrow` is a min or max. This will dictate the rounding direction when converting to normalized amount. If it is a minimum, then the rounding will be rounded up. If it is a maximum, then the rounding will be rounded down. |

#### [repayFullAndWithdraw](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#repayfullandwithdraw" id="repayfullandwithdraw"></a>

Will repay all debt and withdraw desired collateral amount. This function can also simply be used for a full repayment (which may be difficult through a direct tx to the `IonPool`) by setting `collateralToWithdraw` to 0.

*Will repay the debt belonging to `msg.sender`. This function is necessary because with `rate` updating every single block, it may be difficult to repay a full amount if a user uses the total debt from a previous block. If a user ends up repaying all but dust amounts of debt (due to a slight `rate` change), then they repayment will likely fail due to the `dust` parameter.*

```
function repayFullAndWithdraw(uint256 collateralToWithdraw) external;
```

**Parameters**

| Name                   | Type      | Description                 |
| ---------------------- | --------- | --------------------------- |
| `collateralToWithdraw` | `uint256` | in collateral terms. \[WAD] |

#### [\_getFullRepayAmount](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#getfullrepayamount" id="getfullrepayamount"></a>

Helper function to get the repayment amount for all the debt of a `user`.

*This simply emulates the rounding behaviour of the `IonPool` to arrive at an accurate value.*

```
function _getFullRepayAmount(address user) internal view returns (uint256 repayAmount, uint256 normalizedDebt);
```

**Parameters**

| Name   | Type      | Description          |
| ------ | --------- | -------------------- |
| `user` | `address` | Address of the user. |

**Returns**

| Name             | Type      | Description                                                                              |
| ---------------- | --------- | ---------------------------------------------------------------------------------------- |
| `repayAmount`    | `uint256` | Amount of base asset required to repay all debt (this mimics IonPool's behavior). \[WAD] |
| `normalizedDebt` | `uint256` | Total normalized debt held by `user`'s vault. \[WAD]                                     |

#### [repayAndWithdraw](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#repayandwithdraw" id="repayandwithdraw"></a>

Combines repaying debt and then withdrawing and gem-exitting collateral into one compound action. If repaying **all** is the intention, use `repayFullAndWithdraw()` instead to prevent tx revert from dust amounts of debt in vault.

```
function repayAndWithdraw(uint256 debtToRepay, uint256 collateralToWithdraw) external;
```

**Parameters**

| Name                   | Type      | Description                 |
| ---------------------- | --------- | --------------------------- |
| `debtToRepay`          | `uint256` | In ETH terms. \[WAD]        |
| `collateralToWithdraw` | `uint256` | In collateral terms. \[WAD] |

#### [\_repayAndWithdraw](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#repayandwithdraw" id="repayandwithdraw"></a>

Handles all logic to repay debt, followed by a collateral withdrawal and gem-exit. This function can also be used to just withdraw and gem-exit in atomic fashion by setting the `debtToRepay` to 0.

```
function _repayAndWithdraw(
    address vaultHolder,
    address receiver,
    uint256 collateralToWithdraw,
    uint256 debtToRepay
)
    internal;
```

**Parameters**

| Name                   | Type      | Description                                         |
| ---------------------- | --------- | --------------------------------------------------- |
| `vaultHolder`          | `address` | The user whose debt will be repaid.                 |
| `receiver`             | `address` | The user who receives the the withdrawn collateral. |
| `collateralToWithdraw` | `uint256` | to move into vault. \[WAD]                          |
| `debtToRepay`          | `uint256` | out of the vault. \[WAD]                            |

#### [receive](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#receive" id="receive"></a>

ETH cannot be directly sent to this contract.

*To allow unwrapping of WETH into ETH.*

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

### [Errors](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#errors" id="errors"></a>

#### [CannotSendEthToContract](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#cannotsendethtocontract" id="cannotsendethtocontract"></a>

```
error CannotSendEthToContract();
```

#### [FlashloanRepaymentTooExpensive](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#flashloanrepaymenttooexpensive" id="flashloanrepaymenttooexpensive"></a>

```
error FlashloanRepaymentTooExpensive(uint256 repaymentAmount, uint256 maxRepaymentAmount);
```

#### [TransactionDeadlineReached](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#transactiondeadlinereached" id="transactiondeadlinereached"></a>

```
error TransactionDeadlineReached(uint256 deadline);
```

### [Enums](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#enums" id="enums"></a>

#### [AmountToBorrow](broken://pages/5btX1fOyLU56sGdI4adw) <a href="#amounttoborrow" id="amounttoborrow"></a>

*During conversion from borrow amount -> "normalized" borrow amount," there is division required. In certain scenarios, it may be desirable to round up during division, in others, to round down. This enum allows a developer to indicate the rounding direction by describing the `amountToBorrow`. If it `IS_MIN`, then the final borrowed amount should be larger than `amountToBorrow` (round up), and vice versa for `IS_MAX` (round down).*

```
enum AmountToBorrow {
    IS_MIN,
    IS_MAX
}
```


# UniswapFlashloanBalancerSwapHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/UniswapFlashloanBalancerSwapHandler.sol)

**Inherits:** IUniswapV3FlashCallback, IonHandlerBase

This contract allows for easy creation and closing of leverage positions through Uniswap flashloans and LST swaps on Balancer. In terms of creation, this may be a more desirable path than directly minting from an LST provider since market prices tend to be slightly lower than provider exchange rates. DEXes also provide an avenue for atomic deleveraging since the LST -> ETH exchange can be made. NOTE: Uniswap flashloans do charge a small fee.

*Some tokens only have liquidity on Balancer. Due to the reentrancy lock on the Balancer VAULT, utilizing their free flashloan followed by a pool swap is not possible. Instead, we will take a cheap (0.01%) flashloan from the wstETH/ETH uniswap pool and perform the Balancer swap. The rETH/ETH uniswap pool could also be used since it has a 0.01% fee but it does have less liquidity.*

### [State Variables](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#state-variables" id="state-variables"></a>

#### [VAULT](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#vault" id="vault"></a>

```
IVault internal constant VAULT = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
```

#### [WETH\_IS\_TOKEN0\_ON\_UNISWAP](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#weth_is_token0_on_uniswap" id="weth_is_token0_on_uniswap"></a>

```
bool immutable WETH_IS_TOKEN0_ON_UNISWAP;
```

#### [FLASHLOAN\_POOL](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#flashloan_pool" id="flashloan_pool"></a>

```
IUniswapV3Pool public immutable FLASHLOAN_POOL;
```

#### [BALANCER\_POOL\_ID](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#balancer_pool_id" id="balancer_pool_id"></a>

```
bytes32 public immutable BALANCER_POOL_ID;
```

### [Functions](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#constructor" id="constructor"></a>

Creates a new instance of `UniswapFlashloanBalancerSwapHandler`

```
constructor(IUniswapV3Pool _flashloanPool, bytes32 _balancerPoolId);
```

**Parameters**

| Name              | Type             | Description                                            |
| ----------------- | ---------------- | ------------------------------------------------------ |
| `_flashloanPool`  | `IUniswapV3Pool` | UniswapV3 pool from which to flashloan                 |
| `_balancerPoolId` | `bytes32`        | Balancer pool identifier through which to route swaps. |

#### [flashLeverageWethAndSwap](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#flashleveragewethandswap" id="flashleveragewethandswap"></a>

Transfer collateral from user + flashloan WETH from Uniswap -> swap for collateral using WETH on Balancer pool -> deposit all collateral into `IonPool` -> borrow WETH from `IonPool` -> repay Uniswap flashloan + fee. Uniswap flashloans do incur a fee.

```
function flashLeverageWethAndSwap(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingAdditionalDebt,
    uint256 deadline,
    bytes32[] calldata proof
)
    external
    payable
    checkDeadline(deadline)
    onlyWhitelistedBorrowers(proof);
```

**Parameters**

| Name                            | Type        | Description                                                                                                                       |
| ------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `initialDeposit`                | `uint256`   | in collateral terms. \[WAD]                                                                                                       |
| `resultingAdditionalCollateral` | `uint256`   | in collateral terms. \[WAD]                                                                                                       |
| `maxResultingAdditionalDebt`    | `uint256`   | in WETH terms. This value also allows the user to control slippage of the swap. \[WAD]                                            |
| `deadline`                      | `uint256`   | timestamp for which the transaction must be executed. This prevents txs that have sat in the mempool for too long to be executed. |
| `proof`                         | `bytes32[]` | used to validate the user is whitelisted.                                                                                         |

#### [flashDeleverageWethAndSwap](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#flashdeleveragewethandswap" id="flashdeleveragewethandswap"></a>

Flashloan WETH from Uniswap -> repay debt in `IonPool` -> withdraw collateral from `IonPool` -> sell collateral for `WETH` on Balancer -> repay Uniswap flashloan + fee. Uniswap flashloans do incur a fee.

```
function flashDeleverageWethAndSwap(
    uint256 maxCollateralToRemove,
    uint256 debtToRemove,
    uint256 deadline
)
    external
    checkDeadline(deadline);
```

**Parameters**

| Name                    | Type      | Description                                                                                                                       |
| ----------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `maxCollateralToRemove` | `uint256` | The max amount of collateral user is willing to sell to repay `debtToRemove` debt. \[WAD]                                         |
| `debtToRemove`          | `uint256` | The desired amount of debt to remove. \[WAD]                                                                                      |
| `deadline`              | `uint256` | timestamp for which the transaction must be executed. This prevents txs that have sat in the mempool for too long to be executed. |

#### [uniswapV3FlashCallback](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#uniswapv3flashcallback" id="uniswapv3flashcallback"></a>

Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.

*In the implementation, you must repay the pool the tokens sent by `flash()` plus the computed fee amounts. The caller of this method must be checked to be a UniswapV3Pool. Initiator is guaranteed to be this contract since UniswapV3 pools will only call the callback on msg.sender.*

```
function uniswapV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external override;
```

**Parameters**

| Name   | Type      | Description                                                                    |
| ------ | --------- | ------------------------------------------------------------------------------ |
| `fee0` | `uint256` | The fee amount in tokenInBalancer due to the pool by the end of the flash      |
| `fee1` | `uint256` | The fee amount in tokenOutBalancer due to the pool by the end of the flash     |
| `data` | `bytes`   | Any data passed through by the caller via the IUniswapV3PoolActions#flash call |

#### [\_simulateGivenOutBalancerSwap](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#simulategivenoutbalancerswap" id="simulategivenoutbalancerswap"></a>

Simulates a Balancer swap with a desired amount of `assetOut`.

```
function _simulateGivenOutBalancerSwap(
    IVault.FundManagement memory fundManagement,
    address assetIn,
    address assetOut,
    uint256 amountOut
)
    internal
    returns (uint256);
```

**Parameters**

| Name             | Type                    | Description                                                     |
| ---------------- | ----------------------- | --------------------------------------------------------------- |
| `fundManagement` | `IVault.FundManagement` | Balancer fund management struct                                 |
| `assetIn`        | `address`               | asset to swap from                                              |
| `assetOut`       | `address`               | asset to swap to                                                |
| `amountOut`      | `uint256`               | desired amount of assetOut. Will revert if not received. \[WAD] |

### [Errors](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#errors" id="errors"></a>

#### [WethNotInPoolPair](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#wethnotinpoolpair" id="wethnotinpoolpair"></a>

```
error WethNotInPoolPair(IUniswapV3Pool pool);
```

#### [ReceiveCallerNotPool](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#receivecallernotpool" id="receivecallernotpool"></a>

```
error ReceiveCallerNotPool(address unauthorizedCaller);
```

### [Structs](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#structs" id="structs"></a>

#### [FlashCallbackData](broken://pages/9IeI3yyJEsKb3tEw4ruc) <a href="#flashcallbackdata" id="flashcallbackdata"></a>

```
struct FlashCallbackData {
    address user;
    uint256 initialDeposit;
    uint256 maxResultingAdditionalDebtOrCollateralToRemove;
    uint256 wethFlashloaned;
    uint256 amountToLeverage;
}
```


# UniswapFlashswapDirectMintHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/UniswapFlashswapDirectMintHandler.sol)

**Inherits:** IonHandlerBase, IUniswapV3SwapCallback

This contract allows for easy creation of leverge positions through a Uniswap flashswap and direct mint of the collateral from the provider. This will be used when the collateral cannot be minted directly with the base asset but can be directly minted by a token that the base asset has a UniswapV3 pool with. This contract is to be used when there exists a UniswapV3 pool between the base asset and the mint asset.

### [State Variables](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#state-variables" id="state-variables"></a>

#### [MIN\_SQRT\_RATIO](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#min_sqrt_ratio" id="min_sqrt_ratio"></a>

*The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN\_TICK)*

```
uint160 internal constant MIN_SQRT_RATIO = 4_295_128_739;
```

#### [MAX\_SQRT\_RATIO](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#max_sqrt_ratio" id="max_sqrt_ratio"></a>

*The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX\_TICK)*

```
uint160 internal constant MAX_SQRT_RATIO = 1_461_446_703_485_210_103_287_273_052_203_988_822_378_723_970_342;
```

#### [UNISWAP\_POOL](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#uniswap_pool" id="uniswap_pool"></a>

```
IUniswapV3Pool public immutable UNISWAP_POOL;
```

#### [MINT\_ASSET](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#mint_asset" id="mint_asset"></a>

```
IERC20 public immutable MINT_ASSET;
```

#### [MINT\_IS\_TOKEN0](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#mint_is_token0" id="mint_is_token0"></a>

```
bool private immutable MINT_IS_TOKEN0;
```

### [Functions](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#constructor" id="constructor"></a>

Creates a new `UniswapFlashswapDirectMintHandler` instance.

```
constructor(IUniswapV3Pool _uniswapPool, IERC20 _mintAsset);
```

**Parameters**

| Name           | Type             | Description                            |
| -------------- | ---------------- | -------------------------------------- |
| `_uniswapPool` | `IUniswapV3Pool` | Pool to perform the flashswap on.      |
| `_mintAsset`   | `IERC20`         | The asset used to mint the collateral. |

#### [flashswapAndMint](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#flashswapandmint" id="flashswapandmint"></a>

Transfer collateral from user -> Initiate flashswap between from base asset to mint asset -> Use the mint asset to mint the collateral -> Deposit all collateral into `IonPool` -> Borrow the base asset -> Close the flashswap by sending the base asset to the Uniswap pool.

```
function flashswapAndMint(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt,
    uint256 deadline,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof)
    checkDeadline(deadline);
```

**Parameters**

| Name                            | Type        | Description                               |
| ------------------------------- | ----------- | ----------------------------------------- |
| `initialDeposit`                | `uint256`   | in collateral terms. \[WAD]               |
| `resultingAdditionalCollateral` | `uint256`   | in collateral terms. \[WAD]               |
| `maxResultingDebt`              | `uint256`   | in base asset terms. \[WAD]               |
| `deadline`                      | `uint256`   |                                           |
| `proof`                         | `bytes32[]` | used to validate the user is whitelisted. |

#### [\_flashswapAndMint](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#flashswapandmint" id="flashswapandmint"></a>

```
function _flashswapAndMint(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt
)
    internal;
```

#### [\_initiateFlashSwap](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#initiateflashswap" id="initiateflashswap"></a>

Handles swap initiation logic. This function can only initiate exact output swaps.

```
function _initiateFlashSwap(
    bool zeroForOne,
    uint256 amountOut,
    address recipient,
    bytes memory data
)
    private
    returns (uint256 amountIn);
```

**Parameters**

| Name         | Type      | Description                                        |
| ------------ | --------- | -------------------------------------------------- |
| `zeroForOne` | `bool`    | Direction of the swap.                             |
| `amountOut`  | `uint256` | Desired amount of output.                          |
| `recipient`  | `address` | of output tokens.                                  |
| `data`       | `bytes`   | Arbitrary data to be passed through swap callback. |

#### [uniswapV3SwapCallback](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#uniswapv3swapcallback" id="uniswapv3swapcallback"></a>

From the perspective of the pool i.e. Negative amount means pool is sending. This function is intended to never be called directly. It should only be called by the Uniswap pool during a swap initiated by this contract.

*One thing to note from a security perspective is that the pool only calls the callback on `msg.sender`. So a theoretical attacker cannot call this function by directing where to call the callback.*

```
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external override;
```

**Parameters**

| Name           | Type     | Description      |
| -------------- | -------- | ---------------- |
| `amount0Delta` | `int256` | change in token0 |
| `amount1Delta` | `int256` | change in token1 |
| `_data`        | `bytes`  | arbitrary data   |

#### [\_mintCollateralAsset](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#mintcollateralasset" id="mintcollateralasset"></a>

Deposits the mint asset into the provider's collateral-asset deposit contract.

```
function _mintCollateralAsset(uint256 amountMintAsset) internal virtual returns (uint256);
```

**Parameters**

| Name              | Type      | Description                               |
| ----------------- | --------- | ----------------------------------------- |
| `amountMintAsset` | `uint256` | amount of "mint asset" to deposit. \[WAD] |

#### [\_getAmountInForCollateralAmountOut](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#getamountinforcollateralamountout" id="getamountinforcollateralamountout"></a>

Calculates the amount of mint asset required to receive `amountLrt`.

*Calculates the amount of mint asset required to receive `amountLrt`.*

```
function _getAmountInForCollateralAmountOut(uint256 amountLrt) internal view virtual returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `amountLrt` | `uint256` | Desired output amount. \[WAD] |

**Returns**

| Name     | Type      | Description                                           |
| -------- | --------- | ----------------------------------------------------- |
| `<none>` | `uint256` | Amount mint asset required for desired output. \[WAD] |

### [Errors](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#errors" id="errors"></a>

#### [InvalidUniswapPool](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#invaliduniswappool" id="invaliduniswappool"></a>

```
error InvalidUniswapPool();
```

#### [InvalidZeroLiquidityRegionSwap](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#invalidzeroliquidityregionswap" id="invalidzeroliquidityregionswap"></a>

```
error InvalidZeroLiquidityRegionSwap();
```

#### [CallbackOnlyCallableByPool](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#callbackonlycallablebypool" id="callbackonlycallablebypool"></a>

```
error CallbackOnlyCallableByPool(address unauthorizedCaller);
```

#### [OutputAmountNotReceived](broken://pages/LQZvqoAnideoaoR68CF9) <a href="#outputamountnotreceived" id="outputamountnotreceived"></a>

```
error OutputAmountNotReceived(uint256 amountReceived, uint256 amountRequired);
```


# UniswapFlashswapDirectMintHandlerWithDust

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/UniswapFlashswapDirectMintHandlerWithDust.sol)

**Inherits:** IonHandlerBase, IUniswapV3SwapCallback

This contract is forked off of the UniswapFlashswapDirectMintHandler, with one distinction that it handles potential dust collateral amounts that can accrue when the contract ends up minting more collateral than originally intended. This situation can occur when the user has a desired leverage amount and thus an exact resulting collateral amount, but due to rounding errors in the minting contract, the handler is forced to mint a dust amount more than the desired collateral amount. In this contract, the dust is added to the total final deposit amount and ends up in the user's vault as additional collateral. The key difference between this contract and `UniswapFlashswapDirectMintHandler` is a relaxed bound in comparing the sum of initial user deposit and additionally minted collateral to the caller's requested resulting additional collateral amount. This contract allows for easy creation of leverage positions through a Uniswap flashswap and direct mint of the collateral from the provider. This will be used when the collateral cannot be minted directly with the base asset but can be directly minted by a token that the base asset has a UniswapV3 pool with. This contract is to be used when there exists a UniswapV3 pool between the base asset and the mint asset.

### [State Variables](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#state-variables" id="state-variables"></a>

#### [MIN\_SQRT\_RATIO](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#min_sqrt_ratio" id="min_sqrt_ratio"></a>

*The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN\_TICK)*

```
uint160 internal constant MIN_SQRT_RATIO = 4_295_128_739;
```

#### [MAX\_SQRT\_RATIO](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#max_sqrt_ratio" id="max_sqrt_ratio"></a>

*The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX\_TICK)*

```
uint160 internal constant MAX_SQRT_RATIO = 1_461_446_703_485_210_103_287_273_052_203_988_822_378_723_970_342;
```

#### [UNISWAP\_POOL](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#uniswap_pool" id="uniswap_pool"></a>

```
IUniswapV3Pool public immutable UNISWAP_POOL;
```

#### [MINT\_ASSET](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#mint_asset" id="mint_asset"></a>

```
IERC20 public immutable MINT_ASSET;
```

#### [MINT\_IS\_TOKEN0](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#mint_is_token0" id="mint_is_token0"></a>

```
bool private immutable MINT_IS_TOKEN0;
```

### [Functions](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#constructor" id="constructor"></a>

Creates a new `UniswapFlashswapDirectMintHandler` instance.

```
constructor(IUniswapV3Pool _uniswapPool, IERC20 _mintAsset);
```

**Parameters**

| Name           | Type             | Description                            |
| -------------- | ---------------- | -------------------------------------- |
| `_uniswapPool` | `IUniswapV3Pool` | Pool to perform the flashswap on.      |
| `_mintAsset`   | `IERC20`         | The asset used to mint the collateral. |

#### [flashswapAndMint](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#flashswapandmint" id="flashswapandmint"></a>

Transfer collateral from user -> Initiate flashswap between from base asset to mint asset -> Use the mint asset to mint the collateral -> Deposit all collateral into `IonPool` -> Borrow the base asset -> Close the flashswap by sending the base asset to the Uniswap pool.

```
function flashswapAndMint(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt,
    uint256 deadline,
    bytes32[] calldata proof
)
    external
    onlyWhitelistedBorrowers(proof)
    checkDeadline(deadline);
```

**Parameters**

| Name                            | Type        | Description                                                     |
| ------------------------------- | ----------- | --------------------------------------------------------------- |
| `initialDeposit`                | `uint256`   | in collateral terms. \[WAD]                                     |
| `resultingAdditionalCollateral` | `uint256`   | in collateral terms. \[WAD]                                     |
| `maxResultingDebt`              | `uint256`   | in base asset terms. \[WAD]                                     |
| `deadline`                      | `uint256`   | The unix timestamp after which the uniswap transaction reverts. |
| `proof`                         | `bytes32[]` | used to validate the user is whitelisted.                       |

#### [\_flashswapAndMint](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#flashswapandmint" id="flashswapandmint"></a>

```
function _flashswapAndMint(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingDebt
)
    internal;
```

#### [\_initiateFlashSwap](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#initiateflashswap" id="initiateflashswap"></a>

Handles swap initiation logic. This function can only initiate exact output swaps.

```
function _initiateFlashSwap(
    bool zeroForOne,
    uint256 amountOut,
    address recipient,
    bytes memory data
)
    private
    returns (uint256 amountIn);
```

**Parameters**

| Name         | Type      | Description                                        |
| ------------ | --------- | -------------------------------------------------- |
| `zeroForOne` | `bool`    | Direction of the swap.                             |
| `amountOut`  | `uint256` | Desired amount of output.                          |
| `recipient`  | `address` | of output tokens.                                  |
| `data`       | `bytes`   | Arbitrary data to be passed through swap callback. |

#### [uniswapV3SwapCallback](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#uniswapv3swapcallback" id="uniswapv3swapcallback"></a>

From the perspective of the pool i.e. Negative amount means pool is sending. This function is intended to never be called directly. It should only be called by the Uniswap pool during a swap initiated by this contract.

*One thing to note from a security perspective is that the pool only calls the callback on `msg.sender`. So a theoretical attacker cannot call this function by directing where to call the callback.*

```
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external override;
```

**Parameters**

| Name           | Type     | Description      |
| -------------- | -------- | ---------------- |
| `amount0Delta` | `int256` | change in token0 |
| `amount1Delta` | `int256` | change in token1 |
| `_data`        | `bytes`  | arbitrary data   |

#### [\_mintCollateralAsset](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#mintcollateralasset" id="mintcollateralasset"></a>

Deposits the mint asset into the provider's collateral-asset deposit contract.

```
function _mintCollateralAsset(uint256 amountMintAsset) internal virtual returns (uint256);
```

**Parameters**

| Name              | Type      | Description                               |
| ----------------- | --------- | ----------------------------------------- |
| `amountMintAsset` | `uint256` | amount of "mint asset" to deposit. \[WAD] |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `<none>` | `uint256` | Amount of collateral asset received. \[WAD] |

#### [\_getAmountInForCollateralAmountOut](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#getamountinforcollateralamountout" id="getamountinforcollateralamountout"></a>

Calculates the amount of mint asset required to receive `amountLrt`.

*Calculates the amount of mint asset required to receive `amountLrt`.*

```
function _getAmountInForCollateralAmountOut(uint256 amountLrt) internal view virtual returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `amountLrt` | `uint256` | Desired output amount. \[WAD] |

**Returns**

| Name     | Type      | Description                                           |
| -------- | --------- | ----------------------------------------------------- |
| `<none>` | `uint256` | Amount mint asset required for desired output. \[WAD] |

### [Errors](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#errors" id="errors"></a>

#### [InvalidUniswapPool](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#invaliduniswappool" id="invaliduniswappool"></a>

```
error InvalidUniswapPool();
```

#### [InvalidZeroLiquidityRegionSwap](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#invalidzeroliquidityregionswap" id="invalidzeroliquidityregionswap"></a>

```
error InvalidZeroLiquidityRegionSwap();
```

#### [CallbackOnlyCallableByPool](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#callbackonlycallablebypool" id="callbackonlycallablebypool"></a>

```
error CallbackOnlyCallableByPool(address unauthorizedCaller);
```

#### [OutputAmountNotReceived](broken://pages/5sji8Kp5h0p8JfOrqZEC) <a href="#outputamountnotreceived" id="outputamountnotreceived"></a>

```
error OutputAmountNotReceived(uint256 amountReceived, uint256 amountRequired);
```


# UniswapFlashswapHandler

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/flash/UniswapFlashswapHandler.sol)

**Inherits:** IonHandlerBase, IUniswapV3SwapCallback

This contract allows for easy creation and closing of leverage positions through Uniswap flashswaps--flashloan not necessary! In terms of creation, this may be a more desirable path than directly minting from an LST provider since market prices tend to be slightly lower than provider exchange rates. DEXes also provide an avenue for atomic deleveraging since the LST -> ETH exchange can be made.

*When using the `UniswapFlashSwapHandler`, the `IUniswapV3Pool pool` fed to the constructor should be the WETH/\[LST] pool. Unlike Balancer flashloans, there is no concern here that somebody else could initiate a flashswap, then direct the callback to be called on this contract. Uniswap enforces that callback is only called on `msg.sender`.*

### [State Variables](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#state-variables" id="state-variables"></a>

#### [MIN\_SQRT\_RATIO](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#min_sqrt_ratio" id="min_sqrt_ratio"></a>

*The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN\_TICK)*

```
uint160 internal constant MIN_SQRT_RATIO = 4_295_128_739;
```

#### [MAX\_SQRT\_RATIO](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#max_sqrt_ratio" id="max_sqrt_ratio"></a>

*The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX\_TICK)*

```
uint160 internal constant MAX_SQRT_RATIO = 1_461_446_703_485_210_103_287_273_052_203_988_822_378_723_970_342;
```

#### [UNISWAP\_POOL](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#uniswap_pool" id="uniswap_pool"></a>

```
IUniswapV3Pool public immutable UNISWAP_POOL;
```

#### [WETH\_IS\_TOKEN0](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#weth_is_token0" id="weth_is_token0"></a>

```
bool private immutable WETH_IS_TOKEN0;
```

### [Functions](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#constructor" id="constructor"></a>

Creates a new `UniswapFlashswapHandler` instance.

```
constructor(IUniswapV3Pool _pool, bool _wethIsToken0);
```

**Parameters**

| Name            | Type             | Description                                   |
| --------------- | ---------------- | --------------------------------------------- |
| `_pool`         | `IUniswapV3Pool` | Pool to perform the flashswap on.             |
| `_wethIsToken0` | `bool`           | Whether WETH is token0 or token1 in the pool. |

#### [flashswapLeverage](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#flashswapleverage" id="flashswapleverage"></a>

Transfer collateral from user -> initiate swap for collateral from WETH on Uniswap (contract will receive collateral first) -> deposit all collateral into `IonPool` -> borrow WETH from `IonPool` -> complete swap by sending WETH to Uniswap.

```
function flashswapLeverage(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingAdditionalDebt,
    uint160 sqrtPriceLimitX96,
    uint256 deadline,
    bytes32[] calldata proof
)
    external
    checkDeadline(deadline)
    onlyWhitelistedBorrowers(proof);
```

**Parameters**

| Name                            | Type        | Description                                                                                                                                                                                                                 |
| ------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `initialDeposit`                | `uint256`   | in collateral terms. \[WAD]                                                                                                                                                                                                 |
| `resultingAdditionalCollateral` | `uint256`   | in collateral terms. \[WAD]                                                                                                                                                                                                 |
| `maxResultingAdditionalDebt`    | `uint256`   | in WETH terms. This value also allows the user to control slippage of the swap. \[WAD]                                                                                                                                      |
| `sqrtPriceLimitX96`             | `uint160`   | for the swap. Recommended value is the current exchange rate to ensure the swap never costs more than a direct mint would. Passing the current exchange rate means swapping beyond that point is worse than direct minting. |
| `deadline`                      | `uint256`   | timestamp for which the transaction must be executed. This prevents txs that have sat in the mempool for too long to be executed.                                                                                           |
| `proof`                         | `bytes32[]` | that the user is whitelisted.                                                                                                                                                                                               |

#### [\_flashswapLeverage](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#flashswapleverage" id="flashswapleverage"></a>

```
function _flashswapLeverage(
    uint256 initialDeposit,
    uint256 resultingAdditionalCollateral,
    uint256 maxResultingAdditionalDebt,
    uint160 sqrtPriceLimitX96
)
    internal;
```

**Parameters**

| Name                            | Type      | Description                                                                                                                |
| ------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
| `initialDeposit`                | `uint256` | in terms of swETH                                                                                                          |
| `resultingAdditionalCollateral` | `uint256` | in terms of swETH. How much collateral to add to the position in the vault.                                                |
| `maxResultingAdditionalDebt`    | `uint256` | in terms of WETH. How much debt to add to the position in the vault.                                                       |
| `sqrtPriceLimitX96`             | `uint160` | for the swap. Recommended value is the current exchange rate to ensure the swap never costs more than a direct mint would. |

#### [flashswapDeleverage](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#flashswapdeleverage" id="flashswapdeleverage"></a>

Initiate swap for WETH from collateral (contract will receive WETH first) -> repay debt on `IonPool` -> withdraw (and gem-exit) collateral from `IonPool` -> complete swap by sending collateral to Uniswap.

*The two function parameters must be chosen carefully. If `maxCollateralToRemove`'s ETH valuation were higher then `debtToRemove`, it would theoretically be possible to sell more collateral then was required for `debtToRemove` to be repaid (even if `debtToRemove` is worth nowhere near that valuation) due to the slippage of the sell. `maxCollateralToRemove` is essentially a slippage guard here.*

```
function flashswapDeleverage(
    uint256 maxCollateralToRemove,
    uint256 debtToRemove,
    uint160 sqrtPriceLimitX96,
    uint256 deadline
)
    external
    checkDeadline(deadline);
```

**Parameters**

| Name                    | Type      | Description                                                                              |
| ----------------------- | --------- | ---------------------------------------------------------------------------------------- |
| `maxCollateralToRemove` | `uint256` | he max amount of collateral user is willing to sell to repay `debtToRemove` debt. \[WAD] |
| `debtToRemove`          | `uint256` | The desired amount of debt to remove. \[WAD]                                             |
| `sqrtPriceLimitX96`     | `uint160` | for the swap. Can be set to 0 to set max bounds.                                         |
| `deadline`              | `uint256` |                                                                                          |

#### [\_initiateFlashSwap](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#initiateflashswap" id="initiateflashswap"></a>

Handles swap initiation logic. This function can only initiate exact output swaps.

```
function _initiateFlashSwap(
    bool zeroForOne,
    uint256 amountOut,
    address recipient,
    uint160 sqrtPriceLimitX96,
    FlashSwapData memory data
)
    private
    returns (uint256 amountIn);
```

**Parameters**

| Name                | Type            | Description                                        |
| ------------------- | --------------- | -------------------------------------------------- |
| `zeroForOne`        | `bool`          | Direction of the swap.                             |
| `amountOut`         | `uint256`       | Desired amount of output.                          |
| `recipient`         | `address`       | of output tokens.                                  |
| `sqrtPriceLimitX96` | `uint160`       | of the swap.                                       |
| `data`              | `FlashSwapData` | Arbitrary data to be passed through swap callback. |

#### [uniswapV3SwapCallback](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#uniswapv3swapcallback" id="uniswapv3swapcallback"></a>

From the perspective of the pool i.e. Negative amount means pool is sending. This function is intended to never be called directly. It should only be called by the Uniswap pool during a swap initiated by this contract.

*One thing to note from a security perspective is that the pool only calls the callback on `msg.sender`. So a theoretical attacker cannot call this function by directing where to call the callback.*

```
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) external override;
```

**Parameters**

| Name           | Type     | Description      |
| -------------- | -------- | ---------------- |
| `amount0Delta` | `int256` | change in token0 |
| `amount1Delta` | `int256` | change in token1 |
| `_data`        | `bytes`  | arbitrary data   |

### [Errors](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#errors" id="errors"></a>

#### [InvalidUniswapPool](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#invaliduniswappool" id="invaliduniswappool"></a>

```
error InvalidUniswapPool();
```

#### [InvalidZeroLiquidityRegionSwap](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#invalidzeroliquidityregionswap" id="invalidzeroliquidityregionswap"></a>

```
error InvalidZeroLiquidityRegionSwap();
```

#### [InvalidSqrtPriceLimitX96](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#invalidsqrtpricelimitx96" id="invalidsqrtpricelimitx96"></a>

```
error InvalidSqrtPriceLimitX96(uint160 sqrtPriceLimitX96);
```

#### [FlashswapRepaymentTooExpensive](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#flashswaprepaymenttooexpensive" id="flashswaprepaymenttooexpensive"></a>

```
error FlashswapRepaymentTooExpensive(uint256 amountIn, uint256 maxAmountIn);
```

#### [CallbackOnlyCallableByPool](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#callbackonlycallablebypool" id="callbackonlycallablebypool"></a>

```
error CallbackOnlyCallableByPool(address unauthorizedCaller);
```

#### [OutputAmountNotReceived](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#outputamountnotreceived" id="outputamountnotreceived"></a>

```
error OutputAmountNotReceived(uint256 amountReceived, uint256 amountRequired);
```

### [Structs](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#structs" id="structs"></a>

#### [FlashSwapData](broken://pages/eZGDm9udD1bgNE0bO9cg) <a href="#flashswapdata" id="flashswapdata"></a>

```
struct FlashSwapData {
    address user;
    uint256 changeInCollateralOrDebt;
    bool zeroForOne;
}
```


# Join


# GemJoin

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/join/GemJoin.sol)

**Inherits:** Ownable2Step, Pausable

Collateral deposits are held independently from the `IonPool` core contract, but credited to users through `gem` balances.

*Separating collateral deposits from the core contract allows for handling tokens with non-standard behavior, if needed. This contract implements access control through `Ownable2Step`. This contract implements pausing through OpenZeppelin's `Pausable`.*

### [State Variables](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#state-variables" id="state-variables"></a>

#### [GEM](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#gem" id="gem"></a>

```
IERC20 public immutable GEM;
```

#### [POOL](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#pool" id="pool"></a>

```
IonPool public immutable POOL;
```

#### [ILK\_INDEX](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#ilk_index" id="ilk_index"></a>

```
uint8 public immutable ILK_INDEX;
```

#### [totalGem](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#totalgem" id="totalgem"></a>

```
uint256 public totalGem;
```

### [Functions](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#constructor" id="constructor"></a>

Creates a new `GemJoin` instance.

```
constructor(IonPool _pool, IERC20 _gem, uint8 _ilkIndex, address owner) Ownable(owner);
```

**Parameters**

| Name        | Type      | Description                                                     |
| ----------- | --------- | --------------------------------------------------------------- |
| `_pool`     | `IonPool` | Address of the `IonPool` contract.                              |
| `_gem`      | `IERC20`  | ERC20 collateral to be associated with this `GemJoin` instance. |
| `_ilkIndex` | `uint8`   | of the associated collateral.                                   |
| `owner`     | `address` | Admin of the contract.                                          |

#### [pause](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#pause" id="pause"></a>

Pauses the contract.

*Pauses the contract.*

```
function pause() external onlyOwner;
```

#### [unpause](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#unpause" id="unpause"></a>

Unpauses the contract.

*Unpauses the contract.*

```
function unpause() external onlyOwner;
```

#### [join](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#join" id="join"></a>

Converts ERC20 token into gem (credit inside of the `IonPool`'s internal accounting).

*Gem will be sourced from `msg.sender` and credited to `user`.*

```
function join(address user, uint256 amount) external whenNotPaused;
```

**Parameters**

| Name     | Type      | Description           |
| -------- | --------- | --------------------- |
| `user`   | `address` | to credit the gem to. |
| `amount` | `uint256` | of gem to add. \[WAD] |

#### [exit](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#exit" id="exit"></a>

Debits gem from the `IonPool`'s internal accounting and withdraws it into ERC20 token.

*Gem will be debited from `msg.sender` and sent to `user`.*

```
function exit(address user, uint256 amount) external whenNotPaused;
```

**Parameters**

| Name     | Type      | Description                            |
| -------- | --------- | -------------------------------------- |
| `user`   | `address` | to send the withdrawn ERC20 tokens to. |
| `amount` | `uint256` | of gem to remove. \[WAD]               |

### [Errors](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#errors" id="errors"></a>

#### [Int256Overflow](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#int256overflow" id="int256overflow"></a>

```
error Int256Overflow();
```

#### [WrongIlkAddress](broken://pages/bzIaMngkv1VfH3HN1z6a) <a href="#wrongilkaddress" id="wrongilkaddress"></a>

```
error WrongIlkAddress(uint8 ilkIndex, IERC20 gem);
```


# Libraries


# LRT


# KelpDaoLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/lrt/KelpDaoLibrary.sol)

A helper library for KelpDao-related conversions.

### [Functions](broken://pages/1C6cPV7LsVzxSm4G79Ql) <a href="#functions" id="functions"></a>

#### [depositForLrt](broken://pages/1C6cPV7LsVzxSm4G79Ql) <a href="#depositforlrt" id="depositforlrt"></a>

Deposits a given amount of ETH into the rsETH Deposit Pool.

*Care should be taken to handle slippage in the calling function since this function sets NO slippage controls.*

```
function depositForLrt(IRsEth, uint256 ethAmount) internal returns (uint256 rsEthAmountToMint);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `<none>`    | `IRsEth`  |                                  |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |

**Returns**

| Name                | Type      | Description                               |
| ------------------- | --------- | ----------------------------------------- |
| `rsEthAmountToMint` | `uint256` | Amount of rsETH that was obtained. \[WAD] |

#### [getEthAmountInForLstAmountOut](broken://pages/1C6cPV7LsVzxSm4G79Ql) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH required to mint a given amount of rsETH.

```
function getEthAmountInForLstAmountOut(IRsEth, uint256 amountOut) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                    |
| ----------- | --------- | ------------------------------ |
| `<none>`    | `IRsEth`  |                                |
| `amountOut` | `uint256` | Desired output amount of rsETH |

#### [getLstAmountOutForEthAmountIn](broken://pages/1C6cPV7LsVzxSm4G79Ql) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

Calculates the amount of rsETH that will be minted for a given amount of ETH.

```
function getLstAmountOutForEthAmountIn(IRsEth, uint256 ethAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                        |
| ----------- | --------- | ---------------------------------- |
| `<none>`    | `IRsEth`  |                                    |
| `ethAmount` | `uint256` | Amount of ETH to use to mint rsETH |

**Returns**

| Name     | Type      | Description                                         |
| -------- | --------- | --------------------------------------------------- |
| `<none>` | `uint256` | Amount of outputted rsETH for a given amount of ETH |


# EtherFiLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/lrt/EtherFiLibrary.sol)

A helper library for EtherFi-related conversions.

### [Functions](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#functions" id="functions"></a>

#### [getEthAmountInForLstAmountOut](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH required to obtain a given amount of weETH.

*Performing the calculations seems to potentially yield a rounding error of 1-2 wei. In order to ensure that the correct value is returned, both versions are tested and the correct one is returned. Should a correct version ever not be found, any contracts using the library should halt execution.*

```
function getEthAmountInForLstAmountOut(IWeEth weEth, uint256 lrtAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                     |
| ----------- | --------- | ------------------------------- |
| `weEth`     | `IWeEth`  | contract.                       |
| `lrtAmount` | `uint256` | Desired amount of weETH. \[WAD] |

**Returns**

| Name     | Type      | Description                                                        |
| -------- | --------- | ------------------------------------------------------------------ |
| `<none>` | `uint256` | Amount of ETH required to obtain the given amount of weETH. \[WAD] |

#### [getLstAmountOutForEthAmountIn](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

Returns the amount of weETH that will be obtained from a given amount of ETH.

```
function getLstAmountOutForEthAmountIn(IWeEth weEth, uint256 ethAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `weEth`     | `IWeEth`  | contract.                        |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |

**Returns**

| Name     | Type      | Description                                   |
| -------- | --------- | --------------------------------------------- |
| `<none>` | `uint256` | Amount of weETH that will be obtained. \[WAD] |

#### [\_getLstAmountOutForEthAmountIn](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

An internal helper function to calculate the amount of weETH that will be obtained from a given amount of ETH.

*This is useful if the function arguments are already known so that additional external calls can be avoided.*

```
function _getLstAmountOutForEthAmountIn(
    uint256 totalPooledEther,
    uint256 totalShares,
    uint256 ethAmount
)
    internal
    pure
    returns (uint256);
```

**Parameters**

| Name               | Type      | Description                                     |
| ------------------ | --------- | ----------------------------------------------- |
| `totalPooledEther` | `uint256` | Total pooled ether in the Ether Fi pool. \[WAD] |
| `totalShares`      | `uint256` | Total amount of minted shares. \[WAD]           |
| `ethAmount`        | `uint256` | Amount of ETH to deposit. \[WAD]                |

**Returns**

| Name     | Type      | Description                                   |
| -------- | --------- | --------------------------------------------- |
| `<none>` | `uint256` | Amount of weETH that will be obtained. \[WAD] |

#### [depositForLrt](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#depositforlrt" id="depositforlrt"></a>

Deposits a given amount of ETH into the Ether Fi pool and then uses the received eETH to mint weETH.

```
function depositForLrt(IWeEth weEth, uint256 ethAmount) internal returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `weEth`     | `IWeEth`  | contract.                        |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |

**Returns**

| Name     | Type      | Description                               |
| -------- | --------- | ----------------------------------------- |
| `<none>` | `uint256` | Amount of weETH that was obtained. \[WAD] |

#### [\_sharesForAmount](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#sharesforamount" id="sharesforamount"></a>

An internal helper function to calculate the amount of shares from amount.

*Useful for avoiding external calls when the function arguments are already known.*

```
function _sharesForAmount(
    uint256 totalPooledEther,
    uint256 totalShares,
    uint256 _depositAmount
)
    internal
    pure
    returns (uint256);
```

**Parameters**

| Name               | Type      | Description                                     |
| ------------------ | --------- | ----------------------------------------------- |
| `totalPooledEther` | `uint256` | Total pooled ether in the Ether Fi pool. \[WAD] |
| `totalShares`      | `uint256` | Total amount of minted shares. \[WAD]           |
| `_depositAmount`   | `uint256` | Amount of ETH. \[WAD]                           |

#### [\_amountForShares](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#amountforshares" id="amountforshares"></a>

An internal helper function to calculate the amount from given amount of shares.

*Useful for avoiding external calls when the function arguments are already known.*

```
function _amountForShares(
    uint256 totalPooledEther,
    uint256 totalShares,
    uint256 _shares
)
    internal
    pure
    returns (uint256);
```

**Parameters**

| Name               | Type      | Description                                     |
| ------------------ | --------- | ----------------------------------------------- |
| `totalPooledEther` | `uint256` | Total pooled ether in the Ether Fi pool. \[WAD] |
| `totalShares`      | `uint256` | Total amount of minted shares. \[WAD]           |
| `_shares`          | `uint256` | Amount of shares. \[WAD]                        |

### [Errors](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#errors" id="errors"></a>

#### [NoAmountInFound](broken://pages/881nUPx6TcLHioRNL9NA) <a href="#noamountinfound" id="noamountinfound"></a>

```
error NoAmountInFound();
```


# RestakedSwellLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/lrt/RestakedSwellLibrary.sol)

A helper library for restaked Swell-related conversions.

### [Functions](broken://pages/GDTZU52QY2AKPZgva5ly) <a href="#functions" id="functions"></a>

#### [getEthAmountInForLstAmountOut](broken://pages/GDTZU52QY2AKPZgva5ly) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH needed to mint the given amount of rswETH.

```
function getEthAmountInForLstAmountOut(IRswEth rswEth, uint256 lstAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `rswEth`    | `IRswEth` | address.                      |
| `lstAmount` | `uint256` | Desired output amount. \[WAD] |

#### [getLstAmountOutForEthAmountIn](broken://pages/GDTZU52QY2AKPZgva5ly) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

Returns the amount of ETH needed to mint the given amount of rswETH.

```
function getLstAmountOutForEthAmountIn(IRswEth rswEth, uint256 ethAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `rswEth`    | `IRswEth` | address.                         |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |

#### [depositForLrt](broken://pages/GDTZU52QY2AKPZgva5ly) <a href="#depositforlrt" id="depositforlrt"></a>

Deposits ETH into the rswETH contract and returns the amount of rswETH received.

```
function depositForLrt(IRswEth rswEth, uint256 ethAmount) internal returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `rswEth`    | `IRswEth` | address.                         |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |


# RenzoLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/lrt/RenzoLibrary.sol)

A helper library for Renzo-related conversions.

\*The behaviour in minting ezETH is quite strange, so for the sake of the maintenance of this code, we document the behaviour at block 19387902. The following function is invoked to calculate the amount of ezETH to mint given an `ethAmount` to deposit: `calculateMintAmount(totalTVL, ethAmount, totalSupply)`.

```
function calculateMintAmount(uint256 _currentValueInProtocol, uint256 _newValueAdded, uint256 _existingEzETHSupply)
external pure returns (uint256) {
...
// Calculate the percentage of value after the deposit
uint256 inflationPercentaage = SCALE_FACTOR * _newValueAdded / (_currentValueInProtocol + _newValueAdded);
// Calculate the new supply
uint256 newEzETHSupply = (_existingEzETHSupply * SCALE_FACTOR) / (SCALE_FACTOR - inflationPercentaage);
// Subtract the old supply from the new supply to get the amount to mint
uint256 mintAmount = newEzETHSupply - _existingEzETHSupply;
if(mintAmount == 0) revert InvalidTokenAmount();
...
}
```

The first thing to note here is the increments by which you can mint ezETH. To mint a non-zero amount of ezETH, `newEzETHSupply` must not be equal to `_existingEzETHSupply`. For this to happen, `inflationPercentage` must be non-zero. At block 19387902, the `totalTVL` or (`_currentValueInProtocol`) is `227527390751192406096375`. So the smallest value for `_newValueAdded` (or the ETH deposited) that will produce an `inflationPercentage` of 1 is `227528`. Any deposit amount less than this will not mint any ezETH (in fact, it will revert). This is the first piece of strange behaviour; the minimum amount to deposit to mint any ezETH is `227528` wei. This will mint `226219` ezETH. The second piece of strange behaviour can be noted when increasing the deposit. If it is increased from `227528` to `227529`, the amount of ezETH minted REMAINS `226219`. This is the case all the way until `455054`. This means that if a user deposits anywhere between `226219` and `455054` wei, they will mint `226219` ezETH. This is because the `inflationPercentage` remains at 1. At `455055` wei, the `inflationPercentage` finally increases to 2, and the amount of ezETH minted increases to `452438`. This also means that it is impossible to mint an ezETH value between `226219` and `452438` wei even though the transfer granularity remains 1 wei. One side effect of this second behaviour is the cost of acquisition can be optimized. It's a really small difference but to acquire `226219` ezETH a user should pay `227528` wei instead of any other value between `227528` and `455054` wei. We will call a mintable amount of ezETH a "mintable amount" (recall that at block 19387902, a user cannot mint between `226219` and `452438` ezETH). So `226219` and `452438` are mint amounts. We will call the range of values that produce the same amount of ezETH a "mint range". The mint range for `0` ezETH is `0` to `227527` wei and the mint range for `226219` ezETH is `227528` to `455054` wei.\*

### [Functions](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#functions" id="functions"></a>

#### [getEthAmountInForLstAmountOut](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH required to mint at least `minAmountOut` ezETH and the actual amount of ezETH minted when depositing that amount of ETH.

*The goal here is to mint at least `minAmountOut` ezETH. So first, we must find the "mintable amount" right above `minAmountOut`. This ensures that we mint at least `minAmountOut`. Then we find the minimum amount of ETH required to mint that "mintable amount". Essentially, we want to find the lower bound of the "mint range" of the "mintable amount" right above `minAmountOut`. There exists an edge case where `minAmountOut` is an exact "mintable amount". Continuing with the example from block 19387902, if `minAmountOut` is `226218`, the `inflationPercentage` below would be 0. It would then be incremented to 1 and then when deriving the true `amountOut` from the incremented `inflationPercentage`, it would get `amountOut = 226219`. However, if `minAmountOut` is `226219`, the `inflationPercentage` below would be 1 and it would be incremented to 2. Then, true `amountOut` would then be `452438` which is unnecessarily minting more when the initial "mintable amount" was perfect. In this case, the inflationPercentage that the `_calculateDepositAmount`'s `ethAmountIn` maps to may not be the most optimal and users may incur the cost of paying extra dust for the same mint amount. However, we have empirically observed via fuzzing that 90% of the time, the ethAmountIn calculated through this function will be the most optimal eth amount in, and one less the `ethAmountIn` will result in a mint amount out lower than the minimum.*

```
function getEthAmountInForLstAmountOut(uint256 minAmountOut)
    internal
    view
    returns (uint256 ethAmountIn, uint256 amountOut);
```

**Parameters**

| Name           | Type      | Description                     |
| -------------- | --------- | ------------------------------- |
| `minAmountOut` | `uint256` | Minimum amount of ezETH to mint |

**Returns**

| Name          | Type      | Description                                                |
| ------------- | --------- | ---------------------------------------------------------- |
| `ethAmountIn` | `uint256` | Amount of ETH required to mint the desired amount of ezETH |
| `amountOut`   | `uint256` | Actual output amount of ezETH                              |

#### [getLstAmountOutForEthAmountIn](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

Returns the amount of ezETH that will be minted with the provided `ethAmount` and the optimal amount of ETH to acquire the same amount of ezETH.

```
function getLstAmountOutForEthAmountIn(uint256 ethAmount)
    internal
    view
    returns (uint256 amount, uint256 optimalAmount);
```

**Parameters**

| Name        | Type      | Description                  |
| ----------- | --------- | ---------------------------- |
| `ethAmount` | `uint256` | amount of eth to use to mint |

**Returns**

| Name            | Type      | Description                                                              |
| --------------- | --------- | ------------------------------------------------------------------------ |
| `amount`        | `uint256` | of ezETH minted                                                          |
| `optimalAmount` | `uint256` | optimal amount of ETH required to mint (at the bottom of the mint range) |

#### [depositForLrt](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#depositforlrt" id="depositforlrt"></a>

```
function depositForLrt(uint256 ethAmount) internal returns (uint256 ezEthAmountToMint);
```

#### [\_calculateDepositAmount](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#calculatedepositamount" id="calculatedepositamount"></a>

Returns the amount of ETH required to mint amountOut ezETH.

*This function does NOT account for the rounding errors in the ezETH. It simply performs the minting calculation in reverse. To use this function properly, `amountOut` should be a "mintable amount" (an amount of ezETH that is actually possible to mint).*

```
function _calculateDepositAmount(
    uint256 _currentValueInProtocol,
    uint256 _existingEzETHSupply,
    uint256 amountOut
)
    private
    pure
    returns (uint256);
```

**Parameters**

| Name                      | Type      | Description                      |
| ------------------------- | --------- | -------------------------------- |
| `_currentValueInProtocol` | `uint256` | Total TVL in the system.         |
| `_existingEzETHSupply`    | `uint256` | Total supply of ezETH.           |
| `amountOut`               | `uint256` | Desired amount of ezETH to mint. |

#### [\_calculateMintAmount](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#calculatemintamount" id="calculatemintamount"></a>

Calculates the amount of ezETH that will be minted.

*This function emulates the calculations in the Renzo contract (including rounding errors).*

```
function _calculateMintAmount(
    uint256 _currentValueInProtocol,
    uint256 _existingEzETHSupply,
    uint256 _newValueAdded
)
    private
    pure
    returns (uint256);
```

**Parameters**

| Name                      | Type      | Description                             |
| ------------------------- | --------- | --------------------------------------- |
| `_currentValueInProtocol` | `uint256` | The TVL in the protocol (in ETH terms). |
| `_existingEzETHSupply`    | `uint256` | The current supply of ezETH.            |
| `_newValueAdded`          | `uint256` | The amount of ETH to deposit.           |

**Returns**

| Name     | Type      | Description                              |
| -------- | --------- | ---------------------------------------- |
| `<none>` | `uint256` | The amount of ezETH that will be minted. |

### [Errors](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#errors" id="errors"></a>

#### [InvalidAmountOut](broken://pages/FAKKsQTxX2ZoXCYuM0Q2) <a href="#invalidamountout" id="invalidamountout"></a>

```
error InvalidAmountOut(uint256 amountOut);
```


# LST


# StaderLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/lst/StaderLibrary.sol)

A helper library for Stader-related conversions.

### [Functions](broken://pages/sbdPc8M50YEfrj0fH1Wt) <a href="#functions" id="functions"></a>

#### [getEthAmountInForLstAmountOut](broken://pages/sbdPc8M50YEfrj0fH1Wt) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH needed to mint the given amount of ETHx.

```
function getEthAmountInForLstAmountOut(
    IStaderStakePoolsManager staderDeposit,
    uint256 lstAmount
)
    internal
    view
    returns (uint256);
```

**Parameters**

| Name            | Type                       | Description                   |
| --------------- | -------------------------- | ----------------------------- |
| `staderDeposit` | `IStaderStakePoolsManager` | address.                      |
| `lstAmount`     | `uint256`                  | Desired output amount. \[WAD] |

#### [getLstAmountOutForEthAmountIn](broken://pages/sbdPc8M50YEfrj0fH1Wt) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

Returns the amount of ETHx that can be minted with the given amount of ETH.

```
function getLstAmountOutForEthAmountIn(
    IStaderStakePoolsManager staderDeposit,
    uint256 ethAmount
)
    internal
    view
    returns (uint256);
```

**Parameters**

| Name            | Type                       | Description                      |
| --------------- | -------------------------- | -------------------------------- |
| `staderDeposit` | `IStaderStakePoolsManager` | address.                         |
| `ethAmount`     | `uint256`                  | Amount of ETH to deposit. \[WAD] |

#### [depositForLst](broken://pages/sbdPc8M50YEfrj0fH1Wt) <a href="#depositforlst" id="depositforlst"></a>

Deposits ETH into the stader deposit contract and returns the amount of ETHx received.

```
function depositForLst(IStaderStakePoolsManager staderDeposit, uint256 ethAmount) internal returns (uint256);
```

**Parameters**

| Name            | Type                       | Description                      |
| --------------- | -------------------------- | -------------------------------- |
| `staderDeposit` | `IStaderStakePoolsManager` | address.                         |
| `ethAmount`     | `uint256`                  | Amount of ETH to deposit. \[WAD] |

#### [depositForLst](broken://pages/sbdPc8M50YEfrj0fH1Wt) <a href="#depositforlst-1" id="depositforlst-1"></a>

Deposits ETH into the stader deposit contract and returns the amount of ETHx received. This function parameterizes the address to receive the ETHx.

```
function depositForLst(
    IStaderStakePoolsManager staderDeposit,
    uint256 ethAmount,
    address receiver
)
    internal
    returns (uint256);
```

**Parameters**

| Name            | Type                       | Description                      |
| --------------- | -------------------------- | -------------------------------- |
| `staderDeposit` | `IStaderStakePoolsManager` | address.                         |
| `ethAmount`     | `uint256`                  | Amount of ETH to deposit. \[WAD] |
| `receiver`      | `address`                  | to receive the ETHx.             |


# LidoLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/lst/LidoLibrary.sol)

A helper library for Lido-related conversions.

### [Functions](broken://pages/JRYXE5sigVuPsKAz6HHU) <a href="#functions" id="functions"></a>

#### [getEthAmountInForLstAmountOut](broken://pages/JRYXE5sigVuPsKAz6HHU) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH needed to mint the given amount of wstETH.

```
function getEthAmountInForLstAmountOut(IWstEth wstEth, uint256 lstAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `wstEth`    | `IWstEth` | address.                      |
| `lstAmount` | `uint256` | Desired output amount. \[WAD] |

#### [getLstAmountOutForEthAmountIn](broken://pages/JRYXE5sigVuPsKAz6HHU) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

Returns the amount of wstETH that can be minted with the given amount of ETH.

```
function getLstAmountOutForEthAmountIn(IWstEth wstEth, uint256 ethAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `wstEth`    | `IWstEth` | address.                         |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |

#### [depositForLst](broken://pages/JRYXE5sigVuPsKAz6HHU) <a href="#depositforlst" id="depositforlst"></a>

Deposits ETH into the wstETH contract and returns the amount of wstETH received.

```
function depositForLst(IWstEth wstEth, uint256 ethAmount) internal returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `wstEth`    | `IWstEth` | address.                         |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |

### [Errors](broken://pages/JRYXE5sigVuPsKAz6HHU) <a href="#errors" id="errors"></a>

#### [WstEthDepositFailed](broken://pages/JRYXE5sigVuPsKAz6HHU) <a href="#wstethdepositfailed" id="wstethdepositfailed"></a>

```
error WstEthDepositFailed();
```


# SwellLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/lst/SwellLibrary.sol)

A helper library for Swell-related conversions.

### [Functions](broken://pages/j8AWIqKFLow6OX7lT0vT) <a href="#functions" id="functions"></a>

#### [getEthAmountInForLstAmountOut](broken://pages/j8AWIqKFLow6OX7lT0vT) <a href="#getethamountinforlstamountout" id="getethamountinforlstamountout"></a>

Returns the amount of ETH needed to mint the given amount of swETH.

```
function getEthAmountInForLstAmountOut(ISwEth swEth, uint256 lstAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                   |
| ----------- | --------- | ----------------------------- |
| `swEth`     | `ISwEth`  | address.                      |
| `lstAmount` | `uint256` | Desired output amount. \[WAD] |

#### [getLstAmountOutForEthAmountIn](broken://pages/j8AWIqKFLow6OX7lT0vT) <a href="#getlstamountoutforethamountin" id="getlstamountoutforethamountin"></a>

```
function getLstAmountOutForEthAmountIn(ISwEth swEth, uint256 ethAmount) internal view returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `swEth`     | `ISwEth`  | address.                         |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |

#### [depositForLst](broken://pages/j8AWIqKFLow6OX7lT0vT) <a href="#depositforlst" id="depositforlst"></a>

Deposits ETH into the swETH contract and returns the amount of swETH received.

```
function depositForLst(ISwEth swEth, uint256 ethAmount) internal returns (uint256);
```

**Parameters**

| Name        | Type      | Description                      |
| ----------- | --------- | -------------------------------- |
| `swEth`     | `ISwEth`  | address.                         |
| `ethAmount` | `uint256` | Amount of ETH to deposit. \[WAD] |


# math


# WadRayMath constants

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/math/WadRayMath.sol)

#### [WAD](broken://pages/Qp7LiLGXyYeTSWBFigLf) <a href="#wad" id="wad"></a>

```
uint256 constant WAD = 1e18;
```

#### [RAY](broken://pages/Qp7LiLGXyYeTSWBFigLf) <a href="#ray" id="ray"></a>

```
uint256 constant RAY = 1e27;
```

#### [RAD](broken://pages/Qp7LiLGXyYeTSWBFigLf) <a href="#rad" id="rad"></a>

```
uint256 constant RAD = 1e45;
```


# WadRayMath

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/math/WadRayMath.sol)

This library provides mul/div\[up/down] functionality for WAD, RAY and RAD with phantom overflow protection as well as scale\[up/down] functionality for WAD, RAY and RAD.

### [Functions](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#functions" id="functions"></a>

#### [wadMulDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#wadmuldown" id="wadmuldown"></a>

Multiplies two WAD numbers and returns the result as a WAD rounding the result down.

```
function wadMulDown(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description   |
| ---- | --------- | ------------- |
| `a`  | `uint256` | Multiplicand. |
| `b`  | `uint256` | Multiplier.   |

#### [wadMulUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#wadmulup" id="wadmulup"></a>

Multiplies two WAD numbers and returns the result as a WAD rounding the result up.

```
function wadMulUp(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description   |
| ---- | --------- | ------------- |
| `a`  | `uint256` | Multiplicand. |
| `b`  | `uint256` | Multiplier.   |

#### [wadDivDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#waddivdown" id="waddivdown"></a>

Divides two WAD numbers and returns the result as a WAD rounding the result down.

```
function wadDivDown(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description |
| ---- | --------- | ----------- |
| `a`  | `uint256` | Dividend.   |
| `b`  | `uint256` | Divisor.    |

#### [wadDivUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#waddivup" id="waddivup"></a>

Divides two WAD numbers and returns the result as a WAD rounding the result up.

```
function wadDivUp(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description |
| ---- | --------- | ----------- |
| `a`  | `uint256` | Dividend.   |
| `b`  | `uint256` | Divisor.    |

#### [rayMulDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#raymuldown" id="raymuldown"></a>

Multiplies two RAY numbers and returns the result as a RAY rounding the result down.

```
function rayMulDown(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description  |
| ---- | --------- | ------------ |
| `a`  | `uint256` | Multiplicand |
| `b`  | `uint256` | Multiplier   |

#### [rayMulUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#raymulup" id="raymulup"></a>

Multiplies two RAY numbers and returns the result as a RAY rounding the result up.

```
function rayMulUp(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description  |
| ---- | --------- | ------------ |
| `a`  | `uint256` | Multiplicand |
| `b`  | `uint256` | Multiplier   |

#### [rayDivDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#raydivdown" id="raydivdown"></a>

Divides two RAY numbers and returns the result as a RAY rounding the result down.

```
function rayDivDown(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description |
| ---- | --------- | ----------- |
| `a`  | `uint256` | Dividend    |
| `b`  | `uint256` | Divisor     |

#### [rayDivUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#raydivup" id="raydivup"></a>

Divides two RAY numbers and returns the result as a RAY rounding the result up.

```
function rayDivUp(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description |
| ---- | --------- | ----------- |
| `a`  | `uint256` | Dividend    |
| `b`  | `uint256` | Divisor     |

#### [radMulDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#radmuldown" id="radmuldown"></a>

Multiplies two RAD numbers and returns the result as a RAD rounding the result down.

```
function radMulDown(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description  |
| ---- | --------- | ------------ |
| `a`  | `uint256` | Multiplicand |
| `b`  | `uint256` | Multiplier   |

#### [radMulUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#radmulup" id="radmulup"></a>

Multiplies two RAD numbers and returns the result as a RAD rounding the result up.

```
function radMulUp(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description  |
| ---- | --------- | ------------ |
| `a`  | `uint256` | Multiplicand |
| `b`  | `uint256` | Multiplier   |

#### [radDivDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#raddivdown" id="raddivdown"></a>

Divides two RAD numbers and returns the result as a RAD rounding the result down.

```
function radDivDown(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description |
| ---- | --------- | ----------- |
| `a`  | `uint256` | Dividend    |
| `b`  | `uint256` | Divisor     |

#### [radDivUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#raddivup" id="raddivup"></a>

Divides two RAD numbers and returns the result as a RAD rounding the result up.

```
function radDivUp(uint256 a, uint256 b) internal pure returns (uint256);
```

**Parameters**

| Name | Type      | Description |
| ---- | --------- | ----------- |
| `a`  | `uint256` | Dividend    |
| `b`  | `uint256` | Divisor     |

#### [scaleUpToWad](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaleuptowad" id="scaleuptowad"></a>

Scales a value up from WAD. NOTE: The `scale` value must be less than 18.

```
function scaleUpToWad(uint256 value, uint256 scale) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description            |
| ------- | --------- | ---------------------- |
| `value` | `uint256` | to scale up.           |
| `scale` | `uint256` | of the returned value. |

#### [scaleUpToRay](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaleuptoray" id="scaleuptoray"></a>

Scales a value up from RAY. NOTE: The `scale` value must be less than 27.

```
function scaleUpToRay(uint256 value, uint256 scale) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description            |
| ------- | --------- | ---------------------- |
| `value` | `uint256` | to scale up.           |
| `scale` | `uint256` | of the returned value. |

#### [scaleUpToRad](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaleuptorad" id="scaleuptorad"></a>

Scales a value up from RAD. NOTE: The `scale` value must be less than 45.

```
function scaleUpToRad(uint256 value, uint256 scale) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description            |
| ------- | --------- | ---------------------- |
| `value` | `uint256` | to scale up.           |
| `scale` | `uint256` | of the returned value. |

#### [scaleDownToWad](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaledowntowad" id="scaledowntowad"></a>

Scales a value down to WAD. NOTE: The `scale` value must be greater than 18.

```
function scaleDownToWad(uint256 value, uint256 scale) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description            |
| ------- | --------- | ---------------------- |
| `value` | `uint256` | to scale down.         |
| `scale` | `uint256` | of the returned value. |

#### [scaleDownToRay](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaledowntoray" id="scaledowntoray"></a>

Scales a value down to RAY. NOTE: The `scale` value must be greater than 27.

```
function scaleDownToRay(uint256 value, uint256 scale) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description            |
| ------- | --------- | ---------------------- |
| `value` | `uint256` | to scale down.         |
| `scale` | `uint256` | of the returned value. |

#### [scaleDownToRad](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaledowntorad" id="scaledowntorad"></a>

Scales a value down to RAD. NOTE: The `scale` value must be greater than 45.

```
function scaleDownToRad(uint256 value, uint256 scale) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description            |
| ------- | --------- | ---------------------- |
| `value` | `uint256` | to scale down.         |
| `scale` | `uint256` | of the returned value. |

#### [scaleUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaleup" id="scaleup"></a>

Scales a value up from one fixed-point precision to another.

```
function scaleUp(uint256 value, uint256 from, uint256 to) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description              |
| ------- | --------- | ------------------------ |
| `value` | `uint256` | to scale up.             |
| `from`  | `uint256` | Precision to scale from. |
| `to`    | `uint256` | Precision to scale to.   |

#### [scaleDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#scaledown" id="scaledown"></a>

Scales a value down from one fixed-point precision to another.

```
function scaleDown(uint256 value, uint256 from, uint256 to) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description              |
| ------- | --------- | ------------------------ |
| `value` | `uint256` | to scale down.           |
| `from`  | `uint256` | Precision to scale from. |
| `to`    | `uint256` | Precision to scale to.   |

### [Errors](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#errors" id="errors"></a>

#### [NotScalingUp](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#notscalingup" id="notscalingup"></a>

```
error NotScalingUp(uint256 from, uint256 to);
```

#### [NotScalingDown](broken://pages/jm31EM4gWXTfb5CMs4fr) <a href="#notscalingdown" id="notscalingdown"></a>

```
error NotScalingDown(uint256 from, uint256 to);
```


# uniswap


# UniswapOracleLibrary

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/uniswap/UniswapOracleLibrary.sol)

Provides functions to integrate with V3 pool oracle

### [Functions](broken://pages/dySUCNwGmSCDF6WJ15GW) <a href="#functions" id="functions"></a>

#### [consult](broken://pages/dySUCNwGmSCDF6WJ15GW) <a href="#consult" id="consult"></a>

Calculates time-weighted means of tick and liquidity for a given Uniswap V3 pool

```
function consult(
    address pool,
    uint32 secondsAgo
)
    internal
    view
    returns (int24 arithmeticMeanTick, uint128 harmonicMeanLiquidity);
```

**Parameters**

| Name         | Type      | Description                                                                   |
| ------------ | --------- | ----------------------------------------------------------------------------- |
| `pool`       | `address` | Address of the pool that we want to observe                                   |
| `secondsAgo` | `uint32`  | Number of seconds in the past from which to calculate the time-weighted means |

**Returns**

| Name                    | Type      | Description                                                                        |
| ----------------------- | --------- | ---------------------------------------------------------------------------------- |
| `arithmeticMeanTick`    | `int24`   | The arithmetic mean tick from (block.timestamp - secondsAgo) to block.timestamp    |
| `harmonicMeanLiquidity` | `uint128` | The harmonic mean liquidity from (block.timestamp - secondsAgo) to block.timestamp |


# TickMath

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/libraries/uniswap/TickMath.sol)

Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports prices between 2\*\*-128 and 2\*\*128

### [State Variables](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#state-variables" id="state-variables"></a>

#### [MIN\_TICK](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#min_tick" id="min_tick"></a>

*The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2*\*-128\*

```
int24 internal constant MIN_TICK = -887_272;
```

#### [MAX\_TICK](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#max_tick" id="max_tick"></a>

*The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2\*\*128*

```
int24 internal constant MAX_TICK = -MIN_TICK;
```

#### [MIN\_SQRT\_RATIO](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#min_sqrt_ratio" id="min_sqrt_ratio"></a>

*The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN\_TICK)*

```
uint160 public constant MIN_SQRT_RATIO = 4_295_128_739;
```

#### [MAX\_SQRT\_RATIO](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#max_sqrt_ratio" id="max_sqrt_ratio"></a>

*The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX\_TICK)*

```
uint160 internal constant MAX_SQRT_RATIO = 1_461_446_703_485_210_103_287_273_052_203_988_822_378_723_970_342;
```

### [Functions](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#functions" id="functions"></a>

#### [getSqrtRatioAtTick](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#getsqrtratioattick" id="getsqrtratioattick"></a>

Calculates sqrt(1.0001^tick) \* 2^96

*Throws if |tick| > max tick*

```
function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96);
```

**Parameters**

| Name   | Type    | Description                          |
| ------ | ------- | ------------------------------------ |
| `tick` | `int24` | The input tick for the above formula |

**Returns**

| Name           | Type      | Description                                                                                                        |
| -------------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
| `sqrtPriceX96` | `uint160` | A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) at the given tick |

#### [getTickAtSqrtRatio](broken://pages/kxJKN7vVXFdvOqDlXXJd) <a href="#gettickatsqrtratio" id="gettickatsqrtratio"></a>

Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio

*Throws in case sqrtPriceX96 < MIN\_SQRT\_RATIO, as MIN\_SQRT\_RATIO is the lowest value getRatioAtTick may ever return.*

```
function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick);
```

**Parameters**

| Name           | Type      | Description                                              |
| -------------- | --------- | -------------------------------------------------------- |
| `sqrtPriceX96` | `uint160` | The sqrt ratio for which to compute the tick as a Q64.96 |

**Returns**

| Name   | Type    | Description                                                                    |
| ------ | ------- | ------------------------------------------------------------------------------ |
| `tick` | `int24` | The greatest tick for which the ratio is less than or equal to the input ratio |


# Oracles


# Reserve


# LRT


# EzEthWstEthReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/lrt/EzEthWstEthReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve Oracle for ezETH

### [Functions](broken://pages/jgyk6xewP2NVbkDeHnvJ) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/jgyk6xewP2NVbkDeHnvJ) <a href="#constructor" id="constructor"></a>

Creates a new `ezEthWstEthReserveOracle` instance. Provides the amount of wstETH equal to one ezETH. wstETH / ezETH = ETH / ezETH \* wstETH / ETH.

*The value of ezETH denominated in wstETH by the provider.*

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

**Parameters**

| Name         | Type        | Description                                                   |
| ------------ | ----------- | ------------------------------------------------------------- |
| `_ilkIndex`  | `uint8`     |                                                               |
| `_feeds`     | `address[]` | List of alternative data sources for the ezETH exchange rate. |
| `_quorum`    | `uint8`     | The amount of alternative data sources to aggregate.          |
| `_maxChange` | `uint256`   | Maximum percent change between exchange rate updates. \[RAY]  |

#### [\_getProtocolExchangeRate](broken://pages/jgyk6xewP2NVbkDeHnvJ) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```


# RsEthWstEthReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/lrt/RsEthWstEthReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve oracle for rsETH.

### [Functions](broken://pages/Zv1ERdQEFT5fzvffGWxR) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/Zv1ERdQEFT5fzvffGWxR) <a href="#constructor" id="constructor"></a>

Creates a new `rsEthwstEthReserveOracle` instance. Provides the amount of wstETH equal to one rsETH. wstETH / rsETH = ETH / rsETH \* wstETH / ETH.

*The value of rsETH denominated in wstETH by the provider.*

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

**Parameters**

| Name         | Type        | Description                                                   |
| ------------ | ----------- | ------------------------------------------------------------- |
| `_ilkIndex`  | `uint8`     | of rsETH.                                                     |
| `_feeds`     | `address[]` | List of alternative data sources for the rsETH exchange rate. |
| `_quorum`    | `uint8`     | The amount of alternative data sources to aggregate.          |
| `_maxChange` | `uint256`   | Maximum percent change between exchange rate updates. \[RAY]  |

#### [\_getProtocolExchangeRate](broken://pages/Zv1ERdQEFT5fzvffGWxR) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the exchange rate between wstETH and rsETH.

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                             |
| -------- | --------- | --------------------------------------- |
| `<none>` | `uint256` | Exchange rate between wstETH and rsETH. |


# RswEthWstEthReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/lrt/RswEthWstEthReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve oracle for rswETH.

### [Functions](broken://pages/zODz7vacMlbqN8eZ9myL) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/zODz7vacMlbqN8eZ9myL) <a href="#constructor" id="constructor"></a>

Creates a new `rswEthwstEthReserveOracle` instance. Provides the amount of wstETH equal to one rswETH. wstETH / rswETH = ETH / rswETH \* wstETH / ETH.

*The value of rswETH denominated in wstETH by the provider.*

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

**Parameters**

| Name         | Type        | Description                                                    |
| ------------ | ----------- | -------------------------------------------------------------- |
| `_ilkIndex`  | `uint8`     | of rswETH.                                                     |
| `_feeds`     | `address[]` | List of alternative data sources for the rswETH exchange rate. |
| `_quorum`    | `uint8`     | The amount of alternative data sources to aggregate.           |
| `_maxChange` | `uint256`   | Maximum percent change between exchange rate updates. \[RAY]   |

#### [\_getProtocolExchangeRate](broken://pages/zODz7vacMlbqN8eZ9myL) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the exchange rate between wstETH and rswETH.

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                              |
| -------- | --------- | ---------------------------------------- |
| `<none>` | `uint256` | Exchange rate between wstETH and rswETH. |


# WeEthWstEthReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/lrt/WeEthWstEthReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve oracle for weETH.

### [Functions](broken://pages/G4a281XrFCP4qYOvhAsQ) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/G4a281XrFCP4qYOvhAsQ) <a href="#constructor" id="constructor"></a>

Creates a new `weEthwstEthReserveOracle` instance. Provides the amount of wstETH equal to one weETH. wstETH / weETH = eETH / weETH \* ETH / eETH \* wstETH / ETH. ETH / eETH is 1 since eETH is rebasing. Depeg here would reflect in eETH / wETH exchange rate.

*The value of weETH denominated in wstETH by the provider.*

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

**Parameters**

| Name         | Type        | Description                                                   |
| ------------ | ----------- | ------------------------------------------------------------- |
| `_ilkIndex`  | `uint8`     | of weETH.                                                     |
| `_feeds`     | `address[]` | List of alternative data sources for the weETH exchange rate. |
| `_quorum`    | `uint8`     | The amount of alternative data sources to aggregate.          |
| `_maxChange` | `uint256`   | Maximum percent change between exchange rate updates. \[RAY]  |

#### [\_getProtocolExchangeRate](broken://pages/G4a281XrFCP4qYOvhAsQ) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the exchange rate between wstETH and weETH.

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                             |
| -------- | --------- | --------------------------------------- |
| `<none>` | `uint256` | Exchange rate between wstETH and weETH. |


# LST


# SwEthReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/lst/SwEthReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve oracle for swETH.

### [State Variables](broken://pages/xp6RQnW7suW27POpGIY2) <a href="#state-variables" id="state-variables"></a>

#### [PROTOCOL\_FEED](broken://pages/xp6RQnW7suW27POpGIY2) <a href="#protocol_feed" id="protocol_feed"></a>

```
address public immutable PROTOCOL_FEED;
```

### [Functions](broken://pages/xp6RQnW7suW27POpGIY2) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/xp6RQnW7suW27POpGIY2) <a href="#constructor" id="constructor"></a>

Creates a new `EthXReserveOracle` instance.

```
constructor(
    address _protocolFeed,
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

**Parameters**

| Name            | Type        | Description                                                   |
| --------------- | ----------- | ------------------------------------------------------------- |
| `_protocolFeed` | `address`   | Data source for the LST provider exchange rate.               |
| `_ilkIndex`     | `uint8`     | of swETH.                                                     |
| `_feeds`        | `address[]` | List of alternative data sources for the swETH exchange rate. |
| `_quorum`       | `uint8`     | The amount of alternative data sources to aggregate.          |
| `_maxChange`    | `uint256`   | Maximum percent change between exchange rate updates. \[RAY]  |

#### [\_getProtocolExchangeRate](broken://pages/xp6RQnW7suW27POpGIY2) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the exchange rate between ETH and swETH.

```
function _getProtocolExchangeRate() internal view override returns (uint256 protocolExchangeRate);
```

**Returns**

| Name                   | Type      | Description                          |
| ---------------------- | --------- | ------------------------------------ |
| `protocolExchangeRate` | `uint256` | Exchange rate between ETH and swETH. |


# EthXReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/lst/EthXReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve oracle for ETHx.

### [State Variables](broken://pages/ohGkCYu6iENQpQ9vT0ZL) <a href="#state-variables" id="state-variables"></a>

#### [PROTOCOL\_FEED](broken://pages/ohGkCYu6iENQpQ9vT0ZL) <a href="#protocol_feed" id="protocol_feed"></a>

```
address public immutable PROTOCOL_FEED;
```

### [Functions](broken://pages/ohGkCYu6iENQpQ9vT0ZL) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/ohGkCYu6iENQpQ9vT0ZL) <a href="#constructor" id="constructor"></a>

Creates a new `EthXReserveOracle` instance.

```
constructor(
    address _protocolFeed,
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

**Parameters**

| Name            | Type        | Description                                                  |
| --------------- | ----------- | ------------------------------------------------------------ |
| `_protocolFeed` | `address`   | Data source for the LST provider exchange rate.              |
| `_ilkIndex`     | `uint8`     | of ETHx.                                                     |
| `_feeds`        | `address[]` | List of alternative data sources for the ETHx exchange rate. |
| `_quorum`       | `uint8`     | The amount of alternative data sources to aggregate.         |
| `_maxChange`    | `uint256`   | Maximum percent change between exchange rate updates. \[RAY] |

#### [\_getProtocolExchangeRate](broken://pages/ohGkCYu6iENQpQ9vT0ZL) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the exchange rate between ETH and ETHx.

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                         |
| -------- | --------- | ----------------------------------- |
| `<none>` | `uint256` | Exchange rate between ETH and ETHx. |


# WstEthReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/lst/WstEthReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve oracle for wstETH.

### [State Variables](broken://pages/Gwkkgj1mxejhVNdC1GBJ) <a href="#state-variables" id="state-variables"></a>

#### [WST\_ETH](broken://pages/Gwkkgj1mxejhVNdC1GBJ) <a href="#wst_eth" id="wst_eth"></a>

```
address public immutable WST_ETH;
```

### [Functions](broken://pages/Gwkkgj1mxejhVNdC1GBJ) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/Gwkkgj1mxejhVNdC1GBJ) <a href="#constructor" id="constructor"></a>

Creates a new `WstEthReserveOracle` instance.

```
constructor(
    address _wstEth,
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

**Parameters**

| Name         | Type        | Description                                                    |
| ------------ | ----------- | -------------------------------------------------------------- |
| `_wstEth`    | `address`   | wstETH contract address.                                       |
| `_ilkIndex`  | `uint8`     | of wstETH.                                                     |
| `_feeds`     | `address[]` | List of alternative data sources for the WstEth exchange rate. |
| `_quorum`    | `uint8`     | The amount of alternative data sources to aggregate.           |
| `_maxChange` | `uint256`   | Maximum percent change between exchange rate updates. \[RAY]   |

#### [\_getProtocolExchangeRate](broken://pages/Gwkkgj1mxejhVNdC1GBJ) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the exchange rate between wstETH and stETH.

*In a slashing event, the loss for the staker is represented through a decrease in the wstETH to stETH exchange rate inside the wstETH contract. The stETH to ETH ratio in the Lido contract will still remain 1:1 as it rebases. stETH / wstETH = stEth per wstETH ETH / stETH = total ether value / total stETH supply ETH / wstETH = (ETH / stETH) \* (stETH / wstETH)*

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```


# Pendle


# EzEthPtReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/pendle/EzEthPtReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve Oracle for PT-ezETH

### [Functions](broken://pages/qahAwZJnT19JwXLhkLSE) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/qahAwZJnT19JwXLhkLSE) <a href="#constructor" id="constructor"></a>

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

#### [\_getProtocolExchangeRate](broken://pages/qahAwZJnT19JwXLhkLSE) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

*1 PT will be worth 1 ETH at maturity. Since we want to value the PT at maturity, we need to convert 1 ETH of value into ezETH terms.*

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```


# RsEthPtReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/pendle/RsEthPtReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve Oracle for PT-rsETH

### [Functions](broken://pages/TYHQ2o0a3xd6WmK7Bgsm) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/TYHQ2o0a3xd6WmK7Bgsm) <a href="#constructor" id="constructor"></a>

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

#### [\_getProtocolExchangeRate](broken://pages/TYHQ2o0a3xd6WmK7Bgsm) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

*1 PT will be worth 1 ETH at maturity. Since we want to value the PT at maturity, we need to convert 1 ETH of value into rsETH terms.*

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```


# RswEthPtReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/pendle/RswEthPtReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve Oracle for PT-rswETH

### [Functions](broken://pages/H6vaAEU0VUV1tQA8q6eV) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/H6vaAEU0VUV1tQA8q6eV) <a href="#constructor" id="constructor"></a>

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

#### [\_getProtocolExchangeRate](broken://pages/H6vaAEU0VUV1tQA8q6eV) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

*1 PT will be worth 1 ETH at maturity. Since we want to value the PT at maturity, we need to convert 1 ETH of value into rswETH terms.*

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```


# WeEthPtReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/pendle/WeEthPtReserveOracle.sol)

**Inherits:** ReserveOracle

Reserve Oracle for PT-weETH

### [Functions](broken://pages/y9vNg3YBMxksP4CInGEq) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/y9vNg3YBMxksP4CInGEq) <a href="#constructor" id="constructor"></a>

```
constructor(
    uint8 _ilkIndex,
    address[] memory _feeds,
    uint8 _quorum,
    uint256 _maxChange
)
    ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange);
```

#### [\_getProtocolExchangeRate](broken://pages/y9vNg3YBMxksP4CInGEq) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

*1 PT will be worth 1 eETH at maturity. Since we want to value the PT at maturity, we need to convert 1 eETH of value into weETH terms.*

```
function _getProtocolExchangeRate() internal view override returns (uint256);
```


# ReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/ReserveOracle.sol)

Reserve oracles are used to determine the LST provider exchange rate and is utilizated by Ion's liquidation module. Liquidations will only be triggered against this exchange rate and will be completely market-price agnostic. Importantly, this means that liquidations will only be triggered through lack of debt repayment or slashing events.

*In order to protect against potential provider bugs or incorrect one-off values (malicious or accidental), the reserve oracle does not use live data. Instead it will query the exchange every intermittent period and persist the value and this value can only move up or down by a maximum percentage per query. If additional data sources are available, they can be involved as `FEED`s. If other `FEED`s are provided to the reserve oracle, a mean of all the `FEED`s is compared to the protocol exchange rate and the minimum of the two is used as the new exchange rate. This final value is subject to the bounding rules.*

### [State Variables](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#state-variables" id="state-variables"></a>

#### [ILK\_INDEX](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#ilk_index" id="ilk_index"></a>

```
uint8 public immutable ILK_INDEX;
```

#### [QUORUM](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#quorum" id="quorum"></a>

```
uint8 public immutable QUORUM;
```

#### [MAX\_CHANGE](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#max_change" id="max_change"></a>

```
uint256 public immutable MAX_CHANGE;
```

#### [FEED0](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#feed0" id="feed0"></a>

```
IReserveFeed public immutable FEED0;
```

#### [FEED1](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#feed1" id="feed1"></a>

```
IReserveFeed public immutable FEED1;
```

#### [FEED2](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#feed2" id="feed2"></a>

```
IReserveFeed public immutable FEED2;
```

#### [currentExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#currentexchangerate" id="currentexchangerate"></a>

```
uint256 public currentExchangeRate;
```

#### [lastUpdated](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#lastupdated" id="lastupdated"></a>

```
uint256 public lastUpdated;
```

### [Functions](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#constructor" id="constructor"></a>

Creates a new `ReserveOracle` instance.

```
constructor(uint8 _ilkIndex, address[] memory _feeds, uint8 _quorum, uint256 _maxChange);
```

**Parameters**

| Name         | Type        | Description                                                  |
| ------------ | ----------- | ------------------------------------------------------------ |
| `_ilkIndex`  | `uint8`     | of the associated collateral.                                |
| `_feeds`     | `address[]` | Alternative data sources to be used for the reserve oracle.  |
| `_quorum`    | `uint8`     | The number of feeds to aggregate.                            |
| `_maxChange` | `uint256`   | Maximum percent change between exchange rate updates. \[RAY] |

#### [\_getProtocolExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the protocol exchange rate.

*Must be implemented in the child contract with LST-specific logic.*

```
function _getProtocolExchangeRate() internal view virtual returns (uint256);
```

**Returns**

| Name     | Type      | Description                 |
| -------- | --------- | --------------------------- |
| `<none>` | `uint256` | The protocol exchange rate. |

#### [getProtocolExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the protocol exchange rate.

```
function getProtocolExchangeRate() external view returns (uint256);
```

**Returns**

| Name     | Type      | Description                 |
| -------- | --------- | --------------------------- |
| `<none>` | `uint256` | The protocol exchange rate. |

#### [\_aggregate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#aggregate" id="aggregate"></a>

Queries values from whitelisted data feeds and calculates the mean. This does not include the protocol exchange rate.

```
function _aggregate(uint8 _ILK_INDEX) internal view returns (uint256 val);
```

**Parameters**

| Name         | Type    | Description                   |
| ------------ | ------- | ----------------------------- |
| `_ILK_INDEX` | `uint8` | of the associated collateral. |

#### [\_bound](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#bound" id="bound"></a>

Bounds the value between the min and the max.

```
function _bound(uint256 value, uint256 min, uint256 max) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description              |
| ------- | --------- | ------------------------ |
| `value` | `uint256` | The value to be bounded. |
| `min`   | `uint256` | The minimum bound.       |
| `max`   | `uint256` | The maximum bound.       |

#### [\_initializeExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#initializeexchangerate" id="initializeexchangerate"></a>

Initializes the `currentExchangeRate` state variable.

*Called once during construction.*

```
function _initializeExchangeRate() internal;
```

#### [updateExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#updateexchangerate" id="updateexchangerate"></a>

Updates the `currentExchangeRate` state variable.

*Takes the minimum between the aggregated values and the protocol exchange rate, then bounds it up to the maximum change and writes the bounded value to the state. NOTE: keepers should call this update to reflect recent values*

```
function updateExchangeRate() external;
```

### [Events](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#events" id="events"></a>

#### [UpdateExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#updateexchangerate-1" id="updateexchangerate-1"></a>

```
event UpdateExchangeRate(uint256 exchangeRate);
```

### [Errors](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#errors" id="errors"></a>

#### [InvalidQuorum](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidquorum" id="invalidquorum"></a>

```
error InvalidQuorum(uint8 invalidQuorum);
```

#### [InvalidFeedLength](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidfeedlength" id="invalidfeedlength"></a>

```
error InvalidFeedLength(uint256 invalidLength);
```

#### [InvalidMaxChange](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidmaxchange" id="invalidmaxchange"></a>

```
error InvalidMaxChange(uint256 invalidMaxChange);
```

#### [InvalidMinMax](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidminmax" id="invalidminmax"></a>

```
error InvalidMinMax(uint256 invalidMin, uint256 invalidMax);
```

#### [InvalidInitialization](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidinitialization" id="invalidinitialization"></a>

```
error InvalidInitialization(uint256 invalidExchangeRate);
```

#### [UpdateCooldown](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#updatecooldown" id="updatecooldown"></a>

```
error UpdateCooldown(uint256 lastUpdated);
```


# ReserveFeed

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/ReserveFeed.sol)

**Inherits:** Ownable2Step

### [State Variables](broken://pages/krotr4ZeEEhAqrPp4oa3) <a href="#state-variables" id="state-variables"></a>

#### [exchangeRates](broken://pages/krotr4ZeEEhAqrPp4oa3) <a href="#exchangerates" id="exchangerates"></a>

```
mapping(uint8 ilkIndex => uint256 exchangeRate) public exchangeRates;
```

### [Functions](broken://pages/krotr4ZeEEhAqrPp4oa3) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/krotr4ZeEEhAqrPp4oa3) <a href="#constructor" id="constructor"></a>

```
constructor(address owner) Ownable(owner);
```

#### [setExchangeRate](broken://pages/krotr4ZeEEhAqrPp4oa3) <a href="#setexchangerate" id="setexchangerate"></a>

```
function setExchangeRate(uint8 _ilkIndex, uint256 _exchangeRate) external onlyOwner;
```

#### [getExchangeRate](broken://pages/krotr4ZeEEhAqrPp4oa3) <a href="#getexchangerate" id="getexchangerate"></a>

```
function getExchangeRate(uint8 _ilkIndex) external view returns (uint256);
```


# ReserveOracle constants

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/ReserveOracle.sol)

#### [FEED\_COUNT](broken://pages/otliiayflv7lRs5dTNsk) <a href="#feed_count" id="feed_count"></a>

```
uint8 constant FEED_COUNT = 3;
```

#### [UPDATE\_COOLDOWN](broken://pages/otliiayflv7lRs5dTNsk) <a href="#update_cooldown" id="update_cooldown"></a>

```
uint256 constant UPDATE_COOLDOWN = 58 minutes;
```


# Spot


# LRT


# EzEthWstEthSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lrt/EzEthWstEthSpotOracle.sol)

**Inherits:** SpotOracle

The ezETH spot oracle denominated in wstETH

### [State Variables](broken://pages/pZMVDTtzJOjXgb2rxNZz) <a href="#state-variables" id="state-variables"></a>

#### [MAX\_TIME\_FROM\_LAST\_UPDATE](broken://pages/pZMVDTtzJOjXgb2rxNZz) <a href="#max_time_from_last_update" id="max_time_from_last_update"></a>

```
uint256 public immutable MAX_TIME_FROM_LAST_UPDATE;
```

### [Functions](broken://pages/pZMVDTtzJOjXgb2rxNZz) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/pZMVDTtzJOjXgb2rxNZz) <a href="#constructor" id="constructor"></a>

Creates a new `EzEthWstEthSpotOracle` instance.

```
constructor(uint256 _ltv, address _reserveOracle, uint256 _maxTimeFromLastUpdate) SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name                     | Type      | Description                                 |
| ------------------------ | --------- | ------------------------------------------- |
| `_ltv`                   | `uint256` | The loan to value ratio for ezETH <> wstETH |
| `_reserveOracle`         | `address` | The associated reserve oracle.              |
| `_maxTimeFromLastUpdate` | `uint256` |                                             |

#### [getPrice](broken://pages/pZMVDTtzJOjXgb2rxNZz) <a href="#getprice" id="getprice"></a>

Gets the price of ezETH in wstETH (ETH / ezETH) / (ETH / stETH) \* (wstETH / stETH) = wstETH / ezETH

*Redstone oracle returns ETH per ezETH with 8 decimals. This needs to be converted to wstETH per ezETH denomination.*

```
function getPrice() public view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | wstEthPerWeEth price of ezETH in wstETH. \[WAD] |


# RsEthWstEthSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lrt/RsEthWstEthSpotOracle.sol)

**Inherits:** SpotOracle

The rsETH spot oracle denominated in wstETH

### [State Variables](broken://pages/ZHpjzy3jnwljoCfFEj6V) <a href="#state-variables" id="state-variables"></a>

#### [MAX\_TIME\_FROM\_LAST\_UPDATE](broken://pages/ZHpjzy3jnwljoCfFEj6V) <a href="#max_time_from_last_update" id="max_time_from_last_update"></a>

```
uint256 public immutable MAX_TIME_FROM_LAST_UPDATE;
```

### [Functions](broken://pages/ZHpjzy3jnwljoCfFEj6V) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/ZHpjzy3jnwljoCfFEj6V) <a href="#constructor" id="constructor"></a>

Creates a new `RsEthWstEthSpotOracle` instance.

```
constructor(uint256 _ltv, address _reserveOracle, uint256 _maxTimeFromLastUpdate) SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name                     | Type      | Description                                        |
| ------------------------ | --------- | -------------------------------------------------- |
| `_ltv`                   | `uint256` | The loan to value ratio for rsETH <> wstETH        |
| `_reserveOracle`         | `address` | The associated reserve oracle.                     |
| `_maxTimeFromLastUpdate` | `uint256` | The maximum delay for the oracle update in seconds |

#### [getPrice](broken://pages/ZHpjzy3jnwljoCfFEj6V) <a href="#getprice" id="getprice"></a>

Gets the price of rsETH in wstETH. (ETH / rsETH) / (ETH / stETH) \* (wstETH / stETH) = wstETH / rsETH

*Redstone oracle returns ETH per rsETH with 8 decimals. This needs to be converted to wstETH per rsETH denomination.*

```
function getPrice() public view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | wstEthPerRsEth price of rsETH in wstETH. \[WAD] |


# RswEthWstEthSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lrt/RswEthWstEthSpotOracle.sol)

**Inherits:** SpotOracle

The rswETH spot oracle denominated in wstETH

### [State Variables](broken://pages/g0B9LrtSwnLkrXMzFziE) <a href="#state-variables" id="state-variables"></a>

#### [MAX\_TIME\_FROM\_LAST\_UPDATE](broken://pages/g0B9LrtSwnLkrXMzFziE) <a href="#max_time_from_last_update" id="max_time_from_last_update"></a>

```
uint256 public immutable MAX_TIME_FROM_LAST_UPDATE;
```

### [Functions](broken://pages/g0B9LrtSwnLkrXMzFziE) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/g0B9LrtSwnLkrXMzFziE) <a href="#constructor" id="constructor"></a>

Creates a new `RswEthWstEthSpotOracle` instance.

```
constructor(uint256 _ltv, address _reserveOracle, uint256 _maxTimeFromLastUpdate) SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name                     | Type      | Description                                        |
| ------------------------ | --------- | -------------------------------------------------- |
| `_ltv`                   | `uint256` | The loan to value ratio for rswETH <> wstETH       |
| `_reserveOracle`         | `address` | The associated reserve oracle.                     |
| `_maxTimeFromLastUpdate` | `uint256` | The maximum delay for the oracle update in seconds |

#### [getPrice](broken://pages/g0B9LrtSwnLkrXMzFziE) <a href="#getprice" id="getprice"></a>

Gets the price of rswETH in wstETH. (ETH / rswETH) / (ETH / stETH) \* (wstETH / stETH) = wstETH / rswETH

*Redstone oracle returns ETH per rswETH with 8 decimals. This needs to be converted to wstETH per rswETH denomination.*

```
function getPrice() public view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                                       |
| -------- | --------- | ------------------------------------------------- |
| `<none>` | `uint256` | wstEthPerRswEth price of rswETH in wstETH. \[WAD] |


# WeEthWstEthSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lrt/WeEthWstEthSpotOracle.sol)

**Inherits:** SpotOracle

The weETH spot oracle denominated in wstETH

### [State Variables](broken://pages/z9NZMzujvxydlK1EYM9X) <a href="#state-variables" id="state-variables"></a>

#### [MAX\_TIME\_FROM\_LAST\_UPDATE](broken://pages/z9NZMzujvxydlK1EYM9X) <a href="#max_time_from_last_update" id="max_time_from_last_update"></a>

```
uint256 public immutable MAX_TIME_FROM_LAST_UPDATE;
```

### [Functions](broken://pages/z9NZMzujvxydlK1EYM9X) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/z9NZMzujvxydlK1EYM9X) <a href="#constructor" id="constructor"></a>

Creates a new `WeEthWstEthSpotOracle` instance.

```
constructor(uint256 _ltv, address _reserveOracle, uint256 _maxTimeFromLastUpdate) SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name                     | Type      | Description                                        |
| ------------------------ | --------- | -------------------------------------------------- |
| `_ltv`                   | `uint256` | The loan to value ratio for weETH <> wstETH        |
| `_reserveOracle`         | `address` | The associated reserve oracle.                     |
| `_maxTimeFromLastUpdate` | `uint256` | The maximum delay for the oracle update in seconds |

#### [getPrice](broken://pages/z9NZMzujvxydlK1EYM9X) <a href="#getprice" id="getprice"></a>

Gets the price of weETH in wstETH. (ETH / weETH) / (ETH / stETH) \* (wstETH / stETH) = wstETH / weETH

*Redstone oracle returns ETH per weETH with 8 decimals. This needs to be converted to wstETH per weETH denomination.*

```
function getPrice() public view override returns (uint256);
```

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | wstEthPerWeEth price of weETH in wstETH. \[WAD] |


# LST


# EthXSpotOracle constants

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lst/EthXSpotOracle.sol)

#### [REDSTONE\_DECIMALS](broken://pages/pUrPaLspTTswnCWOuzsu) <a href="#redstone_decimals" id="redstone_decimals"></a>

```
uint8 constant REDSTONE_DECIMALS = 8;
```

#### [CHAINLINK\_DECIMALS](broken://pages/pUrPaLspTTswnCWOuzsu) <a href="#chainlink_decimals" id="chainlink_decimals"></a>

```
uint8 constant CHAINLINK_DECIMALS = 8;
```


# EthXSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lst/EthXSpotOracle.sol)

**Inherits:** SpotOracle

The ETHx spot oracle.

### [State Variables](broken://pages/gxGDN4jyV9PBnftyQ0Nn) <a href="#state-variables" id="state-variables"></a>

#### [REDSTONE\_ETHX\_PRICE\_FEED](broken://pages/gxGDN4jyV9PBnftyQ0Nn) <a href="#redstone_ethx_price_feed" id="redstone_ethx_price_feed"></a>

```
IRedstonePriceFeed public immutable REDSTONE_ETHX_PRICE_FEED;
```

#### [USD\_PER\_ETH\_CHAINLINK](broken://pages/gxGDN4jyV9PBnftyQ0Nn) <a href="#usd_per_eth_chainlink" id="usd_per_eth_chainlink"></a>

```
IChainlink public immutable USD_PER_ETH_CHAINLINK;
```

### [Functions](broken://pages/gxGDN4jyV9PBnftyQ0Nn) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/gxGDN4jyV9PBnftyQ0Nn) <a href="#constructor" id="constructor"></a>

Creates a new `EthXSpotOracle` instance.

```
constructor(
    uint256 _ltv,
    address _reserveOracle,
    address _redstoneEthXPriceFeed,
    address _usdPerEthChainlink
)
    SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name                     | Type      | Description                           |
| ------------------------ | --------- | ------------------------------------- |
| `_ltv`                   | `uint256` | The loan to value ratio for ETHX.     |
| `_reserveOracle`         | `address` | The associated reserve oracle.        |
| `_redstoneEthXPriceFeed` | `address` | The redstone price feed for ETHx/USD. |
| `_usdPerEthChainlink`    | `address` | The chainlink price feed for ETH/USD. |

#### [getPrice](broken://pages/gxGDN4jyV9PBnftyQ0Nn) <a href="#getprice" id="getprice"></a>

Gets the price of ETHx in ETH.

*Redstone oracle returns dollar value per ETHx with 6 decimals. This needs to be converted to a WAD and to ETH denomination.*

```
function getPrice() public view override returns (uint256 ethPerEthX);
```

**Returns**

| Name         | Type      | Description                  |
| ------------ | --------- | ---------------------------- |
| `ethPerEthX` | `uint256` | price of ETHx in ETH. \[WAD] |


# IRedstonePriceFeed

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lst/EthXSpotOracle.sol)

### [Functions](broken://pages/Xx9AWDbjPqzetG0mW2rH) <a href="#functions" id="functions"></a>

#### [latestRoundData](broken://pages/Xx9AWDbjPqzetG0mW2rH) <a href="#latestrounddata" id="latestrounddata"></a>

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


# SwEthSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lst/SwEthSpotOracle.sol)

**Inherits:** SpotOracle

The swETH spot oracle.

### [State Variables](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#state-variables" id="state-variables"></a>

#### [POOL](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#pool" id="pool"></a>

```
IUniswapV3Pool public immutable POOL;
```

#### [SECONDS\_AGO](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#seconds_ago" id="seconds_ago"></a>

```
uint32 public immutable SECONDS_AGO;
```

### [Functions](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#constructor" id="constructor"></a>

Creates a new `SwEthSpotOracle` instance.

```
constructor(
    uint256 _ltv,
    address _reserveOracle,
    address _uniswapPool,
    uint32 _secondsAgo
)
    SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name             | Type      | Description                        |
| ---------------- | --------- | ---------------------------------- |
| `_ltv`           | `uint256` | The loan to value ratio for swETH. |
| `_reserveOracle` | `address` | The associated reserve oracle.     |
| `_uniswapPool`   | `address` | swETH/Eth Uniswap pool address.    |
| `_secondsAgo`    | `uint32`  | The TWAP period in seconds.        |

#### [getPrice](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#getprice" id="getprice"></a>

Gets the price of swETH in ETH.

*Uniswap returns price in swETH per ETH. This needs to be inversed.*

```
function getPrice() public view override returns (uint256 ethPerSwEth);
```

**Returns**

| Name          | Type      | Description                   |
| ------------- | --------- | ----------------------------- |
| `ethPerSwEth` | `uint256` | price of swETH in ETH. \[WAD] |

#### [\_getPriceInWadFromSqrtPriceX96](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#getpriceinwadfromsqrtpricex96" id="getpriceinwadfromsqrtpricex96"></a>

Converts a sqrtPriceX96 to a price in WAD.

```
function _getPriceInWadFromSqrtPriceX96(uint256 sqrtPriceX96) internal pure returns (uint256);
```

**Parameters**

| Name           | Type      | Description            |
| -------------- | --------- | ---------------------- |
| `sqrtPriceX96` | `uint256` | Price in sqrtPriceX96. |

### [Errors](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#errors" id="errors"></a>

#### [InvalidSecondsAgo](broken://pages/3MfS8rIe4PB4MlRXobY0) <a href="#invalidsecondsago" id="invalidsecondsago"></a>

```
error InvalidSecondsAgo(uint32 invalidSecondsAgo);
```


# WstEthSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/lst/WstEthSpotOracle.sol)

**Inherits:** SpotOracle

The wstETH spot oracle.

### [State Variables](broken://pages/mdixZxaUrD852sKoBlbu) <a href="#state-variables" id="state-variables"></a>

#### [ST\_ETH\_TO\_ETH\_CHAINLINK](broken://pages/mdixZxaUrD852sKoBlbu) <a href="#st_eth_to_eth_chainlink" id="st_eth_to_eth_chainlink"></a>

```
IChainlink public immutable ST_ETH_TO_ETH_CHAINLINK;
```

#### [WST\_ETH](broken://pages/mdixZxaUrD852sKoBlbu) <a href="#wst_eth" id="wst_eth"></a>

```
IWstEth public immutable WST_ETH;
```

### [Functions](broken://pages/mdixZxaUrD852sKoBlbu) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/mdixZxaUrD852sKoBlbu) <a href="#constructor" id="constructor"></a>

Creates a new `WstEthSpotOracle` instance.

```
constructor(
    uint256 _ltv,
    address _reserveOracle,
    address _stEthToEthChainlink,
    address _wstETH
)
    SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name                   | Type      | Description                             |
| ---------------------- | --------- | --------------------------------------- |
| `_ltv`                 | `uint256` | The loan to value ratio for wstETH.     |
| `_reserveOracle`       | `address` | The associated reserve oracle.          |
| `_stEthToEthChainlink` | `address` | The chainlink price feed for stETH/ETH. |
| `_wstETH`              | `address` | The wstETH contract address.            |

#### [getPrice](broken://pages/mdixZxaUrD852sKoBlbu) <a href="#getprice" id="getprice"></a>

Gets the price of wstETH in terms of ETH.

*Because the collateral amount in the core contract is denominated in amount of wstETH tokens, spot needs to equal (stETH/wstETH) \* (ETH/stETH) liquidationThreshold. If the beaconchain reserve decreases, the wstETH to stEth conversion will be directly impacted, but the stEth to Eth conversion will simply be determined by the chainlink price oracle.*

```
function getPrice() public view override returns (uint256 ethPerWstEth);
```

**Returns**

| Name           | Type      | Description                    |
| -------------- | --------- | ------------------------------ |
| `ethPerWstEth` | `uint256` | price of wstETH in ETH. \[WAD] |


# SpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/SpotOracle.sol)

The `SpotOracle` is supposed to reflect the current market price of a collateral asset. It is used by `IonPool` to determine the health factor of a vault as a user is opening or closing a position. NOTE: The price data provided by this contract is not used by the liquidation module at all. The spot price will also always be bounded by the collateral's corresponding reserve oracle price to ensure that a user can never open position that is directly liquidatable.

### [State Variables](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#state-variables" id="state-variables"></a>

#### [LTV](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#ltv" id="ltv"></a>

```
uint256 public immutable LTV;
```

#### [RESERVE\_ORACLE](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#reserve_oracle" id="reserve_oracle"></a>

```
ReserveOracle public immutable RESERVE_ORACLE;
```

### [Functions](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#constructor" id="constructor"></a>

Creates a new `SpotOracle` instance.

```
constructor(uint256 _ltv, address _reserveOracle);
```

**Parameters**

| Name             | Type      | Description                                |
| ---------------- | --------- | ------------------------------------------ |
| `_ltv`           | `uint256` | Loan to value ratio for the collateral.    |
| `_reserveOracle` | `address` | Address for the associated reserve oracle. |

#### [getPrice](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#getprice" id="getprice"></a>

Gets the price of the collateral asset in ETH.

*Overridden by collateral specific spot oracle contracts.*

```
function getPrice() public view virtual returns (uint256 price);
```

**Returns**

| Name    | Type      | Description                 |
| ------- | --------- | --------------------------- |
| `price` | `uint256` | of the asset in ETH. \[WAD] |

#### [getSpot](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#getspot" id="getspot"></a>

Gets the risk-adjusted market price.

```
function getSpot() external view returns (uint256 spot);
```

**Returns**

| Name   | Type      | Description                     |
| ------ | --------- | ------------------------------- |
| `spot` | `uint256` | The risk-adjusted market price. |

### [Errors](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#errors" id="errors"></a>

#### [InvalidLtv](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#invalidltv" id="invalidltv"></a>

```
error InvalidLtv(uint256 ltv);
```

#### [InvalidReserveOracle](broken://pages/uHI3W7DXDqHnS5vxNxTs) <a href="#invalidreserveoracle" id="invalidreserveoracle"></a>

```
error InvalidReserveOracle();
```


# PtSpotOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/spot/PtSpotOracle.sol)

**Inherits:** SpotOracle

Spot Oracle for PT MARKETs

*This contract assumes that the SY is pegged 1:1 with the underlying asset of IonPool. This is a major assumption to be aware of since this oracle will return a valuation in SY, which may or may not be the same as the underlying in the IonPool.*

### [State Variables](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#state-variables" id="state-variables"></a>

#### [MARKET](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#market" id="market"></a>

```
IPMarketV3 public immutable MARKET;
```

#### [TWAP\_DURATION](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#twap_duration" id="twap_duration"></a>

```
uint32 public immutable TWAP_DURATION;
```

### [Functions](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#constructor" id="constructor"></a>

Construct a new `PtSpotOracle` instance

```
constructor(
    IPMarketV3 _market,
    uint32 _twapDuration,
    uint256 _ltv,
    address _reserveOracle
)
    SpotOracle(_ltv, _reserveOracle);
```

**Parameters**

| Name             | Type         | Description                                |
| ---------------- | ------------ | ------------------------------------------ |
| `_market`        | `IPMarketV3` | The Pendle Market to get the PT price from |
| `_twapDuration`  | `uint32`     | The duration of the TWAP                   |
| `_ltv`           | `uint256`    | The Loan To Value ratio                    |
| `_reserveOracle` | `address`    | The oracle to get the reserve price from   |

#### [getPrice](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#getprice" id="getprice"></a>

Gets the price of the collateral asset in ETH.

*Overridden by collateral specific spot oracle contracts.*

```
function getPrice() public view override returns (uint256 price);
```

**Returns**

| Name    | Type      | Description                 |
| ------- | --------- | --------------------------- |
| `price` | `uint256` | of the asset in ETH. \[WAD] |

### [Errors](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#errors" id="errors"></a>

#### [InsufficientOracleSlots](broken://pages/FOQl6w7CDNYsIhr8fzW1) <a href="#insufficientoracleslots" id="insufficientoracleslots"></a>

```
error InsufficientOracleSlots(uint256 currentSlots);
```


# Periphery




---

[Next Page](/llms-full.txt/1)

