# 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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#state-variables" id="state-variables"></a>

#### [MIN\_SQRT\_RATIO](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#uniswap_pool" id="uniswap_pool"></a>

```
IUniswapV3Pool public immutable UNISWAP_POOL;
```

#### [WETH\_IS\_TOKEN0](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#weth_is_token0" id="weth_is_token0"></a>

```
bool private immutable WETH_IS_TOKEN0;
```

### [Functions](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#functions" id="functions"></a>

#### [constructor](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#errors" id="errors"></a>

#### [InvalidUniswapPool](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#invaliduniswappool" id="invaliduniswappool"></a>

```
error InvalidUniswapPool();
```

#### [InvalidZeroLiquidityRegionSwap](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#invalidzeroliquidityregionswap" id="invalidzeroliquidityregionswap"></a>

```
error InvalidZeroLiquidityRegionSwap();
```

#### [InvalidSqrtPriceLimitX96](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#invalidsqrtpricelimitx96" id="invalidsqrtpricelimitx96"></a>

```
error InvalidSqrtPriceLimitX96(uint160 sqrtPriceLimitX96);
```

#### [FlashswapRepaymentTooExpensive](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#flashswaprepaymenttooexpensive" id="flashswaprepaymenttooexpensive"></a>

```
error FlashswapRepaymentTooExpensive(uint256 amountIn, uint256 maxAmountIn);
```

#### [CallbackOnlyCallableByPool](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#callbackonlycallablebypool" id="callbackonlycallablebypool"></a>

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

#### [OutputAmountNotReceived](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#outputamountnotreceived" id="outputamountnotreceived"></a>

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

### [Structs](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#structs" id="structs"></a>

#### [FlashSwapData](https://docs.ionprotocol.io/devs/smart-contract-architecture/flash/broken-reference) <a href="#flashswapdata" id="flashswapdata"></a>

```
struct FlashSwapData {
    address user;
    uint256 changeInCollateralOrDebt;
    bool zeroForOne;
}
```
