# Introduction

## About EVO

**EVO** is a non-custodial, concentrated liquidity market maker (CLMM) built on the **Supra Network**. It leverages Supra’s high-performance architecture to deliver secure, scalable, and user-friendly decentralized trading. EVO aims to make DeFi more efficient, accessible, and aligned with the needs of both liquidity providers and traders.

## Core Principles

### Capital Efficiency by Design

Through concentrated liquidity, EVO allows users to provide liquidity within specific price ranges—making capital work harder and increasing yield potential with less idle funds.

### Tools for Liquidity Providers

EVO gives LPs full control over their positions. Liquidity can be actively managed and adjusted in real time, allowing providers to respond to market changes, optimize exposure, and improve risk management.

### Simplifying DeFi

EVO is built with simplicity in mind. The interface and mechanics are designed to be intuitive, making it easy for anyone—regardless of experience level—to swap, provide liquidity, and interact with DeFi markets.

### Growing the Supra Ecosystem

EVO provides essential liquidity infrastructure for the Supra Network, helping new and existing projects connect to a deep, flexible trading environment.


# About Concentrated Liquidity

## Introduction

The core concept behind EVO is **concentrated liquidity**—a system where liquidity providers (LPs) allocate capital within specific price ranges rather than across the entire price spectrum. This contrasts with earlier AMM models that distributed liquidity uniformly between 0 and infinity, regardless of how much of that range was actually used in trading.

In practice, only a small portion of the total liquidity in traditional AMMs is used efficiently. For example, in stablecoin pairs where prices rarely move far from parity, the vast majority of liquidity outside the typical $0.99–$1.01 range is unused—effectively idle capital.

EVO allows LPs to define custom price ranges for their liquidity. In a stablecoin/stablecoin pool, for instance, an LP can focus their capital specifically within the $0.99–$1.01 band. This increases liquidity density where it's most needed, reducing price impact for traders and maximizing fee earnings for LPs. Each custom range is called a **position**, and LPs can maintain multiple positions per pool to tailor their strategies.

## Active Liquidity

As market prices move, the spot price may enter or exit the price ranges defined by LPs. A position is considered **active** when the current price falls within its specified range, and only active positions are eligible to earn fees.

When the price exits a position’s range, the underlying liquidity becomes **inactive**—no longer participating in trades or generating fees. As swaps occur and prices shift, LPs may end up holding one asset entirely, depending on the direction of trades. If the market re-enters their range, their position becomes active again and resumes earning fees.

LPs have the flexibility to create multiple positions with different ranges, enabling a variety of custom liquidity provisioning strategies. Concentrated liquidity allows the market to self-regulate liquidity distribution, as LPs are incentivized to place their liquidity where it will be both active and profitable.

## Ticks

EVO’s implementation of concentrated liquidity is powered by a system of **ticks**, which divide the price spectrum into discrete intervals.

Each tick represents a boundary in price space, spaced so that moving up or down by 1 tick corresponds to a 0.01% price change. When creating a position, LPs select a **lower tick** and an **upper tick** to define the active price range for their liquidity.

During swaps, the protocol processes trades by consuming liquidity from the current tick interval. As the price moves and reaches the boundary of the current tick, the protocol **crosses** into the next tick. If any LP positions use the new tick as a boundary, their liquidity is activated as the price enters the tick range.

Tick spacing varies by fee tier. Lower fee pools allow tighter tick intervals, enabling greater precision in liquidity placement and higher capital efficiency. Higher fee tiers use wider tick spacing, which may be more suitable for volatile or long-tail assets where fewer trades are expected.

Crossing active ticks incurs additional gas costs due to the need to activate or deactivate liquidity positions. However, inactive ticks themselves do not impact swap costs.

For pools where tight price control is essential—such as stablecoin pairs—narrow tick spacing significantly improves execution quality. More granular liquidity placement leads to lower slippage and better prices for traders.


# Fees

## Swap Fees

In EVO, swap fees are allocated proportionally to all active liquidity positions within range at the moment a trade occurs. When the current price moves outside a position’s specified range, that liquidity becomes inactive and stops earning fees. If the market price moves back into the range, the liquidity reactivates and resumes collecting fees.

Unlike AMMs where fees are automatically reinvested back in the LP positions, EVO separates fee earnings from the pool’s liquidity. Collected fees must be claimed manually by the position owner whenever they choose to harvest their earnings.

## Pool Fee Tiers

EVO supports multiple liquidity pools for each token pair, each configured with a distinct swap fee. When creating a pool, liquidity providers can select from predefined fee options such as 0.01%, 0.05%, 0.25%, and 1.00%.&#x20;

In traditional AMM designs, fragmenting liquidity across separate pools is impractical because it reduces the depth of each individual market, resulting in higher slippage for traders. However, concentrated liquidity in EVO decouples total liquidity from its distribution, meaning that even fragmented pools can maintain strong execution quality if liquidity is well-placed.

By enabling fine-tuned control over price ranges and fees, EVO allows for more specialized pools tailored to different asset profiles—particularly those poorly served by a one-size-fits-all fee structure.

## Selecting the Appropriate Fee Tier

We anticipate that certain types of assets will gravitate towards specific fee tiers, based on where the incentives for both swappers and liquidity providers come nearest to alignment.

Stablecoins and other low-volatility assets will often be found in low-fee pools (e.g. 0.01%–0.05%), where LPs face minimal price exposure and traders seek near-parity execution.

On the other hand, higher-risk or less frequently traded tokens are more likely to thrive in higher-fee pools (e.g. 0.25%–1.00%), where LPs are better compensated for the additional risk of impermanent loss and market volatility.


# Price Ranges

## How Do Liquidity Price Ranges Work?

In concentrated liquidity market maker (CLMM) pools, users set specific price ranges where they provide liquidity. Liquidity providers (LPs) earn fees based on their share of liquidity at the current market price. This encourages LPs to actively manage their positions to keep the price within their selected range.

If the market price moves outside an LP's chosen range, their position stops earning fees and becomes inactive. LPs may also face higher impermanent loss. Similar to traditional AMM pools, when the base token price rises, traders swap the quote token for the base token, leaving the pool—and the LP—with more of the quote token and less of the base token.

In CLMMs, these effects happen faster within the chosen range:

* If the price falls below the minimum range, the LP’s position becomes fully composed of the base token.
* If the price rises above the maximum range, the LP’s position fully converts to the quote token.

This setup gives LPs more control over their liquidity and the chance for higher returns. However, it also requires careful monitoring to avoid being out of range and missing out on fees.


# Active and Inactive Liquidity

As asset prices change, they may move beyond the price range defined by LPs. When this happens, liquidity for that position becomes inactive, and fees stop accumulating until the price returns to the defined range.

When prices shift, LPs accumulate more of one asset as trades occur. This continues until the position holds only one asset. However, unlike traditional models, concentrated liquidity allows LPs to avoid extremes (e.g., 0 or ∞) by setting precise price intervals. Once the price reenters the defined range, the position becomes active again, and LPs resume earning fees.

LPs can also create multiple positions with different price ranges, offering flexibility to spread liquidity across various ranges. This approach helps maximize earnings while keeping liquidity active as often as possible.

Concentrated liquidity provides LPs with detailed control over their strategies, letting them focus liquidity where it’s most effective. This supports higher returns and promotes a more efficient trading system overall.


# LP NFT Positions

## Liquidity Position Ownership with NFTs

Each liquidity position is linked to an LP Position NFT, giving liquidity providers full ownership and control over their position. This NFT keeps track of fees and rewards earned within the chosen price range for the specific liquidity pool where funds are deposited.

These NFTs are transferable, enabling LPs to transfer ownership or sell their positions on secondary NFT marketplaces.

## **Why Use NFTs for Liquidity Positions?**

NFTs are ideal for storing unique data about liquidity positions. They securely record details such as price ranges, the amount of tokens provided, and fees earned. This structure allows for transparency, flexibility, and easy transferability, making NFTs a practical choice for representing liquidity ownership.


# AMM


# Router

## **Contract Info**

* **Contract Name**: `evo::router`
* **Contract Address**: \[tba]
* **Admin Multi Sig**: \[tba]

### Public Functions

***

#### **Create Pair**

Creates a new liquidity pair for tokens X and Y. Reverts if the pair already exists.

```move
public entry fun create_pair<X, Y>(sender: &signer)
```

| Input Values | Type   | Description          |
| ------------ | ------ | -------------------- |
| sender       | signer | The sender's signer. |

***

#### **Register Fee On Transfer in Pair**

Adds fee-on-transfer functionality to a token pair (only callable by token owners).

```move
public entry fun register_fee_on_transfer_in_a_pair<CoinType, X, Y>(sender: &signer)
```

| Input Values | Type   | Description          |
| ------------ | ------ | -------------------- |
| sender       | signer | The sender's signer. |

