# IchiSpell

This contract is used to manage the deployments of borrowing tokens to enter into ICHI vault's. The contract allows users to open and close positions by depositing collateral into the Blueberry money market and borrowing tokens to achieve the desired leverage.&#x20;

### Structs

The contract defines the following structs:

* `Strategy`:A struct that represents an ICHI vault strategy. It contains the address of the vault and the maximum position size, which is a USD price-based value
* `OpenPosParam`: A struct that represents the parameters required to open a position. It contains the strategy ID, collateral token address, borrowing token address, collateral amount, borrowing amount , and farming pool ID
* `ClosePosParam`: A struct that represents the parameters required to close a position. It contains the strategy ID, collateral token address, borrowing token address, amount of LP tokens to remove, amount of debt to repay, amount of isolated collateral to withdraw, and sell slippage.

### State Variables

The contract has the following state variables:

* `swapPool`: A private state variable that is used to store the Uniswap V3 pool when swapping tokens.
* `strategies`: A public array of `Strategy` structs that stores all the ICHI vault strategies
* `maxLTV`: A mapping that maps strategy IDs to collateral tokens and their maximum loan-to-value (LTV) ratios
* `wIchiFarm`: An instance of the `IWIchiFarm` interface that is used to interact with the ICHI farm
* `ICHI`: The address of the ICHI token

### Events

The contract emits the following events:

* `StrategyAdded(uint256 strategyId, address vault, uint256 maxPosSize)`: Emits when a new strategy is added to the contract.
* `CollateralsMaxLTVSet(uint256 strategyId, address[] collaterals, uint256[] maxLTVs)`: Emits when the maximum LTV ratios are set for collateral tokens.

### Modifiers

The contract defines the following modifiers:

* `existingStrategy(uint256 strategyId)`: A modifier that checks if a strategy ID exists.
* `existingCollateral(uint256 strategyId, address col)`: A modifier that checks if a collateral token exists for a strategy.

### Functions

The contract defines the following functions:

#### initialize

{% code overflow="wrap" %}

```solidity
function initialize(IBank bank_, address werc20_, address weth_, address wichiFarm_) external initializer 
```

{% endcode %}

This function is an initializer function that is used to set the contract's state variables. It takes the following:

**Parameters:**

<table><thead><tr><th width="167.33333333333331">Name</th><th width="142">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>bank_</code></td><td>IBank</td><td>An interface for the Bank contract that manages positions and collateral</td></tr><tr><td><code>werc20_</code></td><td>address</td><td>The address of the WERC20 contract used to wrap collateral tokens</td></tr><tr><td><code>weth_</code></td><td>address</td><td>The address of the WETH contract used to wrap ETH</td></tr><tr><td><code>wichiFarm_</code></td><td>address</td><td>The address of the WIchiFarm contract used to interact with the ICHI farming system</td></tr></tbody></table>

#### addStrategy

{% code overflow="wrap" %}

```solidity
function addStrategy(address vault, uint256 maxPosSize) external onlyOwner
```

{% endcode %}

This function is used to add a new strategy to the contract. The function is marked as external and can only be called by the contract's owner. The function first checks that the `vault` parameter is not an empty address and that the `maxPosSize` parameter is greater than zero. Then, a new `Strategy` struct is created with the `vault` and `maxPosSize` parameters and added to the `strategies` array. An event is emitted with the index of the new strategy, the vault address, and the maximum position size.

**Parameters:**

<table><thead><tr><th width="173.33333333333331">Name</th><th width="119">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>vault</code></td><td>address</td><td>The address of the ICHI vault used for the strategy</td></tr><tr><td><code>maxPosSize</code></td><td>uint256</td><td>The maximum size of a position for the given vault, expressed in USD and based on 1e18</td></tr></tbody></table>

#### \_deposit

{% code overflow="wrap" %}

```solidity
function _deposit(OpenPosParam calldata param) internal
```

{% endcode %}

This function is an internal function that deposits assets onto an ICHI Vault as part of an open position. The function starts by getting the strategy information for the given `strategyId` using the `strategies` array. It then executes three main steps:

1. Deposit isolated collaterals on Blueberry Money Market
2. Borrow specific amounts
3. Add liquidity - Deposit on ICHI Vault

