Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router v2 stable liquidity #118

Merged
merged 10 commits into from
Sep 26, 2024
Merged
111 changes: 90 additions & 21 deletions amm/contracts/router_v2/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub struct CallerIsNotOwner;
#[ink::contract]
pub mod router_v2 {
use crate::{
pool::{Pair, Pool},
pool::{Pair, Pool, StablePool},
utils::*,
};
use amm_helpers::ensure;
Expand Down Expand Up @@ -50,7 +50,7 @@ pub mod router_v2 {
/// Returns Pool for `pool_id` if it exists.
/// Adds the Pool to the cache.
#[inline]
fn get_pool(&mut self, pool_id: AccountId) -> Result<Pool, RouterV2Error> {
fn get_and_cache_pool(&mut self, pool_id: AccountId) -> Result<Pool, RouterV2Error> {
match self.cached_pools.get(pool_id) {
Some(pool) => Ok(pool),
None => {
Expand All @@ -60,13 +60,24 @@ pub mod router_v2 {
}
}
}

/// Returns StablePool for `pool_id`.
/// Adds the StablePool to the cache.
#[inline]
fn get_and_cache_stable_pool(&mut self, pool_id: AccountId) -> Result<StablePool, RouterV2Error> {
match self.get_and_cache_pool(pool_id)? {
Pool::StablePool(pool) => Ok(pool),
Pool::Pair(_) => Err(RouterV2Error::InvalidPoolAddress),
}
}

/// Returns Pair for `pool_id`.
/// If `pool_id` is `None`, it creates a new Pair for
/// `(token_0, token_1)` tokens if the Pair does not
/// exist in the pair Factory.
/// Adds the Pair to the cache.
#[inline]
fn get_pair(
fn get_and_cache_pair(
&mut self,
pool_id: Option<AccountId>,
token_0: AccountId,
Expand All @@ -76,9 +87,9 @@ pub mod router_v2 {
Some(pool_id) => pool_id,
None => self.pair_factory_ref().create_pair(token_0, token_1)?,
};
match self.get_pool(pool_id)? {
match self.get_and_cache_pool(pool_id)? {
Pool::Pair(pair) => Ok(pair),
Pool::StablePool(_) => Err(RouterV2Error::PairNotFound),
Pool::StablePool(_) => Err(RouterV2Error::InvalidPoolAddress),
}
}

Expand All @@ -91,15 +102,15 @@ pub mod router_v2 {
) -> Result<(), RouterV2Error> {
let n_pools = path.len();
for i in 0..n_pools - 1 {
self.get_pool(path[i].pool_id)?.swap(
self.get_and_cache_pool(path[i].pool_id)?.swap(
path[i].token_in,
path[i + 1].token_in,
amounts[i + 1],
path[i + 1].pool_id,
)?;
}
// If last pool in the path, transfer tokens to the `to` recipient.
self.get_pool(path[n_pools - 1].pool_id)?.swap(
self.get_and_cache_pool(path[n_pools - 1].pool_id)?.swap(
path[n_pools - 1].token_in,
token_out,
amounts[n_pools],
Expand All @@ -120,13 +131,13 @@ pub mod router_v2 {
let n_pools = path.len();
let mut amounts = vec![0; n_pools + 1];
amounts[n_pools] = amount_out;
amounts[n_pools - 1] = self.get_pool(path[n_pools - 1].pool_id)?.get_amount_in(
amounts[n_pools - 1] = self.get_and_cache_pool(path[n_pools - 1].pool_id)?.get_amount_in(
path[n_pools - 1].token_in,
token_out,
amount_out,
)?;
for i in (0..n_pools - 1).rev() {
amounts[i] = self.get_pool(path[i].pool_id)?.get_amount_in(
amounts[i] = self.get_and_cache_pool(path[i].pool_id)?.get_amount_in(
path[i].token_in,
path[i + 1].token_in,
amounts[i + 1],
Expand All @@ -149,13 +160,13 @@ pub mod router_v2 {
let mut amounts = vec![0; n_pools + 1];
amounts[0] = amount_in;
for i in 0..n_pools - 1 {
amounts[i + 1] = self.get_pool(path[i].pool_id)?.get_amount_out(
amounts[i + 1] = self.get_and_cache_pool(path[i].pool_id)?.get_amount_out(
path[i].token_in,
path[i + 1].token_in,
amounts[i],
)?;
}
amounts[n_pools] = self.get_pool(path[n_pools - 1].pool_id)?.get_amount_out(
amounts[n_pools] = self.get_and_cache_pool(path[n_pools - 1].pool_id)?.get_amount_out(
path[n_pools - 1].token_in,
token_out,
amounts[n_pools - 1],
Expand Down Expand Up @@ -284,9 +295,7 @@ pub mod router_v2 {
self.swap(&amounts, &path, wnative, self.env().account_id())?;
let native_out = amounts[amounts.len() - 1];
withdraw(wnative, native_out)?;
self.env()
.transfer(to, native_out)
.map_err(|_| RouterV2Error::TransferError)?;
transfer_native(to, native_out)?;
Ok(amounts)
}

Expand Down Expand Up @@ -315,9 +324,7 @@ pub mod router_v2 {
)?;
self.swap(&amounts, &path, wnative, self.env().account_id())?;
withdraw(wnative, native_out)?;
self.env()
.transfer(to, native_out)
.map_err(|_| RouterV2Error::TransferError)?;
transfer_native(to, native_out)?;
Ok(amounts)
}

Expand Down Expand Up @@ -386,7 +393,7 @@ pub mod router_v2 {
to: AccountId,
deadline: u64,
) -> Result<(u128, u128, u128), RouterV2Error> {
let pair = self.get_pair(pair, token_0, token_1)?;
let pair = self.get_and_cache_pair(pair, token_0, token_1)?;
pair.add_liquidity(
token_0,
token_1,
Expand All @@ -411,7 +418,7 @@ pub mod router_v2 {
deadline: u64,
) -> Result<(u128, Balance, u128), RouterV2Error> {
let wnative = self.wnative;
let pair = self.get_pair(pair, token, wnative)?;
let pair = self.get_and_cache_pair(pair, token, wnative)?;
pair.add_liquidity_native(
token,
wnative,
Expand All @@ -435,7 +442,7 @@ pub mod router_v2 {
to: AccountId,
deadline: u64,
) -> Result<(u128, u128), RouterV2Error> {
let pair = self.get_pair(Some(pair), token_0, token_1)?;
let pair = self.get_and_cache_pair(Some(pair), token_0, token_1)?;
pair.remove_liquidity(
token_0,
token_1,
Expand All @@ -459,7 +466,7 @@ pub mod router_v2 {
deadline: u64,
) -> Result<(u128, Balance), RouterV2Error> {
let wnative = self.wnative;
let pair = self.get_pair(Some(pair), token, wnative)?;
let pair = self.get_and_cache_pair(Some(pair), token, wnative)?;
pair.remove_liquidity_native(
token,
wnative,
Expand All @@ -470,6 +477,68 @@ pub mod router_v2 {
deadline,
)
}

// ----------- STABLE POOL LIQUIDITY METHODS ----------- //

#[ink(message, payable)]
fn add_stable_pool_liquidity(
&mut self,
pool: AccountId,
min_share_amount: u128,
amounts: Vec<u128>,
to: AccountId,
deadline: u64,
native: bool,
) -> Result<(u128, u128), RouterV2Error> {
let wnative = if native { Some(self.wnative) } else { None };
self.get_and_cache_stable_pool(pool)?.add_liquidity(
min_share_amount,
amounts,
to,
deadline,
wnative,
)
}

#[ink(message)]
fn remove_stable_pool_liquidity(
&mut self,
pool: AccountId,
max_share_amount: u128,
amounts: Vec<u128>,
to: AccountId,
deadline: u64,
native: bool,
) -> Result<(u128, u128), RouterV2Error> {
let wnative = if native { Some(self.wnative) } else { None };
self.get_and_cache_stable_pool(pool)?.remove_liquidity(
max_share_amount,
amounts,
to,
deadline,
wnative,
)
}

#[ink(message)]
fn remove_stable_pool_liquidity_by_share(
&mut self,
pool: AccountId,
share_amount: u128,
min_amounts: Vec<u128>,
to: AccountId,
deadline: u64,
native: bool,
) -> Result<Vec<u128>, RouterV2Error> {
let wnative = if native { Some(self.wnative) } else { None };
self.get_and_cache_stable_pool(pool)?.remove_liquidity_by_share(
share_amount,
min_amounts,
to,
deadline,
wnative,
)
}
}

#[cfg(test)]
Expand Down
9 changes: 5 additions & 4 deletions amm/contracts/router_v2/pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use amm_helpers::{ensure, math::casted_mul};
use ink::{
codegen::TraitCallBuilder,
contract_ref,
env::{account_id, caller, transfer, transferred_value, DefaultEnvironment as Env},
env::{account_id, caller, transferred_value, DefaultEnvironment as Env},
primitives::AccountId,
};
use traits::{Balance, MathError, Pair as PairTrait, RouterV2Error};
Expand Down Expand Up @@ -63,6 +63,8 @@ impl Pair {

/// Makes a cross-contract call to fetch the Pair reserves.
/// Returns reserves `(reserve_0, reserve_1)` in order of `token_0` and `token_1`
/// NOTE: before calling this method ensure that `token_0` and `token_1` belong to
/// this `Pair` pool
fn get_reserves(&self, token_0: &AccountId, token_1: &AccountId) -> (u128, u128) {
let (reserve_0, reserve_1, _) = self.contract_ref().get_reserves();
if token_0 < token_1 {
Expand Down Expand Up @@ -185,8 +187,7 @@ impl Pair {
let liquidity = self.contract_ref().mint(to)?;

if received_value > amount_native {
transfer::<Env>(caller, received_value - amount_native)
.map_err(|_| RouterV2Error::TransferError)?;
transfer_native(caller, received_value - amount_native)?;
}

Ok((amount_0, amount_native, liquidity))
Expand Down Expand Up @@ -240,7 +241,7 @@ impl Pair {
)?;
psp22_transfer(token, to, amount_token)?;
withdraw(wnative, amount_native)?;
transfer::<Env>(to, amount_native).map_err(|_| RouterV2Error::TransferError)?;
transfer_native(to, amount_native)?;
Ok((amount_token, amount_native))
}

Expand Down
Loading