***

#### **Stake Tokens in Pool**

Deposit tokens into the staking pool for a liquidity pair.

```move
public entry fun stake_tokens_in_pool<X, Y>(sender: &signer, amount: u64)
```

| Input Values | Type   | Description                    |
| ------------ | ------ | ------------------------------ |
| sender       | signer | The sender's signer.           |
| amount       | u64    | The amount of tokens to stake. |

***

#### **Unstake Tokens from Pool**

Withdraw tokens from the staking pool for a liquidity pair.

```move
public entry fun unstake_tokens_from_pool<X, Y>(sender: &signer, amount: u64)
```

| Input Values | Type   | Description                       |
| ------------ | ------ | --------------------------------- |
| sender       | signer | The sender's signer.              |
| amount       | u64    | The amount of tokens to withdraw. |

***

#### **Claim Rewards from Pool**

Claim staking rewards from the rewards pool.

```move
public entry fun claim_rewards_from_pool<X, Y>(sender: &signer)
```

| Input Values | Type   | Description          |
| ------------ | ------ | -------------------- |
| sender       | signer | The sender's signer. |

***

#### **Add Liquidity**

Add liquidity to a pair or create the pair if it doesn't exist.

```move
public entry fun add_liquidity<X, Y>(sender: &signer, amount_x_desired: u64, amount_y_desired: u64, amount_x_min: u64, amount_y_min: u64)
```

| Input Values       | Type   | Description                           |
| ------------------ | ------ | ------------------------------------- |
| sender             | signer | The sender's signer.                  |
| amount\_x\_desired | u64    | The amount of token X desired.        |
| amount\_y\_desired | u64    | The amount of token Y desired.        |
| amount\_x\_min     | u64    | The minimum amount of token X to add. |
| amount\_y\_min     | u64    | The minimum amount of token Y to add. |

***

#### **Remove Liquidity**

Remove liquidity from a pair.

```move
public entry fun remove_liquidity<X, Y>(sender: &signer, liquidity: u64, amount_x_min: u64, amount_y_min: u64)
```

| Input Values   | Type   | Description                               |
| -------------- | ------ | ----------------------------------------- |
| sender         | signer | The sender's signer.                      |
| liquidity      | u64    | The amount of liquidity to remove.        |
| amount\_x\_min | u64    | The minimum amount of token X to receive. |
| amount\_y\_min | u64    | The minimum amount of token Y to receive. |

***

#### **Swap Exact Input**

Swap an exact input amount of token X for the maximum possible amount of token Y.

```move
public entry fun swap_exact_input<X, Y>(sender: &signer, x_in: u64, y_min_out: u64)
```

| Input Values | Type   | Description                               |
| ------------ | ------ | ----------------------------------------- |
| sender       | signer | The sender's signer.                      |
| x\_in        | u64    | The exact amount of token X to swap.      |
| y\_min\_out  | u64    | The minimum amount of token Y to receive. |

***

#### **Swap Exact Output**

Swap the minimum possible amount of token X to receive an exact output amount of token Y.

```move
public entry fun swap_exact_output<X, Y>(sender: &signer, y_out: u64, x_max_in: u64)
```

| Input Values | Type   | Description                             |
| ------------ | ------ | --------------------------------------- |
| sender       | signer | The sender's signer.                    |
| y\_out       | u64    | The exact amount of token Y to receive. |
| x\_max\_in   | u64    | The maximum amount of token X to swap.  |

***

#### **Multi-Hop Exact Input**

Swap token X for token Y through an intermediate token Z.

```move
public entry fun swap_exact_input_with_one_intermediate_coin<X, Y, Z>(sender: &signer, x_in: u64, y_min_out: u64)
```

| Input Values | Type   | Description                               |
| ------------ | ------ | ----------------------------------------- |
| sender       | signer | The sender's signer.                      |
| x\_in        | u64    | The exact amount of token X to swap.      |
| y\_min\_out  | u64    | The minimum amount of token Y to receive. |

***

#### **Register LP**

Register the LP token for a pair to the sender's account.

```move
public entry fun register_lp<X, Y>(sender: &signer)
```

| Input Values | Type   | Description          |
| ------------ | ------ | -------------------- |
| sender       | signer | The sender's signer. |

***

#### **Update Fee Tier**

Update the fee tier for a liquidity pair.

```move
public entry fun update_fee_tier<Tier, X, Y>(signer_ref: &signer)
```

| Input Values | Type   | Description          |
| ------------ | ------ | -------------------- |
| signer\_ref  | signer | The sender's signer. |


# Aggregator Integration

To integrate the EVO AMM with your aggregator, use the following public functions for swap calculations.

#### Get Amount In <a href="#get-amount-in" id="get-amount-in"></a>

`router::get_amount_in`

**Description**

This function calculates the required input amount of token **X** to receive a specific output amount of token **Y**.

**Usage**

* **Checks**: Ensures that a pair exists between token **X** and token **Y** before proceeding.
* **Returns**: The amount of token **X** required for the swap.

**Parameters**

| Input Value    | Type  | Description                               |
| -------------- | ----- | ----------------------------------------- |
| `y_out_amount` | `u64` | The desired output amount of token **Y**. |

**Code**

```
public fun get_amount_in<X, Y>(y_out_amount: u64): u64 {
    assert!(swap::is_pair_created<X, Y>(), errors::pair_not_created());
    let is_x_to_y = swap_utils::sort_token_type<X, Y>();
    get_amount_in_internal<X, Y>(is_x_to_y, y_out_amount)
}
```

***

#### Get Amount Out <a href="#get-amount-out" id="get-amount-out"></a>

`router::get_amount_out`

**Description**

This function calculates the output amount of token **Y** given an input amount of token **X**.

**Usage**

* **Checks**: Ensures that a pair exists between token **X** and token **Y** before proceeding.
* **Returns**: The amount of token **Y** that will be received for the swap.

**Parameters**

| Input Value   | Type  | Description                      |
| ------------- | ----- | -------------------------------- |
| `x_in_amount` | `u64` | The input amount of token **X**. |

**Code**

```
public fun get_amount_out<X, Y>(x_in_amount: u64): u64 {
    assert!(swap::is_pair_created<X, Y>(), errors::pair_not_created());
    let is_x_to_y = swap_utils::sort_token_type<X, Y>();
    get_amount_out_internal<X, Y>(is_x_to_y, x_in_amount)
} 
```


# Swap

### **Contract Info**

* **Contract Name**: `evo::swap`
* **Contract Address**: \[tba]
* **Admin Multi Sig**: \[tba]

### Types

| Name | Type         | Description                                   |
| ---- | ------------ | --------------------------------------------- |
| X    | type address | The coin type address of token X in the pair. |
| Y    | type address | The coin type address of token Y in the pair. |

### Resources

#### **LPToken**

The liquidity token corresponds to each pool XY.

```move
struct LPToken<phantom X, phantom Y> has key {}
```

***

#### **TokenPairMetadata**

Metadata related to the token pair and liquidity pool.

```move
struct TokenPairMetadata<phantom X, phantom Y> has key {
    creator: address,
    fee_on_transfer_x: Option<FeeOnTransferInfo<X>>,
    fee_on_transfer_y: Option<FeeOnTransferInfo<Y>>,
    k_last: u128,
    liquidity_fee: u128,
    rewards_fee: u128,
    team_fee: u128,
    treasury_fee: u128,
    balance_x: coin::Coin<X>,
    balance_y: coin::Coin<Y>,
    mint_cap: coin::MintCapability<LPToken<X, Y>>,
    burn_cap: coin::BurnCapability<LPToken<X, Y>>,
    freeze_cap: coin::FreezeCapability<LPToken<X, Y>>,
}
```

| Name          | Type                 | Description                                                   |
| ------------- | -------------------- | ------------------------------------------------------------- |
| creator       | address              | The creator address of the pool.                              |
| k\_last       | u128                 | The last recorded reserve product (reserve\_x \* reserve\_y). |
| balance\_x    | coin::Coin           | The total amount of token X in the pool.                      |
| balance\_y    | coin::Coin           | The total amount of token Y in the pool.                      |
| mint\_cap     | coin::MintCapability | Capability to mint LP tokens.                                 |
| burn\_cap     | coin::BurnCapability | Capability to burn LP tokens.                                 |
| treasury\_fee | u128                 | The fee collected by the treasury.                            |

***

#### **TokenPairReserve**

Reserve balances and metadata related to liquidity reserves.

```move
struct TokenPairReserve<phantom X, phantom Y> has key {
    reserve_x: u64,
    reserve_y: u64,
    block_timestamp_last: u64
}
```