Step 1 is done by calling the `_doLend` function, which deposits the collateral into the Blueberry Money Market. Step 2 is done by calling the `_doBorrow` function, which borrows the specified amount of tokens from the Blueberry Money Market.

Step 3 involves adding liquidity by depositing the borrowed tokens into the ICHI Vault. The function starts by checking if the borrow token is one of the tokens supported by the ICHI Vault using the `token0` and `token1` functions of the ICHI Vault contract. If the borrow token is not supported by the ICHI Vault, the function reverts with an error message.

The function then approves the transfer of the borrowed tokens to the ICHI Vault using the `_ensureApprove` function. It then calls the `deposit` function of the ICHI Vault contract, passing in the amount of tokens to deposit and the address of the current contract as the recipient of the ICHI Vault shares. The function stores the returned ICHI Vault shares in the `ichiVaultShare` variable.

After adding liquidity to the ICHI Vault, the function validates the maximum LTV and maximum position size for the current strategy using the `_validateMaxLTV` and `_validateMaxPosSize` functions, respectively. If either validation fails, the function reverts with an error message.

**Parameters:**

* `OpenPosParam` (struct): A struct containing the parameters for the open position.

#### openPosition

{% code overflow="wrap" %}

```solidity
function openPosition(OpenPosParam calldata param) external exisitingStrategy(param.strategyId) existingCollateral(param.strategyId, param.collToken)
```

{% endcode %}

This is an external function that is used to deposit assets on the IchiVault. It takes in an OpenPosParam struct as its only parameter which contains the necessary information to open a new position. The function performs the following steps:

1. It checks that the strategy with the given ID exists in the system.
2. It checks that the collateral token associated with the given strategy also exists in the system.
3. It calls the internal `_deposit` function to deposit the required assets on the IchiVault.
4. It puts the ICHI Vault LP token as collateral in the bank.

**Parameters:**

* `OpenPosParam` (struct): A struct containing the parameters to open a new position. Which includes the following fields -&#x20;
  * `strategyId` `uint256:` representing the ID of the strategy to use.
  * `collToken` `address:` representing the address of the collateral token.
  * `borrowToken` `address:` representing the address of the token to borrow.
  * `collAmount` `uint256:` representing the number of collateral to deposit.
  * `borrowAmount` `uint256:` representing the number of tokens to borrow.
  * `farmingPid` `uint256:` representing the ID of the farming pool.

#### openPositionFarm

{% code overflow="wrap" %}

```solidity
function openPositionFarm(OpenPosParam calldata param) external existingStrategy(param.strategyId) existingCollateral(param.strategyId, param.collToken)
```

{% endcode %}

An external function that allows a user to deposit assets on IchiVault and farm in Ichi Farm. It checks that the given strategy, collateral token, and farming pool ID are existing in the contract. The function calls the `_deposit` function and then takes out the collateral, deposits on the farming pool, and puts the ICHI Vault LP token as collateral.

**Parameters:**

* `OpenPosParam` (struct): A struct containing the parameters to open a new position. Which includes the following fields -&#x20;
  * `strategyId` `uint256:` representing the ID of the strategy to use.
  * `collToken` `address:` representing the address of the collateral token.
  * `borrowToken` `address:` representing the address of the token to borrow.
  * `collAmount` `uint256:` representing the number of collateral to deposit.
  * `borrowAmount` `uint256:` representing the number of tokens to borrow.
  * `farmingPid` `uint256:` representing the ID of the farming pool.

#### \_withdraw

{% code overflow="wrap" %}

```solidity
function _withdraw(ClosePosParam calldata param) internal
```

{% endcode %}

This is an internal function to withdraw assets from ICHI Vault, swap withdrawn assets to debt token, withdraw isolated collaterals from Blueberry Money Market, repay debt, and refund the rest to the user.

**Parameters:**

* `ClosePosParam`(struct): Is a struct that contains the following-&#x20;
  * `strategyId`(uint256): representing the id of the strategy.
  * `amountLpRemove`(uint256): representing the amount of liquidity pool token to remove.
  * `sellSlippage`(uint256): representing the slippage percentage for the swap.
  * `borrowToken`(address): representing the token to borrow.
  * `collToken`(address): representing the collateral token to use.
  * `sqrtRatioLimit`(uint160): representing the square root of the price ratio limit.
  * `amountRepay`(uint256): representing the amount of debt to repay.
  * `amountShareWithdraw`(uint256): representing the amount of isolated collateral to withdraw.

