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
43 changes: 22 additions & 21 deletions amm/contracts/router_v2/lib.rs
Original file line number Diff line number Diff line change
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 @@ -62,11 +62,12 @@ pub mod router_v2 {
}

/// Returns StablePool for `pool_id`.
/// Adds the StablePool to the cache.
#[inline]
fn get_stable_pool(&mut self, pool_id: AccountId) -> Result<StablePool, RouterV2Error> {
match self.get_pool(pool_id) {
Ok(Pool::StablePool(pool)) => Ok(pool),
_ => Err(RouterV2Error::PoolNotFound),
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),
}
}

Expand All @@ -76,7 +77,7 @@ pub mod router_v2 {
/// 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 @@ -86,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 @@ -101,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 @@ -130,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 @@ -159,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 @@ -392,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 @@ -417,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 @@ -441,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 @@ -465,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 @@ -490,7 +491,7 @@ pub mod router_v2 {
native: bool,
) -> Result<(u128, u128), RouterV2Error> {
let wnative = if native { Some(self.wnative) } else { None };
self.get_stable_pool(pool)?.add_liquidity(
self.get_and_cache_stable_pool(pool)?.add_liquidity(
min_share_amount,
amounts,
to,
Expand All @@ -510,7 +511,7 @@ pub mod router_v2 {
native: bool,
) -> Result<(u128, u128), RouterV2Error> {
let wnative = if native { Some(self.wnative) } else { None };
self.get_stable_pool(pool)?.remove_liquidity(
self.get_and_cache_stable_pool(pool)?.remove_liquidity(
max_share_amount,
amounts,
to,
Expand All @@ -530,7 +531,7 @@ pub mod router_v2 {
native: bool,
) -> Result<Vec<u128>, RouterV2Error> {
let wnative = if native { Some(self.wnative) } else { None };
self.get_stable_pool(pool)?.remove_liquidity_by_share(
self.get_and_cache_stable_pool(pool)?.remove_liquidity_by_share(
share_amount,
min_amounts,
to,
Expand Down
41 changes: 18 additions & 23 deletions amm/contracts/router_v2/stable_pool.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use amm_helpers::ensure;
use ink::{
codegen::TraitCallBuilder,
contract_ref,
env::{account_id, caller, transferred_value, DefaultEnvironment as Env},
prelude::vec::Vec,
primitives::AccountId,
};
use traits::{RouterV2Error, StablePool as StablePoolTrait, StablePoolError};
use traits::{RouterV2Error, StablePool as StablePoolTrait};

use crate::utils::{
check_timestamp, psp22_approve, psp22_transfer, psp22_transfer_from, transfer_native, withdraw,
Expand Down Expand Up @@ -68,10 +69,6 @@ impl StablePool {
wnative: Option<AccountId>,
) -> Result<(u128, u128), RouterV2Error> {
check_timestamp(deadline)?;
ensure!(
self.tokens.len() == amounts.len(),
RouterV2Error::StablePoolError(StablePoolError::IncorrectAmountsCount)
);
let native_received = transferred_value::<Env>();
let (wnative_idx, native_surplus) = match wnative {
Some(wnative) => {
Expand Down Expand Up @@ -115,10 +112,6 @@ impl StablePool {
wnative: Option<AccountId>,
) -> Result<(u128, u128), RouterV2Error> {
check_timestamp(deadline)?;
ensure!(
self.tokens.len() == amounts.len(),
RouterV2Error::StablePoolError(StablePoolError::IncorrectAmountsCount)
);
psp22_transfer_from(
self.id,
caller::<Env>(),
Expand All @@ -133,11 +126,7 @@ impl StablePool {
amounts.clone(),
account_id::<Env>(),
)?;
withdraw(wnative, amounts[wnative_idx])?;
transfer_native(to, amounts[wnative_idx])?;
for i in (0..self.tokens.len()).filter(|&idx| idx != wnative_idx) {
psp22_transfer(self.tokens[i], to, amounts[i])?;
}
self.handle_token_transfers(&amounts, to, wnative_idx)?;
res
}
None => {
Expand All @@ -164,10 +153,6 @@ impl StablePool {
wnative: Option<AccountId>,
) -> Result<Vec<u128>, RouterV2Error> {
check_timestamp(deadline)?;
ensure!(
self.tokens.len() == min_amounts.len(),
RouterV2Error::StablePoolError(StablePoolError::IncorrectAmountsCount)
);
psp22_transfer_from(self.id, caller::<Env>(), account_id::<Env>(), share_amount)?;
match wnative {
Some(wnative) => {
Expand All @@ -177,11 +162,7 @@ impl StablePool {
min_amounts,
account_id::<Env>(),
)?;
withdraw(wnative, amounts[wnative_idx])?;
transfer_native(to, amounts[wnative_idx])?;
for i in (0..self.tokens.len()).filter(|&idx| idx != wnative_idx) {
psp22_transfer(self.tokens[i], to, amounts[i])?;
}
self.handle_token_transfers(&amounts, to, wnative_idx)?;
Ok(amounts)
}
None => {
Expand Down Expand Up @@ -234,4 +215,18 @@ impl StablePool {
.position(|&token| wnative == token)
.ok_or(RouterV2Error::InvalidToken)
}

fn handle_token_transfers(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: maybe transfer_tokens_back ?

&self,
amounts: &[u128],
to: AccountId,
wnative_idx: usize,
) -> Result<(), RouterV2Error> {
withdraw(self.tokens[wnative_idx], amounts[wnative_idx])?;
transfer_native(to, amounts[wnative_idx])?;
for i in (0..self.tokens.len()).filter(|&idx| idx != wnative_idx) {
psp22_transfer(self.tokens[i], to, amounts[i])?;
}
Ok(())
}
}
8 changes: 2 additions & 6 deletions amm/contracts/router_v2/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,11 @@ pub fn psp22_approve(token: AccountId, spender: AccountId, value: u128) -> Resul
#[inline]
pub fn wrap(wnative: AccountId, value: Balance) -> Result<(), RouterV2Error> {
let mut wnative_ref: contract_ref!(WrappedAZERO, Env) = wnative.into();
wnative_ref
Ok(wnative_ref
.call_mut()
.deposit()
.transferred_value(value)
.try_invoke()
.map_err(|_| {
RouterV2Error::CrossContractCallFailed(String::from("Wrapped AZERO: deposit"))
})???;
Ok(())
.invoke()?)
}

#[inline]
Expand Down
5 changes: 1 addition & 4 deletions amm/traits/router_v2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{Balance, FactoryError, MathError, PairError, StablePoolError};
use ink::{
prelude::{string::String, vec::Vec},
prelude::vec::Vec,
primitives::AccountId,
LangError,
};
Expand Down Expand Up @@ -289,12 +289,9 @@ pub enum RouterV2Error {
MathError(MathError),
StablePoolError(StablePoolError),

CrossContractCallFailed(String),
Expired,
InvalidPoolAddress,
InvalidToken,
PairNotFound,
PoolNotFound,
TransferError,

ExcessiveInputAmount,
Expand Down