| Name                   | Type | Description                              |
| ---------------------- | ---- | ---------------------------------------- |
| reserve\_x             | u64  | The total amount of token X in the pool. |
| reserve\_y             | u64  | The total amount of token Y in the pool. |
| block\_timestamp\_last | u64  | The last time the reserves were updated. |

***

### Public Functions

#### **Register LP**

Register the LP token to the account.

```move
public fun register_lp<X, Y>(sender: &signer)
```

#### **Is Pair Created**

Check if the pool XY is created or not.

```move
public fun is_pair_created<X, Y>(): bool
```

#### **LP Balance**

Check the LP balance of a user.

```move
public fun lp_balance<X, Y>(addr: address): u64
```

#### **Total LP Supply**

Retrieve the total amount of LP tokens in the pool.

```move
public fun total_lp_supply<X, Y>(): u128
```

#### **Token Reserves**

Retrieve the reserves of the token pair XY.

```move
public fun token_reserves<X, Y>(): (u64, u64, u64)
```

#### **Token Balance**

Retrieve the token balances in the pool XY.

```move
public fun token_balances<X, Y>(): (u64, u64)
```


# CLMM


# Liquidity Pool

## Module Info <a href="#module-info" id="module-info"></a>

* **Name**: <mark style="color:green;">`evo::liquidity_pool`</mark>
* **Description**: This module contains the core logic for the liquidity pool of the <mark style="color:green;">`evo`</mark> contract. This module only works with fungible assets. If you want to use coins, please check the <mark style="color:green;">`router`</mark> module, which contains functions to work with coins.

## Public Functions

### Swap releated functions

The <mark style="color:green;">`liquidity_pool`</mark> uses the <mark style="color:green;">`"Hot potato"`</mark> pattern for swapping feature.

### Swap Functions

***

Swaps tokens in the liquidity pool. This function returns a <mark style="color:green;">`SwapReciept`</mark> object and requires to pay back in the same transaction to complete (<mark style="color:green;">`"Hot potato"`</mark> pattern).

```
public fun swap(
    trader: &signer,
    pool: Object<LiquidityPool>,
    zero_for_one: bool,
    is_exact_in: bool,
    specified_amount: u64,
    sqrt_price_limit: u128,
): (FungibleAsset, SwapReciept)
```

#### Function arguments

| Argument           | Type     | Description                                                                                                                                               |
| ------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| trade              | \&signer | The trader’s signer.                                                                                                                                      |
| pool               | Object   | The liquidity pool.                                                                                                                                       |
| zero\_for\_one     | bool     | Direction of the swap. <mark style="color:green;">`true`</mark> for token 0 to token 1, <mark style="color:green;">`false`</mark> for token 1 to token 0. |
| is\_exact\_in      | bool     | Whether the specified amount is the exact input amount.                                                                                                   |
| specified\_amount  | u64      | The specified amount for the swap.                                                                                                                        |
| sqrt\_price\_limit | u128     | The sqrt price limit for the swap.                                                                                                                        |

#### Returns

| Type          | Description                |
| ------------- | -------------------------- |
| FungibleAsset | The swapped fungible asset |
| SwapReciept   | The swap receipt.          |

#### SwapReciept

```
struct SwapReciept {
    pool: Object<LiquidityPool>,
    token_metadata: Object<Metadata>,
    amount_in: u64,
}
```

| Field           | Type   | Description                                           |
| --------------- | ------ | ----------------------------------------------------- |
| pool            | Object | The liquidity pool of the swap.                       |
| token\_metadata | Object | The metadata of the token in of the swap.             |
| amount\_in      | u64    | The amount of token in needs to be paid for the swap. |

### Get swap receipt amount

***

Gets the amount from a <mark style="color:green;">`SwapReciept`</mark>.

```
public fun get_swap_receipt_amount(swap_receipt: &SwapReciept): u64
```

#### Function arguments

| Argument      | Type          | Description       |
| ------------- | ------------- | ----------------- |
| swap\_receipt | \&SwapReciept | The swap receipt. |

#### Returns

| Type | Description                |
| ---- | -------------------------- |
| u64  | The amount in the receipt. |

### Get swap receipt token metadata

***

Gets the token metadata from a <mark style="color:green;">`SwapReciept`</mark>.

```
public fun get_swap_receipt_token_metadata(swap_receipt: &SwapReciept): Object<Metadata>
```

#### Function arguments

| Argument      | Type          | Description   |
| ------------- | ------------- | ------------- |
| swap\_receipt | \&SwapReciept | \&SwapReciept |

#### Returns

| Type   | Description                        |
| ------ | ---------------------------------- |
| Object | The token metadata in the receipt. |

### Pay swap

***

Pays the swap using the provided token and receipt.

```
public fun pay_swap(
    token_in: FungibleAsset,
    reciept: SwapReciept,
)
```

#### Function arguments

| Argument  | Type          | Description               |
| --------- | ------------- | ------------------------- |
| token\_in | FungibleAsset | The input fungible asset. |
| receipt   | SwapReciept   | The swap receipt.         |

### Quote swap

***

Quotes a swap in the liquidity pool without executing it.

```
public fun quote_swap(
    trader: address,
    pool: Object<LiquidityPool>,
    zero_for_one: bool,
    is_exact_in: bool,
    specified_amount: u64,
    sqrt_price_limit: u128,
): (u64, u64, u64)
```

#### Function arguments

| Argument           | Type    | Description                                                                                                                                               |
| ------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| trader             | address | The trader’s address.                                                                                                                                     |
| pool               | Object  | The liquidity pool.                                                                                                                                       |
| zero\_for\_one     | bool    | Direction of the swap. <mark style="color:green;">`true`</mark> for token 0 to token 1, <mark style="color:green;">`false`</mark> for token 1 to token 0. |
| is\_exact\_in      | bool    | Whether the specified amount is the exact input amount.                                                                                                   |
| specified\_amount  | u64     | The specified amount for the swap.                                                                                                                        |
| sqrt\_price\_limit | u128    | The sqrt price limit for the swap.                                                                                                                        |

#### Returns

| Type | Description                  |
| ---- | ---------------------------- |
| u64  | The amount of token in.      |
| u64  | The amount of token out.     |
| u64  | The fee amount for the swap. |


# Router

## Module info

* **Name**: <mark style="color:green;">`evo::router`</mark>
* **Description**: This module contains public functions for other modules/contracts to call and interact with the <mark style="color:green;">`evo`</mark> contract.

## Public Functions <a href="#public-functions" id="public-functions"></a>

### Create Pool <a href="#create-pool" id="create-pool"></a>

**Create pool with two fungible assets**

***

Creates a new liquidity pool for two fungible assets. Reverts if the pool already exists.

```
public fun create_pool(
    creator: &signer,
    token_0: Object<Metadata>,
    token_1: Object<Metadata>,
    fee: u64,
    sqrt_price: u128,
)
```

**Function arguments**

| Argument    | Type     | Description                        |
| ----------- | -------- | ---------------------------------- |
| creator     | \&signer | The creator’s signer               |
| token\_0    | Object   | Fungible asset metadata of token 0 |
| token\_1    | Object   | Fungible asset metadata of token 1 |
| fee         | u64      | Fee tier of the pool               |
| sqrt\_price | u128     | Initial sqrt price of the pool     |

### Create pool with one coin and one fungible asset <a href="#create-pool-with-one-coin-and-one-fungible-asset" id="create-pool-with-one-coin-and-one-fungible-asset"></a>

***

Creates a new liquidity pool with one coin (<mark style="color:green;">`Token0`</mark>) and one fungible asset. Reverts if the pool already exists.

```
public fun create_pool_one_coin<Token0>(
    creator: &signer,
    token_1: Object<Metadata>,
    fee: u64,
    sqrt_price: u128,
)
```

**Function type arguments**

| Argument | Description      |
| -------- | ---------------- |
| Token0   | The coin’s type. |

**Function arguments**

| Argument    | Type     | Description                        |
| ----------- | -------- | ---------------------------------- |
| creator     | \&signer | The creator’s signer               |
| token\_1    | Object   | Fungible asset metadata of token 1 |
| fee         | u64      | Fee tier of the pool               |
| sqrt\_price | u128     | Initial sqrt price of the pool     |

### Create pool with two coins <a href="#create-pool-with-two-coins" id="create-pool-with-two-coins"></a>

***

Creates a new liquidity pool with two coins <mark style="color:green;">`Token0`</mark> and <mark style="color:green;">`Token1`</mark>. Reverts if the pool already exists.

```
public fun create_pool_both_coins<Coin0, Coin1>(
    creator: &signer,
    fee: u64,
    sqrt_price: u128,
)
```

**Function type arguments**

| Argument | Description                    |
| -------- | ------------------------------ |
| Coin0    | The coin’s type of the token 0 |
| Coin1    | The coin’s type of the token 1 |

**Function arguments**