**Function Steps:**

1. Check if `param.sellSlippage` is less than or equal to the maximum slippage set in the bank's configuration. If it is greater than the maximum slippage, revert the transaction with an error message.
2. Get the strategy using the `param.strategyId`.
3. Get the ICHI vault instance using the `strategy.vault` address.
4. Compute the amount of debt to repay. If `param.amountRepay` is `type(uint256).max`, set `amountRepay` to the current debt of the position using `bank.currentPositionDebt(positionId)`.
5. Calculate the actual amount to remove. If `param.amountLpRemove` is `type(uint256).max`, set `amountLpRemove` to the current balance of the contract in the ICHI vault using `vault.balanceOf(address(this))`.
6. Withdraw liquidity from the ICHI vault using `vault.withdraw(amountLpRemove, address(this))`.
7. Determine if the token to swap is `token0` or `token1` and calculate the amount to swap. If the amount is greater than 0, swap the token using `swapPool.swap()`.
8. Withdraw isolated collateral from the bank using `_doWithdraw()`.
9. Repay the debt using `_doRepay()`.
10. Validate the maximum loan-to-value ratio using `_validateMaxLTV()`.
11. Refund the remaining tokens to the user using `_doRefund()`.

#### closePosition

{% code overflow="wrap" %}

```solidity
function closePosition(ClosePosParam calldata param) external existingStrategy(param.strategyId) existingCollateral(param.strategyId, param.collToken)
```

{% endcode %}

This is an external function to withdraw assets from ICHI Vault

**Parameters:**

* `ClosePosParam`(struct): Is a struct that contains the following-&#x20;
  * `strategyId`(uint256): representing the id of the strategy.
  * `amountLpRemove`(uint256): representing the amount of liquidity pool token to remove.
  * `sellSlippage`(uint256): representing the slippage percentage for the swap.
  * `borrowToken`(address): representing the token to borrow.
  * `collToken`(address): representing the collateral token to use.
  * `sqrtRatioLimit`(uint160): representing the square root of the price ratio limit.
  * `amountRepay`(uint256): representing the amount of debt to repay.
  * `amountShareWithdraw`(uint256): representing the amount of isolated collateral to withdraw.

#### closePositionFarm

{% code overflow="wrap" %}

```solidity
function closePositionFarm(ClosePosParam calldata param) external existingStrategy(param.strategyId) existingCollateral(param.strategyId, param.collToken)
```

{% endcode %}

This function is an external function that allows a user to close their position in a farming strategy. The function first validates that the specified collateral token is correct and then removes the collateral token from the Bank. It then burns the withdrawn collateral token from the wIchiFarm and refunds the rewards. The function then calls the `_withdraw` function to remove liquidity and ends by refunding the ICHI token.

**Parameters:**&#x20;

`ClosePosParam`(struct): Is a struct that contains the following-&#x20;

* `strategyId`(uint256): representing the id of the strategy.
* `collToken`(address): the address of the collateral token to be used
* `borrowToken`(address): representing the token to borrow.
* `amountRepay`(uint256): representing the amount of debt to repay.
* `amountLpRemove`(uint256): representing the amount of liquidity pool token to remove.
* `amountShareWithdraw`(uint256): representing the amount of isolated collateral to withdraw.
* `sqrtRatioLimit`(uint160): representing the square root of the price ratio limit.
* `sellSlippage`(uint256): representing the slippage percentage for the swap.

#### uinswapV3 SwapCallback&#x20;

{% code overflow="wrap" %}

```solidity
function uniswapV3SwapCallback(in256 amount0Delta, int256 amount1Delta, bytes calldata data) external override
```

{% endcode %}

This function is a callback function that is called by a Uniswap V3 pool contract after a swap transaction is completed. The function checks if the caller is the correct pool contract and transfers the swapped tokens to the appropriate address.

**Parameters:**

<table><thead><tr><th width="180.33333333333331">Name</th><th width="224">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>amount0Delta</code></td><td>int256</td><td>The change in token0 amount</td></tr><tr><td><code>amount1Delta</code></td><td>int256</td><td>The change in token1 amount</td></tr><tr><td><code>data</code></td><td>bytes calldata</td><td>Encoded address of the payer</td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://v1.docs.blueberry.garden/developer-guides/contracts/spell/ichispell.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
