npm package: @sentre/senswap
Description: SenSwap is a Balancer-like AMM on Solana. The AMM implementation is heavily relying on [Balancer's Whitepaper](https://balancer.fi/whitepaper.pdf).
Author: Sentre
Latest version: 1.0.9

# SenSwap

SenSwap is a Balancer-like AMM on Solana. The AMM implementation is heavily relying on [Balancer's Whitepaper](https://balancer.fi/whitepaper.pdf).

Beside that, we also add some extra features to help leverage others on-top application in the future. You can find details in the [Implementation](#implementation).

## Preresiquite

### Install anchor-lang

Please follow this link https://www.anchor-lang.com/docs/installation to setup anchor-lang on your machine.

### pnpm

Due to some conlicts between `yarn` and `anchor-lang`, we decided to migrate `yarn` to `pnpm` within this project. Follow https://pnpm.io/installation to setup pnpm and run the below commands to install the project's dependencies

```bash
pnpm install
```

## Build

To build the program,

```bash
pnpm build
```

## Test

To run the testcase,

```bash
pnpm test
```

## Folder Structure

| Folder name                     | Description                                                                                               |
| ------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `src/balancer-amm`              | The smart contract implementation                                                                         |
| `src/balancer-amm/instructions` | The smart contract's processors. Each instruction from users will be navigated to the relevant processor. |
| `src/balancer-amm/schema`       | Defines program account schema.                                                                           |
| `lib`                           | The SenSwap Javascript SDK to help developers to interact with the smart contract.                        |
| `migrations`                    | Contains smart contract deployment scripts.                                                               |
| `tests`                         | Contains testcases for both the smart contract and the SDK.                                               |
| `.github`                       | Defines Github workflows                                                                                  |

## Implementation

This section will require the reader to understand both the current documentation and the source code also.

![senswap.jpg](https://i.imgur.com/cW6rWlI.jpg)
Fig.1. This is flowchart-like diagram depicting available features of SenSwap corresponding to its state. Note that the circle is just a diagram connector and has no semantic meaning.

### How to initialize a pool?

To initialize a pool, the pool owner needs to call `initialize_pool` first. The function will ask for basic info like `mints`, `treasuries`, `weights`, etc., to create a pool account and store these info.

Note that `initialize_pool` won't create any accounts (execept the pool account) and keep the status of `PoolState::Uninitialized` until the pool when owner calls `initialize_join`.

To create the treasuries (aka token accounts) corresponding to the mints, and also deposit the initial amount of tokens into the pool, the pool owner must call `initialize_join` for all mints one by one. After all, the pool will transmit the status from `PoolState::Uninitialized` to `PoolState::Initializing` and there are a number LP initialized for the pool owner aka the first liquidity provider.

In case of incorrect configs, the pool owner can cancel the pool by `close_pool`. This function is only possible when the pool is `PoolState::Uninitialized`.

> There current pool limit is 8 mints.

### How to finalize a pool?

Once the pool is initialized, only the pool owner is able to update weights, add/remove liquidity. This limit is to avoid rug pull and build a foundation for liquidity boostrapping (aka. launchpad).

To open the pool to the publish, the pool owner must finalized the pool state from `PoolState::Initializing` to `PoolState::Initialized`. At that time, the publish can join and add/remove liquidity to the pool.

### How to add liquidity?

By adding liquidity, the user will become an liquidity provider. However, `add_liquidity` differs from `initialize_pool` that it requires all token deposited at once. In exchange, the liquidity provider will receive a corresponding number of LP tokens.

### How to remove liquidity?

The liquidity providers can return LP tokens via `remove_liquidity` ~~or `remove_sided_liqudity`~~ to get back their deposited tokens.

~~The different between `remove_liquidity` and `remove_sided_liqudity` is that `remove_liquidity` will return all mints respectively to the current proportion while `remove_sided_liqudity` will allow liquidity providers to select their single favorite mint to withdraw.~~

Senswap now only supports `remove_liquidity` for full liquidity withdrawals.

### Swap

Users can run a swap by calling `swap`. There exists fees for each transaction. You can find more in [Fee & Tax](#fee--tax).

### Route

`route` is a high-level abstract function of `swap`. Users can call multiple `swap`-s in a monolithic transaction of `route`. The basic idea is that `route` will verify params for each `swap` then self-invoke the program by calling `swap`. This function is really helpful for AMM aggregators.

### Fee & Tax

On each `swap`, there are fees that the trader must to pay:

- Liquidity Provision Fee (aka `fee`):

  - IT'S COLLECTED OVER BIDDING TOKENS.
  - This fee is to incentivize people to provide liquidity into the pool and avoid permanent loss.

- Platform Fee (aka `tax`):

  - IT'S COLLECTED OVER BIDDING TOKENS.
  - This tax is to help SenSwap maintain the system and develop more features to the platform.
  - However, the `tax` is not only for the SenSwap foundation, but also being structured for the referral system. When referrer addresses are injected in a transaction, the `tax` will splitted equally for the platform fee and referral fees. For example, there are 2 referrer addresses in a `swap` transaction and 90 tokens for the `tax`, then the platform fee will be 30 tokens, and 30 tokens for each referrer.
  - There is MAXIMUM 2 referral addresses.
  - We skip the tax in term of inbalance liquidity provision.

As you may notice, SenSwap allows liquidity providers add/remove liquidity asymmetrically while the system will make an auto swap to balance the structure. Because of the auto swap, the fee & tax is available in `add_liquidity`, and `remove_liquidity`. However, the referal system is disabled in those transaction types.

### Pause & Resume (aka Frezee & thaw)

> Only avaiable when `PoolState::Initializing`.

These actions are rarely used and only avaialble when the pool is in state of `PoolState::Initializing`. When the pool owner is creating a pool or launching their tokens but meet some fatal flaws, the can call `freezePool` to secure the pool and their tokens.

## Computing Precision

In regard to the Balancer's multiple-weighted-tokens AMM, the computation is heavily relies on fractional exponentiation. To keep the implementation effective and reliable, we employ directly the float system `f64` in Rust to for only float exponentiation. For bounded precision, we immediately check the swap price must fall into the gap of previous and next spot price: `prev_spot_price < swap_price < next_spot_price`.

## Audited

- [Verichains Audit Report](https://drive.google.com/file/d/1v_SlGMzy60e9b8srKZaAUtcL5q4Lb6On/view?usp=sharing)
- [Sec3 Audit Report](#)

## Copyright

SenSwap © 2023 Sentizen Foundation.