| Argument    | Type     | Description                     |
| ----------- | -------- | ------------------------------- |
| creator     | \&signer | The creator’s signer.           |
| fee         | u64      | Fee tier of the pool.           |
| sqrt\_price | u128     | Initial sqrt price of the pool. |

## Add liquidity

### Add liquidity to a pool with two fungible assets

***

Adds liquidity to a pool with two fungible assets.

```
public fun add_liquidity(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    tick_lower: u32,
    tick_upper: u32,
    token_0: FungibleAsset,
    token_1: FungibleAsset,
    amount_0_min: u64,
    amount_1_min: u64,
): (FungibleAsset, FungibleAsset)
```

**Function arguments**

| Argument       | Type          | Description                                                                                                              |
| -------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------ |
| user           | \&signer      | The user’s signer.                                                                                                       |
| pool           | Object        | The liquidity pool to add liquidity to.                                                                                  |
| position\_id   | u64           | The position ID of the liquidity. Leave it as 0 if you want to create a new position or you don’t have any position yet. |
| tick\_lower    | u32           | The lower tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| tick\_upper    | u32           | The upper tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| token\_0       | FungibleAsset | The amount of token 0 to add to the liquidity.                                                                           |
| token\_1       | FungibleAsset | The amount of token 1 to add to the liquidity.                                                                           |
| amount\_0\_min | u64           | The minimum amount of token 0 to add to the liquidity.                                                                   |
| amount\_1\_min | u64           | The minimum amount of token 1 to add to the liquidity.                                                                   |

**Returns**

| Type                           | Description                |
| ------------------------------ | -------------------------- |
| (FungibleAsset, FungibleAsset) | The added fungible assets. |

### Remove liquidity from a pool

***

Removes liquidity from a pool.

```
public fun remove_liquidity(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    liquidity: u128,
    amount_0_min: u64,
    amount_1_min: u64,
): (FungibleAsset, FungibleAsset)
```

**Function arguments**

| Argument       | Type     | Description                                  |
| -------------- | -------- | -------------------------------------------- |
| user           | \&signer | The user’s signer.                           |
| pool           | Object   | The liquidity pool to remove liquidity from. |
| position\_id   | u64      | The position ID of the liquidity.            |
| liquidity      | u128     | The amount of liquidity to remove.           |
| amount\_0\_min | u64      | The minimum amount of token 0 to get.        |
| amount\_1\_min | u64      | The minimum amount of token 1 to get.        |

**Returns**

| Type          | Description                                                           |
| ------------- | --------------------------------------------------------------------- |
| FungibleAsset | The returned fungible assets of the token 0 after removing liquidity. |
| FungibleAsset | The returned fungible assets of the token 1 after removing liquidity. |

### Collect fee

***

Collects fee from a position.

```
public fun collect_fee(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    amount_0_requested: u64,
    amount_1_requested: u64,
): (FungibleAsset, FungibleAsset)
```

**Function arguments**

| Argument             | Type     | Description                      |
| -------------------- | -------- | -------------------------------- |
| user                 | \&signer | The user’s signer.               |
| pool                 | Object   | The liquidity pool.              |
| position\_id         | u64      | The position ID.                 |
| amount\_0\_requested | u64      | The amount of token 0 requested. |
| amount\_1\_requested | u64      | The amount of token 1 requested. |

**Returns**

| Type          | Description                       |
| ------------- | --------------------------------- |
| FungibleAsset | The collected fee of the token 0. |
| FungibleAsset | The collected fee of the token 1. |

### Collect reward

***

Collects reward from a position.

```
public fun collect_reward(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    reward_index: u64,
    amount_requested: u64,
): FungibleAsset
```

**Function arguments**

| Argument          | Type     | Description                     |
| ----------------- | -------- | ------------------------------- |
| user              | \&signer | The user’s signer.              |
| pool              | Object   | The liquidity pool.             |
| position\_id      | u64      | The position ID.                |
| reward\_index     | u64      | The reward index.               |
| amount\_requested | u64      | The amount of reward requested. |

**Returns**

| Type          | Description           |
| ------------- | --------------------- |
| FungibleAsset | The collected reward. |

## Swap functions

### Swap exact fungible asset for fungible asset

***

Swaps an exact amount of fungible asset for another fungible asset.

```
public fun swap_exact_fa_for_fa(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: FungibleAsset,
    amount_out_min: u64,
    sqrt_price_limit: u128,
): FungibleAsset
```

**Function arguments**

| Argument           | Type          | Description                         |
| ------------------ | ------------- | ----------------------------------- |
| trader             | \&signer      | The trader’s signer.                |
| pool               | Object        | The liquidity pool.                 |
| token\_in          | FungibleAsset | The input token.                    |
| amount\_out\_min   | u64           | The minimum amount of output token. |
| sqrt\_price\_limit | u128          | The sqrt price limit.               |

**Returns**

| Type          | Description                 |
| ------------- | --------------------------- |
| FungibleAsset | The swapped fungible asset. |

### Swap exact fungible asset for coin

***

Swaps an exact amount of fungible asset for a coin.

```
public fun swap_exact_fa_for_coin<CoinType>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: FungibleAsset,
    amount_out_min: u64,
    sqrt_price_limit: u128,
): Coin<CoinType>
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument           | Type          | Description                         |
| ------------------ | ------------- | ----------------------------------- |
| trader             | \&signer      | The trader’s signer.                |
| pool               | Object        | The liquidity pool.                 |
| token\_in          | FungibleAsset | The input token.                    |
| amount\_out\_min   | u64           | The minimum amount of output token. |
| sqrt\_price\_limit | u128          | The sqrt price limit.               |

**Returns**

| Type | Description       |
| ---- | ----------------- |
| Coin | The swapped coin. |

### Swap exact coin for fungible asset

***

Swaps an exact amount of coin for a fungible asset.

```
public fun swap_exact_coin_for_fa<CoinType>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: Coin<CoinType>,
    amount_out_min: u64,
    sqrt_price_limit: u128,
): FungibleAsset
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument           | Type     | Description                         |
| ------------------ | -------- | ----------------------------------- |
| trader             | \&signer | The trader’s signer.                |
| pool               | Object   | The liquidity pool.                 |
| token\_in          | Coin     | The input coin.                     |
| amount\_out\_min   | u64      | The minimum amount of output token. |
| sqrt\_price\_limit | u128     | The sqrt price limit.               |

**Returns**

| Type          | Description                 |
| ------------- | --------------------------- |
| FungibleAsset | The swapped fungible asset. |

### Swap exact coin for coin

***

Swaps an exact amount of coin for another coin.

```
public fun swap_exact_coin_for_coin<CoinIn, CoinOut>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: Coin<CoinIn>,
    amount_out_min: u64,
    sqrt_price_limit: u128,
): Coin<CoinOut>
```

**Function type arguments**

| Argument | Description            |
| -------- | ---------------------- |
| CoinIn   | The input coin’s type  |
| CoinOut  | The output coin’s type |

**Function arguments**

| Argument           | Type     | Description                         |
| ------------------ | -------- | ----------------------------------- |
| trader             | \&signer | The trader’s signer.                |
| pool               | Object   | The liquidity pool.                 |
| token\_in          | Coin     | The input coin.                     |
| amount\_out\_min   | u64      | The minimum amount of output token. |
| sqrt\_price\_limit | u128     | The sqrt price limit.               |

**Returns**

| Type | Description       |
| ---- | ----------------- |
| Coin | The swapped coin. |

### Swap fungible asset for exact fungible asset

***

Swaps a fungible asset for an exact amount of another fungible asset.

```
public fun swap_fa_for_exact_fa(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: FungibleAsset,
    amount_out_desired: u64,
    sqrt_price_limit: u128,
): (FungibleAsset, FungibleAsset)
```

**Function arguments**

| Argument             | Type          | Description                         |
| -------------------- | ------------- | ----------------------------------- |
| trader               | \&signer      | The trader’s signer.                |
| pool                 | Object        | The liquidity pool.                 |
| token\_in            | FungibleAsset | The input token.                    |
| amount\_out\_desired | u64           | The desired amount of output token. |
| sqrt\_price\_limit   | u128          | The sqrt price limit.               |

**Returns**

| Type          | Description                                      |
| ------------- | ------------------------------------------------ |
| FungibleAsset | The remaining fungible asset of the input token. |
| FungibleAsset | The swapped fungible asset of the output token.  |

### Swap fungible asset for exact coin

***

Swaps a fungible asset for an exact amount of a coin.

```
public fun swap_fa_for_exact_coin<CoinType>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: FungibleAsset,
    amount_out_desired: u64,
    sqrt_price_limit: u128,
): (FungibleAsset, Coin<CoinType>)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument             | Type          | Description                         |
| -------------------- | ------------- | ----------------------------------- |
| trader               | \&signer      | The trader’s signer.                |
| pool                 | Object        | The liquidity pool.                 |
| token\_in            | FungibleAsset | The input token.                    |
| amount\_out\_desired | u64           | The desired amount of output token. |
| sqrt\_price\_limit   | u128          | The sqrt price limit.               |

**Returns**

| Type          | Description                                      |
| ------------- | ------------------------------------------------ |
| FungibleAsset | The remaining fungible asset of the input token. |
| Coin          | The swapped coin of the output token.            |

### Swap coin for exact fungible asset

***

Swaps a coin for an exact amount of a fungible asset.

```
public fun swap_coin_for_exact_fa<CoinType>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: Coin<CoinType>,
    amount_out_desired: u64,
    sqrt_price_limit: u128,
): (Coin<CoinType>, FungibleAsset)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument             | Type     | Description                         |
| -------------------- | -------- | ----------------------------------- |
| trader               | \&signer | The trader’s signer.                |
| pool                 | Object   | The liquidity pool.                 |
| token\_in            | Coin     | The input coin.                     |
| amount\_out\_desired | u64      | The desired amount of output token. |
| sqrt\_price\_limit   | u128     | The sqrt price limit.               |

**Returns**

| Type          | Description                                     |
| ------------- | ----------------------------------------------- |
| Coin          | The remaining coin of the input token.          |
| FungibleAsset | The swapped fungible asset of the output token. |

### Swap coin for exact coin

***

Swaps a coin for an exact amount of another coin.

```
public fun swap_coin_for_exact_coin<CoinIn, CoinOut>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: Coin<CoinIn>,
    amount_out_desired: u64,
    sqrt_price_limit: u128,
): (Coin<CoinIn>, Coin<CoinOut>)
```

**Function type arguments**

| Argument | Description            |
| -------- | ---------------------- |
| CoinIn   | The input coin’s type  |
| CoinOut  | The output coin’s type |

**Function arguments**

| Argument             | Type     | Description                         |
| -------------------- | -------- | ----------------------------------- |
| trader               | \&signer | The trader’s signer.                |
| pool                 | Object   | The liquidity pool.                 |
| token\_in            | Coin     | The input coin.                     |
| amount\_out\_desired | u64      | The desired amount of output token. |
| sqrt\_price\_limit   | u128     | The sqrt price limit.               |

**Returns**

| Type | Description                            |
| ---- | -------------------------------------- |
| Coin | The remaining coin of the input token. |
| Coin | The swapped coin of the output token.  |

### Swap exact fungible asset for fungible asset with multiple hops

***

Swaps an exact amount of fungible asset for another fungible asset with multiple hops.

```
public fun swap_exact_fa_for_fa_multi_hops(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    token_in: FungibleAsset,
    amount_out_min: u64,
): FungibleAsset
```

**Function arguments**

| Argument         | Type            | Description                         |
| ---------------- | --------------- | ----------------------------------- |
| trader           | \&signer        | The trader’s signer.                |
| pools            | vector\<Object> | The liquidity pools.                |
| token\_in        | FungibleAsset   | The input token.                    |
| amount\_out\_min | u64             | The minimum amount of output token. |

**Returns**

| Type          | Description                 |
| ------------- | --------------------------- |
| FungibleAsset | The swapped fungible asset. |

### Swap exact coin for fungible asset with multiple hops

***

Swaps an exact amount of coin for a fungible asset with multiple hops.

```
public fun swap_exact_coin_for_fa_multi_hops<CoinType>(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    token_in: Coin<CoinType>,
    amount_out_min: u64,
): FungibleAsset
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument         | Type            | Description                         |
| ---------------- | --------------- | ----------------------------------- |
| trader           | \&signer        | The trader’s signer.                |
| pools            | vector\<Object> | The liquidity pools.                |
| token\_in        | Coin            | The input coin.                     |
| amount\_out\_min | u64             | The minimum amount of output token. |

**Returns**

| Type          | Description                 |
| ------------- | --------------------------- |
| FungibleAsset | The swapped fungible asset. |

### Swap fungible asset for exact fungible asset with multiple hops

***

Swaps a fungible asset for an exact amount of another fungible asset with multiple hops.

```
public fun swap_fa_for_exact_fa_multi_hops(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    token_in: FungibleAsset,
    amount_out_desired: u64,
): (FungibleAsset, FungibleAsset)
```

**Function arguments**

| Argument             | Type            | Description                         |
| -------------------- | --------------- | ----------------------------------- |
| trader               | \&signer        | The trader’s signer.                |
| pools                | vector\<Object> | The liquidity pools.                |
| token\_in            | FungibleAsset   | The input token.                    |
| amount\_out\_desired | u64             | The desired amount of output token. |
| sqrt\_price\_limit   | u128            | The sqrt price limit.               |

**Returns**

| Type          | Description                                      |
| ------------- | ------------------------------------------------ |
| FungibleAsset | The remaining fungible asset of the input token. |
| FungibleAsset | The swapped fungible asset of the output token.  |

### Swap coin for exact fungible asset with multiple hops

***

Swaps a coin for an exact amount of a fungible asset with multiple hops.

```
public fun swap_coin_for_exact_fa_multi_hops<CoinType>(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    token_in: Coin<CoinType>,
    amount_out_desired: u64,
): (Coin<CoinType>, FungibleAsset)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument             | Type            | Description                         |
| -------------------- | --------------- | ----------------------------------- |
| trader               | \&signer        | The trader’s signer.                |
| pools                | vector\<Object> | The liquidity pools.                |
| token\_in            | Coin            | The input coin.                     |
| amount\_out\_desired | u64             | The desired amount of output token. |

**Returns**

| Type          | Description                                     |
| ------------- | ----------------------------------------------- |
| Coin          | The remaining coin of the input token.          |
| FungibleAsset | The swapped fungible asset of the output token. |

## Get pool functions

### Get pool

***

Gets the liquidity pool for two fungible assets.

```
#[view]
public fun get_pool(
    token_0: Object<Metadata>,
    token_1: Object<Metadata>,
    fee: u64,
): Object<LiquidityPool>
```

**Function arguments**

| Argument | Type   | Description                        |
| -------- | ------ | ---------------------------------- |
| token\_0 | Object | Fungible asset metadata of token 0 |
| token\_1 | Object | Fungible asset metadata of token 1 |
| fee      | u64    | Fee tier of the pool               |

**Returns**

| Type   | Description         |
| ------ | ------------------- |
| Object | The liquidity pool. |

### Get pool with one coin and one fungible asset

***

Gets the liquidity pool for one coin (<mark style="color:green;">`CoinType`</mark>) and one fungible asset.

```
#[view]
public fun get_pool_one_coin<CoinType>(
    token_1: Object<Metadata>,
    fee: u64,
): Object<LiquidityPool>
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument | Type   | Description                        |
| -------- | ------ | ---------------------------------- |
| token\_1 | Object | Fungible asset metadata of token 1 |
| fee      | u64    | Fee tier of the pool               |

**Returns**

| Type   | Description         |
| ------ | ------------------- |
| Object | The liquidity pool. |

### Get pool with two coins

***

Gets the liquidity pool for two coins <mark style="color:green;">`Coin0`</mark> and <mark style="color:green;">`Coin1`</mark>.

```
#[view]
public fun get_pool_both_coins<Coin0, Coin1>(
    fee: u64,
): Object<LiquidityPool>
```

**Function type arguments**

| Argument | Description                    |
| -------- | ------------------------------ |
| Coin0    | The coin’s type of the token 0 |
| Coin1    | The coin’s type of the token 1 |

**Function arguments**

| Argument | Type | Description          |
| -------- | ---- | -------------------- |
| fee      | u64  | Fee tier of the pool |

**Returns**

| Type   | Description         |
| ------ | ------------------- |
| Object | The liquidity pool. |


# Scripts

## Module info

* **Name**: <mark style="color:green;">`evo::scripts`</mark>
* **Description**: This module contains entry functions for users to call and interact with the <mark style="color:green;">`evo`</mark> contract.

## Public Functions

## Create Pool

### Create pool with two fungible assets

***

Creates a new liquidity pool for two fungible assets. Reverts if the pool already exists.

```
public entry fun create_pool(
    creator: &signer,
    token_0: Object<Metadata>,
    token_1: Object<Metadata>,
    fee: u64,
    sqrt_price: u128,****
)
```

**Function arguments**

| Argument    | Type     | Description                        |
| ----------- | -------- | ---------------------------------- |
| sender      | \&signer | The sender’s signer                |
| token\_0    | Object   | Fungible asset metadata of token 0 |
| token\_1    | Object   | Fungible asset metadata of token 1 |
| fee         | u64      | Fee tier of the pool               |
| sqrt\_price | u128     | Initial sqrt price of the pool     |

### Create pool with one coin and one fungible asset

***

Creates a new liquidity pool with one coin (<mark style="color:green;">`Token0`</mark>) and one fungible asset. Reverts if the pool already exists.

```
public entry fun create_pool_one_coin<Token0>(
    creator: &signer,
    token_1: Object<Metadata>,
    fee: u64,
    sqrt_price: u128,
)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| Token0   | The coin’s type |

**Function arguments**

| Argument    | Type     | Description                        |
| ----------- | -------- | ---------------------------------- |
| sender      | \&signer | The sender’s signer                |
| token\_1    | Object   | Fungible asset metadata of token 1 |
| fee         | u64      | Fee tier of the pool               |
| sqrt\_price | u128     | Initial sqrt price of the pool     |

### Create pool with two coins

***

Creates a new liquidity pool with two coins <mark style="color:green;">`Token0`</mark> and <mark style="color:green;">`Token1`</mark>. Reverts if the pool already exists.

```
public entry fun create_pool_both_coins<Coin0, Coin1>(
    creator: &signer,
    fee: u64,
    sqrt_price: u128,
)
```

**Function type arguments**

| Argument | Description                    |
| -------- | ------------------------------ |
| Token1   | The coin’s type of the token 0 |
| Token0   | The coin’s type of the token 1 |

**Function arguments**

| Argument    | Type     | Description                    |
| ----------- | -------- | ------------------------------ |
| sender      | \&signer | The sender’s signer            |
| fee         | u64      | Fee tier of the pool           |
| sqrt\_price | u128     | Initial sqrt price of the pool |

## Add liquidity

### Add liquidity to a pool with two fungible assets

***

Adds liquidity to a pool with two fungible assets.

```
public entry fun add_liquidity(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    tick_lower: u32,
    tick_upper: u32,
    amount_0: u64,
    amount_1: u64,
    amount_0_min: u64,
    amount_1_min: u64,
)
```

**Function arguments**

| Argument       | Type     | Description                                                                                                              |
| -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| user           | \&signer | The user’s signer.                                                                                                       |
| pool           | Object   | The liquidity pool to add liquidity to.                                                                                  |
| position\_id   | u64      | The position ID of the liquidity. Leave it as 0 if you want to create a new position or you don’t have any position yet. |
| tick\_lower    | u32      | The lower tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| tick\_upper    | u32      | The upper tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| amount\_0      | u64      | The amount of token 0 to add to the liquidity.                                                                           |
| amount\_1      | u64      | The amount of token 1 to add to the liquidity.                                                                           |
| amount\_0\_min | u64      | The minimum amount of token 0 to add to the liquidity.                                                                   |
| amount\_1\_min | u64      | The minimum amount of token 1 to add to the liquidity.                                                                   |

### Add liquidity to a pool with one coin and one fungible asset

***

Adds liquidity to a pool with one coin and one fungible asset.

```
public entry fun add_liquidity_one_coin<CoinType>(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    tick_lower: u32,
    tick_upper: u32,
    amount_0: u64,
    amount_1: u64,
    amount_0_min: u64,
    amount_1_min: u64,
)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument       | Type     | Description                                                                                                              |
| -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| user           | \&signer | The user’s signer.                                                                                                       |
| pool           | Object   | The liquidity pool to add liquidity to.                                                                                  |
| position\_id   | u64      | The position ID of the liquidity. Leave it as 0 if you want to create a new position or you don’t have any position yet. |
| tick\_lower    | u32      | The lower tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| tick\_upper    | u32      | The upper tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| amount\_0      | u64      | The amount of token 0 to add to the liquidity.                                                                           |
| amount\_1      | u64      | The amount of token 1 to add to the liquidity.                                                                           |
| amount\_0\_min | u64      | The minimum amount of token 0 to add to the liquidity.                                                                   |
| amount\_1\_min | u64      | The minimum amount of token 1 to add to the liquidity.                                                                   |

### Add liquidity to a pool with two coins

***

Adds liquidity to a pool with two coins.

```
public entry fun add_liquidity_both_coins<Coin0, Coin1>(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    tick_lower: u32,
    tick_upper: u32,
    amount_0: u64,
    amount_1: u64,
    amount_0_min: u64,
    amount_1_min: u64,
)
```

**Function type arguments**

| Argument | Description                    |
| -------- | ------------------------------ |
| Coin0    | The coin’s type of the token 0 |
| Coin1    | The coin’s type of the token 1 |

**Function arguments**

| Argument       | Type     | Description                                                                                                              |
| -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| user           | \&signer | The user’s signer.                                                                                                       |
| pool           | Object   | The liquidity pool to add liquidity to.                                                                                  |
| position\_id   | u64      | The position ID of the liquidity. Leave it as 0 if you want to create a new position or you don’t have any position yet. |
| tick\_lower    | u32      | The lower tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| tick\_upper    | u32      | The upper tick of the liquidity. Required in the case of creating a new position. Otherwise, leave it as 0.              |
| amount\_0      | u64      | The amount of token 0 to add to the liquidity.                                                                           |
| amount\_1      | u64      | The amount of token 1 to add to the liquidity.                                                                           |
| amount\_0\_min | u64      | The minimum amount of token 0 to add to the liquidity.                                                                   |
| amount\_1\_min | u64      | The minimum amount of token 1 to add to the liquidity.                                                                   |

## Remove liquidity |

### Remove liquidity from a pool

***

Removes liquidity from a pool.

```
public entry fun remove_liquidity(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    liquidity: u128,
    amount_0_min: u64,
    amount_1_min: u64,
)
```

**Function arguments**

| Argument       | Type     | Description                                  |
| -------------- | -------- | -------------------------------------------- |
| user           | \&signer | The user’s signer.                           |
| pool           | Object   | The liquidity pool to remove liquidity from. |
| position\_id   | u64      | The position ID of the liquidity.            |
| liquidity      | u128     | The amount of liquidity to remove.           |
| amount\_0\_min | u64      | The minimum amount of token 0 to get.        |
| amount\_1\_min | u64      | The minimum amount of token 1 to get.        |

### Burn position

***

Burns a position.

```
public entry fun burn_position(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
)
```

**Function arguments**

| Argument     | Type     | Description              |
| ------------ | -------- | ------------------------ |
| user         | \&signer | The user’s signer.       |
| pool         | Object   | The liquidity pool.      |
| position\_id | u64      | The position ID to burn. |

### Collect fee

***

Collects fee from a position.

```
public entry fun collect_fee(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    amount_0_requested: u64,
    amount_1_requested: u64,
    recipient: address,
)
```

**Function arguments**

| Argument             | Type     | Description                      |
| -------------------- | -------- | -------------------------------- |
| user                 | \&signer | The user’s signer.               |
| pool                 | Object   | The liquidity pool.              |
| position\_id         | u64      | The position ID.                 |
| amount\_0\_requested | u64      | The amount of token 0 requested. |
| amount\_1\_requested | u64      | The amount of token 1 requested. |
| recipient            | address  | The recipient address.           |

### Collect reward

***

Collects reward from a position.

```
public entry fun collect_reward(
    user: &signer,
    pool: Object<LiquidityPool>,
    position_id: u64,
    reward_index: u64,
    amount_requested: u64,
    recipient: address,
)
```

**Function arguments**

| Argument          | Type     | Description                     |
| ----------------- | -------- | ------------------------------- |
| user              | \&signer | The user’s signer.              |
| pool              | Object   | The liquidity pool.             |
| position\_id      | u64      | The position ID.                |
| reward\_index     | u64      | The reward index.               |
| amount\_requested | u64      | The amount of reward requested. |
| recipient         | address  | The recipient address.          |

## Swap functions

### Swap exact fungible asset for fungible asset

***

Swaps an exact amount of fungible asset for another fungible asset.

```
public entry fun swap_exact_fa_for_fa(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: Object<Metadata>,
    amount_in: u64,
    amount_out_min: u64,
    sqrt_price_limit: u128,
    recipient: address,
)
```

**Function arguments**

| Argument           | Type     | Description                         |
| ------------------ | -------- | ----------------------------------- |
| trader             | \&signer | The trader’s signer.                |
| pool               | Object   | The liquidity pool.                 |
| token\_in          | Object   | The input token metadata.           |
| amount\_in         | u64      | The amount of input token.          |
| amount\_out\_min   | u64      | The minimum amount of output token. |
| sqrt\_price\_limit | u128     | The sqrt price limit.               |
| recipient          | address  | The recipient address.              |

### Swap exact coin for fungible asset

***

Swaps an exact amount of coin for a fungible asset.

```
public entry fun swap_exact_coin_for_fa<CoinType>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    amount_in: u64,
    amount_out_min: u64,
    sqrt_price_limit: u128,
    recipient: address,
)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument           | Type     | Description                         |
| ------------------ | -------- | ----------------------------------- |
| trader             | \&signer | The trader’s signer.                |
| pool               | Object   | The liquidity pool.                 |
| amount\_in         | u64      | The amount of input coin.           |
| amount\_out\_min   | u64      | The minimum amount of output token. |
| sqrt\_price\_limit | u128     | The sqrt price limit.               |
| recipient          | address  | The recipient address.              |

### Swap fungible asset for exact fungible asset

***

Swaps a fungible asset for an exact amount of another fungible asset.

```
public entry fun swap_fa_for_exact_fa(
    trader: &signer,
    pool: Object<LiquidityPool>,
    token_in: Object<Metadata>,
    amount_in: u64,
    amount_out_min: u64,
    sqrt_price_limit: u128,
    recipient: address,
)
```

**Function arguments**

| Argument           | Type     | Description                         |
| ------------------ | -------- | ----------------------------------- |
| trader             | \&signer | The trader’s signer.                |
| pool               | Object   | The liquidity pool.                 |
| token\_in          | Object   | The input token metadata.           |
| amount\_in         | u64      | The amount of input token.          |
| amount\_out\_min   | u64      | The minimum amount of output token. |
| sqrt\_price\_limit | u128     | The sqrt price limit.               |
| recipient          | address  | The recipient address.              |

### Swap coin for exact fungible asset

***

Swaps a coin for an exact amount of a fungible asset.

```
public entry fun swap_coin_for_exact_fa<CoinType>(
    trader: &signer,
    pool: Object<LiquidityPool>,
    amount_in: u64,
    amount_out_min: u64,
    sqrt_price_limit: u128,
    recipient: address,
)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument           | Type     | Description                         |
| ------------------ | -------- | ----------------------------------- |
| trader             | \&signer | The trader’s signer.                |
| pool               | Object   | The liquidity pool.                 |
| amount\_in         | u64      | The amount of input coin.           |
| amount\_out\_min   | u64      | The minimum amount of output token. |
| sqrt\_price\_limit | u128     | The sqrt price limit.               |
| recipient          | address  | The recipient address.              |

### Swap exact fungible asset for fungible asset with multiple hops

***

Swaps an exact amount of fungible asset for another fungible asset with multiple hops.

```
public entry fun swap_exact_fa_for_fa_multi_hops(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    token_in: Object<Metadata>,
    amount_in: u64,
    amount_out_min: u64,
    recipient: address,
)
```

**Function arguments**

| Argument         | Type            | Description                         |
| ---------------- | --------------- | ----------------------------------- |
| trader           | \&signer        | The trader’s signer.                |
| pools            | vector\<Object> | The liquidity pools.                |
| token\_in        | Object          | The input token metadata.           |
| amount\_in       | u64             | The amount of input token.          |
| amount\_out\_min | u64             | The minimum amount of output token. |
| recipient        | address         | The recipient address.              |

### Swap exact coin for fungible asset with multiple hops

***

Swaps an exact amount of coin for a fungible asset with multiple hops.

```
public entry fun swap_exact_coin_for_fa_multi_hops<CoinType>(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    amount_in: u64,
    amount_out_min: u64,
    recipient: address,
)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

| Argument         | Type            | Description                         |
| ---------------- | --------------- | ----------------------------------- |
| trader           | \&signer        | The trader’s signer.                |
| pools            | vector\<Object> | The liquidity pools.                |
| amount\_in       | u64             | The amount of input coin.           |
| amount\_out\_min | u64             | The minimum amount of output token. |
| recipient        | address         | The recipient address.              |

### Swap fungible asset for exact fungible asset with multiple hops

***

Swaps a fungible asset for an exact amount of another fungible asset with multiple hops.

```
public entry fun swap_fa_for_exact_fa_multi_hops(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    token_in: Object<Metadata>,
    amount_in_max: u64,
    amount_out_desired: u64,
    recipient: address,
)
```

**Function arguments**

| Argument             | Type            | Description                         |
| -------------------- | --------------- | ----------------------------------- |
| trader               | \&signer        | The trader’s signer.                |
| pools                | vector\<Object> | The liquidity pools.                |
| token\_in            | Object          | The input token metadata.           |
| amount\_in\_max      | u64             | The maximum amount of input token.  |
| amount\_out\_desired | u64             | The desired amount of output token. |
| recipient            | address         | The recipient address.              |

### Swap coin for exact fungible asset with multiple hops

***

Swaps a coin for an exact amount of a fungible asset with multiple hops.

```
public entry fun swap_coin_for_exact_fa_multi_hops<CoinType>(
    trader: &signer,
    pools: vector<Object<LiquidityPool>>,
    amount_in_max: u64,
    amount_out_desired: u64,
    recipient: address,
)
```

**Function type arguments**

| Argument | Description     |
| -------- | --------------- |
| CoinType | The coin’s type |

**Function arguments**

<table><thead><tr><th>Argument</th><th width="228">Type</th><th>Description</th></tr></thead><tbody><tr><td>trader</td><td>&#x26;signer</td><td>The trader’s signer.</td></tr><tr><td>pools</td><td>vector&#x3C;Object></td><td>The liquidity pools.</td></tr><tr><td>amount_in_max</td><td>u64</td><td>The maximum amount of input coin.</td></tr><tr><td>amount_out_desired</td><td>u64</td><td>The desired amount of output token.</td></tr><tr><td>recipient</td><td>address</td><td>The recipient address.</td></tr></tbody></table>


# Examples


# Liquidity Pools

**Extract key attributes of a position**

```
public fun extract_core_position(
    position: &Position,
): (u64, u32, u32, u128, u256, u256, u64, u64)
```

**Function arguments**

| position | \&Position | The current position to extract detailed data. |
| -------- | ---------- | ---------------------------------------------- |

**Returns**

| `u64`  | Position identifier                  |
| ------ | ------------------------------------ |
| `u32`  | Lower tick boundary                  |
| `u32`  | Upper tick boundary                  |
| `u128` | Liquidity value                      |
| `u256` | Fee growth inside for token 0        |
| `u256` | Fee growth inside for token 1        |
| `u64`  | Pending fees for position in token 0 |
| `u64`  | Pending fees for position in token 1 |

**Extract position rewards**

```
public fun extract_position_rewards(
    position: &Position,
): vector<PositionRewardInfo>
```

**Function arguments**

| `position` | `&Position` | A reference to the position from which reward details are retrieved |
| ---------- | ----------- | ------------------------------------------------------------------- |

**Returns**

| `vector<PositionRewardInfo>` | A vector containing all reward information records of the position |
| ---------------------------- | ------------------------------------------------------------------ |

**Extract reward info of a position**

This function is used to extract the detailed reward data from a position reward information.

```
public fun extract_reward_info(
    reward_info: &PositionRewardInfo,
): (u256, u64)
```

**Function arguments**

| `reward_info` | `&PositionRewardInfo` | A reference to the reward info record to extract detailed data |
| ------------- | --------------------- | -------------------------------------------------------------- |

**Returns**

| `u256` | The reward growth accumulated |
| ------ | ----------------------------- |
| `u64`  | The pending reward amount     |


# NFT Manager

* **Name**: `evoswap::position_nft_manager`
* **Description**: This module provides functions to work with liquidity positions.

## Public Functions <a href="#public-functions" id="public-functions"></a>

**Get positions info**

Get info of positions with pending fees and pending rewards.

```
#[view]
public fun get_positions(
    pool_addresses: vector<address>,
    position_ids: vector<u64>,
): vector<Option<Position>>
```

**Parameters**

| `pool_addresses` | `vector<address>` | A list of pool addresses to retrieve position information based on the position IDs vector. The length of `pool_addresses` must be equal to the length of `position_ids` |
| ---------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ​                | ​                 | ​                                                                                                                                                                        |
| `position_ids`   | `vector<u64>`     | List of position IDs to query                                                                                                                                            |

**Returns**

| `vector<Option<Position>>` | List of position information, where each element is either `Some(Position)` if the position exists or `None` if it doesn't |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |

**Get position token amounts**

Returns the amounts of tokens held in a specific position.

```
#[view]
public fun get_position_token_amounts(
    pool: Object<LiquidityPool>,
    position_id: u64,
): (u64, u64) acquires ResourceSignerCap
```

**Parameters**

| `pool`        | `Object<LiquidityPool>` | The Liquidity Pool object              |
| ------------- | ----------------------- | -------------------------------------- |
| `position_id` | `u64`                   | The unique identifier for the position |

**Returns**

| `(u64, u64)` | A tuple containing the amounts of token 0 and token 1 in the position |
| ------------ | --------------------------------------------------------------------- |


# Tick Math

* **Name**: `evoswap::tick_math`
* **Description**: This module provides functions to work with ticks and their corresponding square root prices. In EVO, the square root price is represented in a fixed-point format 48x80, using a `u128` number.

#### Sqrt Price Formula <a href="#sqrt-price-formula" id="sqrt-price-formula"></a>

To compute the client-side square root price (`sqrt_price_x80`), use the following formula:

`sqrt_price_x80 = floor(sqrt(price) * 2^80)`

For example, if the price is 1.5, then:

`sqrt_price_x80 = floor(sqrt(1.5) * 2^80) = 1480625697465890259337216`

## Public Functions <a href="#public-functions" id="public-functions"></a>

**Calculate Tick from Square Root Price**

CommentShare feedback on the editorCalculates the tick value corresponding to a given square root price.

```
public fun get_tick_at_sqrt_price(sqrt_price: u128): u32
```

**Function Parameters**

| `sqrt_price` | `u128` | The square root price in fixed-point format 48x80. |
| ------------ | ------ | -------------------------------------------------- |

**Return Value**

| `u32` | The tick value corresponding to the given sqrt\_price. |
| ----- | ------------------------------------------------------ |


# iAsset LP Rewards Distribution

### Overview

The **iAsset LP Rewards Manager** implements a **pro-rata distribution mechanism** for allocating iAsset rewards to liquidity providers based on their actual iAsset token holdings within their positions.

***

{% hint style="warning" %}
iAsset LP Rewards Distribution is currently in development and available **only on the Supra Testnet.**
{% endhint %}

### Distribution Mechanism

#### Core Principle: Pro-Rata by Token Amount

Unlike traditional LP rewards that distribute based on liquidity share, iAsset rewards are distributed **proportionally to the actual amount of iAsset tokens** held in each position.

**Key Formula:**

```rust
reward_per_token = new_rewards × Q64 / total_iasset_amount
user_rewards = user_iasset_amount × (current_rate - last_claimed_rate) / Q64
```

**Where:**

* `new_rewards`: Total new iAsset rewards accumulated since the last harvest
* `total_iasset_amount`: Sum of all iAsset tokens across all LP positions
* `user_iasset_amount`: Actual iAsset token amount in a specific position
* `Q64`: Fixed-point precision factor (`2^64`) to prevent rounding errors

***

#### Why Token Amount, Not Liquidity?

In concentrated liquidity pools, the same liquidity value can represent vastly different token amounts depending on the price range:

* **Position A:** 1000 liquidity at price range \[$1–$2] → holds \~500 token0 + 500 token1
* **Position B:** 1000 liquidity at price range \[$0.01–$0.02] → holds \~50,000 token0 + 50 token1

If rewards were distributed purely by liquidity, both would receive the same rewards — even though Position B holds 100× more token0.\
By distributing based on actual token amounts, the system ensures **fair, proportional rewards**.

***

### How It Works

#### 1. Harvest Phase

The `harvest_rewards()` function periodically checks for new iAsset rewards:

```rust
// Calculate new rewards since last harvest
new_rewards = current_balance - last_harvested_balance

// Only distribute if there are positions with this iAsset
if (total_iasset_0_amount > 0 && new_rewards > 0) {
    // Calculate reward rate per token
    reward_per_token = (new_rewards × Q64) / total_iasset_0_amount

    // Accumulate global rate
    reward_growth_global_0 += reward_per_token

    // Update checkpoint
    last_harvested_balance_0 = current_balance
}
```

**Key Points:**

* Rewards are harvested by comparing current balance vs. last known balance
* Distribution only occurs if positions hold the iAsset (`total_iasset_amount > 0`)
* The global rate accumulates over time, tracking total rewards per token
* Works independently for `token0` and `token1`

***

#### 2. Position Tracking

When users add or remove liquidity, the system tracks their iAsset token amounts.

**On Liquidity Added:**

```rust
// Update position's iAsset amount
position.iasset_amount_0 += amount_0
pool.total_iasset_0_amount += amount_0

// Checkpoint: prevent new deposit from being counted as rewards
last_harvested_balance_0 = current_balance
```

**On Liquidity Removed:**

* Harvest any new rewards first
* Update position rewards to capture pending amounts
* Update tracked iAsset token amounts accordingly

***

#### 3. Reward Calculation

Rewards for a position are calculated using the accumulated rate pattern:

```rust
// Calculate reward growth inside position's price range
reward_growth_inside = calculate_growth_in_range(tick_lower, tick_upper, current_tick)

// Calculate pending rewards based on iAsset amount held
delta_reward = (reward_growth_inside - last_claimed_rate) × iasset_amount / Q64

// Accumulate to amount owed
amount_owed += delta_reward
```

***

#### 4. Claiming Rewards

Users can claim accumulated rewards via `claim_rewards()`:

1. Harvest any new rewards from the pool
2. Update the position to calculate pending amounts
3. Transfer owed rewards to the user
4. Reset `amount_owed` and update claim timestamp

***

### Distribution Properties

#### Fairness Guarantees

* **Pro-rata by token amount:**\
  Users holding 10% of total iAsset tokens receive 10% of rewards — independent of liquidity share or price range.
* **No double-counting:**\
  Checkpointing ensures new deposits aren’t mistakenly rewarded.
* **Time-independent:**\
  Two positions holding equal iAsset amounts for equal time periods earn the same rewards, regardless of entry/exit timing.
* **Price-range independent:**\
  Rewards depend only on token holdings, not on which price range liquidity is provided.

***

#### Active vs. Inactive Range

Unlike fee rewards, which accrue only when positions are in the **active price range**, iAsset rewards distribute **globally** to all positions holding iAsset tokens:

* A position can be completely out of range (no active liquidity)
* As long as it holds iAsset tokens, it earns rewards
* This is intentional — iAsset rewards are **governance/protocol incentives**, not trading fees

***

### Example Scenario

**Setup:**

* Pool has two positions with `token0` as iAsset
* Position A: 1,000 iAsset
* Position B: 4,000 iAsset
* Total: 5,000 iAsset

**Reward Distribution:**

1. Pool receives 500 new iAsset rewards
2. `reward_per_token = 500 × 2^64 / 5,000`
3. Position A: `1,000 × reward_per_token / 2^64 = 100` rewards (20%)
4. Position B: `4,000 × reward_per_token / 2^64 = 400` rewards (80%)

✅ **Result:** Perfectly pro-rata distribution based on token holdings.

***

### Technical Details

#### Precision & Overflow Prevention

* Uses **Q64.64 fixed-point arithmetic** (`2^64` precision)
* All intermediate calculations use `u256` to prevent overflow
* Final results are safely downcast to `u64` for token transfers

***

#### Tick-Based Growth Tracking

Similar to Uniswap v3, the system tracks **reward growth per tick boundary**:

* `tick_rewards_0` and `tick_rewards_1` map each tick to its `reward_growth_outside`
* `reward_growth_inside` is derived for each position based on its tick range
* Enables **precise accounting** for overlapping or partially active ranges

***

#### State Variables

**Global (per pool):**

* `reward_growth_global_0/1`: Accumulated reward rate per token
* `total_iasset_0/1_amount`: Total iAsset tokens held in positions
* `last_harvested_balance_0/1`: Checkpoint for detecting new rewards

**Per Position:**

* `iasset_amount_0/1`: Actual iAsset tokens in this position
* `reward_growth_inside_last_0/1`: Last claimed rate
* `amount_owed_0/1`: Pending unclaimed rewards

***

### Integration Points

#### When to Harvest

The system automatically harvests in these scenarios:

1. **On liquidity removal:** Ensures latest rewards are distributed before changes
2. **On claim:** Ensures user receives all accumulated rewards
3. **Periodically:** Can be called by anyone to update global state

***

### Summary

The **iAsset LP Rewards Distribution** system provides:

1. Fair **pro-rata distribution** based on actual iAsset token holdings
2. Efficient global state tracking using accumulated rates
3. Precise per-position accounting via tick-based growth calculations
4. Protection against double-counting, overflow, and zero-division errors
5. Full compatibility with existing concentrated liquidity mechanics

**Result:**\
All liquidity providers receive rewards proportional to their true iAsset contributions — **independent of price ranges, liquidity concentration, or activity status.**

***


# Contact

We share all news, updates, and announcements on [**X (Twitter)**](https://x.com/swapwithevo) and [**Discord**](https://discord.gg/5vnpNAVBzC).

If you have questions, feedback, partnership inquiries, or just want to say hi, we’d love to hear from you.\
\
The best way to reach us is by joining our **Discord community**, where the team and community members are active.

👉 Join us on [Discord](https://discord.gg/5vnpNAVBzC) to get support, ask questions, say hi and stay up to date.

EVO is built by EVO Labs INC. For contact to labs, we can be reached by email:

* <SwapWithEVO@gmail.com>


