diff --git a/amm/contracts/mock_sazero_rate/lib.rs b/amm/contracts/mock_sazero_rate/lib.rs index 5b7007e..42dcba4 100644 --- a/amm/contracts/mock_sazero_rate/lib.rs +++ b/amm/contracts/mock_sazero_rate/lib.rs @@ -11,7 +11,9 @@ mod mock_sazero_rate { #[ink(constructor)] #[allow(clippy::new_without_default)] pub fn new() -> Self { - Self { rate: 10u128.pow(12u32) } + Self { + rate: 10u128.pow(12u32), + } } #[ink(message)] diff --git a/amm/contracts/stable_pool/lib.rs b/amm/contracts/stable_pool/lib.rs index db7b53f..8761230 100644 --- a/amm/contracts/stable_pool/lib.rs +++ b/amm/contracts/stable_pool/lib.rs @@ -29,7 +29,6 @@ pub mod stable_pool { use psp22::{PSP22Data, PSP22Error, PSP22Event, PSP22Metadata, PSP22}; use traits::{ MathError, Ownable2Step, Ownable2StepData, Ownable2StepResult, StablePool, StablePoolError, - StablePoolView, }; #[ink(event)] @@ -66,12 +65,12 @@ pub mod stable_pool { #[ink(event)] pub struct Sync { - reserves: Vec, + pub reserves: Vec, } #[ink(event)] pub struct RatesUpdated { - rates: Vec, + pub rates: Vec, } #[ink(event)] @@ -101,11 +100,13 @@ pub mod stable_pool { #[ink(event)] pub struct TransferOwnershipInitiated { + #[ink(topic)] pub new_owner: AccountId, } #[ink(event)] pub struct TransferOwnershipAccepted { + #[ink(topic)] pub new_owner: AccountId, } @@ -120,14 +121,13 @@ pub mod stable_pool { #[ink(event)] pub struct AmpCoefChanged { - #[ink(topic)] pub new_amp_coef: u128, } #[ink(event)] pub struct FeeChanged { - trade_fee: u32, - protocol_fee: u32, + pub trade_fee: u32, + pub protocol_fee: u32, } #[ink::storage_item] @@ -305,11 +305,18 @@ pub mod stable_pool { self.pool.tokens[token_id].into() } + /// Update cached rates if expired. + /// + /// NOTE: + /// If the pool contains a token with rate oracle, this function makes + /// a cross-contract call to the `RateProvider` contract if the cached rate is expired. + /// This means that the gas cost of the contract methods that use this function may vary, + /// depending on the state of the expiration timestamp of the cached rate. fn update_rates(&mut self) { let current_time = self.env().block_timestamp(); let mut rate_changed = false; for rate in self.pool.token_rates.iter_mut() { - rate_changed = rate.update_rate(current_time) | rate_changed; + rate_changed |= rate.update_rate(current_time); } if rate_changed { Self::env().emit_event(RatesUpdated { @@ -318,18 +325,21 @@ pub mod stable_pool { } } - fn fee_to(&self) -> Option { - self.pool.fee_receiver + /// Get updated rates + fn get_updated_rates(&self) -> Vec { + let current_time = self.env().block_timestamp(); + let mut rates = self.pool.token_rates.clone(); + rates.iter_mut().for_each(|rate| { + rate.update_rate(current_time); + }); + rates } /// Scaled rates are rates multiplied by precision. They are assumed to fit in u128. /// If TOKEN_TARGET_DECIMALS is 18 and RATE_DECIMALS is 12, then rates not exceeding ~340282366 should fit. /// That's because if precision <= 10^18 and rate <= 10^12 * 340282366, then rate * precision < 2^128. - /// - /// NOTE: Rates should be updated prior to calling this function - fn get_scaled_rates(&self) -> Result, MathError> { - self.pool - .token_rates + fn get_scaled_rates(&self, rates: &[TokenRate]) -> Result, MathError> { + rates .iter() .zip(self.pool.precisions.iter()) .map(|(rate, &precision)| { @@ -364,10 +374,10 @@ pub mod stable_pool { /// /// NOTE: Rates should be updated prior to calling this function fn mint_protocol_fee(&mut self, fee: u128, token_id: usize) -> Result<(), StablePoolError> { - if let Some(fee_to) = self.fee_to() { + if let Some(fee_to) = self.fee_receiver() { let protocol_fee = self.pool.fees.protocol_trade_fee(fee)?; if protocol_fee > 0 { - let rates = self.get_scaled_rates()?; + let rates = self.get_scaled_rates(&self.pool.token_rates)?; let mut protocol_deposit_amounts = vec![0u128; self.pool.tokens.len()]; protocol_deposit_amounts[token_id] = protocol_fee; let mut reserves = self.pool.reserves.clone(); @@ -428,8 +438,8 @@ pub mod stable_pool { // Make sure rates are up to date before we attempt any calculations self.update_rates(); + let rates = self.get_scaled_rates(&self.pool.token_rates)?; - let rates = self.get_scaled_rates()?; // calc amount_out and fees let (token_out_amount, fee) = math::rated_swap_to( &rates, @@ -489,8 +499,7 @@ pub mod stable_pool { // Make sure rates are up to date before we attempt any calculations self.update_rates(); - - let rates = self.get_scaled_rates()?; + let rates = self.get_scaled_rates(&self.pool.token_rates)?; // calc amount_out and fees let (token_in_amount, fee) = math::rated_swap_from( @@ -506,7 +515,7 @@ pub mod stable_pool { // Check if in token_in_amount is as constrained by the user ensure!( token_in_amount <= max_token_in_amount, - StablePoolError::TooLargeInputAmount + StablePoolError::InsufficientInputAmount ); // update reserves self.increase_reserve(token_in_id, token_in_amount)?; @@ -577,8 +586,24 @@ pub mod stable_pool { amounts: Vec, to: AccountId, ) -> Result<(u128, u128), StablePoolError> { + ensure!( + amounts.len() == self.pool.tokens.len(), + StablePoolError::IncorrectAmountsCount + ); + + // Make sure rates are up to date before we attempt any calculations + self.update_rates(); + let rates = self.get_scaled_rates(&self.pool.token_rates)?; + // calc lp tokens (shares_to_mint, fee) - let (shares, fee_part) = self.get_mint_liquidity_for_amounts(amounts.clone())?; + let (shares, fee_part) = math::rated_compute_lp_amount_for_deposit( + &rates, + &amounts, + &self.reserves(), + self.psp22.total_supply(), + Some(&self.pool.fees), + self.amp_coef(), + )?; // Check min shares ensure!( @@ -601,7 +626,7 @@ pub mod stable_pool { self.emit_events(events); // mint protocol fee - if let Some(fee_to) = self.fee_to() { + if let Some(fee_to) = self.fee_receiver() { let protocol_fee = self.pool.fees.protocol_trade_fee(fee_part)?; if protocol_fee > 0 { let events = self.psp22.mint(fee_to, protocol_fee)?; @@ -683,9 +708,24 @@ pub mod stable_pool { amounts: Vec, to: AccountId, ) -> Result<(u128, u128), StablePoolError> { + ensure!( + amounts.len() == self.pool.tokens.len(), + StablePoolError::IncorrectAmountsCount + ); + + // Make sure rates are up to date before we attempt any calculations + self.update_rates(); + let rates = self.get_scaled_rates(&self.pool.token_rates)?; + // calc comparable amounts - let (shares_to_burn, fee_part) = - self.get_burn_liquidity_for_amounts(amounts.clone())?; + let (shares_to_burn, fee_part) = math::rated_compute_lp_amount_for_withdraw( + &rates, + &amounts, + &self.reserves(), + self.psp22.total_supply(), + Some(&self.pool.fees), + self.amp_coef(), + )?; // check max shares ensure!( @@ -696,7 +736,7 @@ pub mod stable_pool { let events = self.psp22.burn(self.env().caller(), shares_to_burn)?; self.emit_events(events); // mint protocol fee - if let Some(fee_to) = self.fee_to() { + if let Some(fee_to) = self.fee_receiver() { let protocol_fee = self.pool.fees.protocol_trade_fee(fee_part)?; if protocol_fee > 0 { let events = self.psp22.mint(fee_to, protocol_fee)?; @@ -725,11 +765,11 @@ pub mod stable_pool { } #[ink(message)] - fn force_update_rate(&mut self) { + fn force_update_rates(&mut self) { let current_time = self.env().block_timestamp(); let mut rate_changed = false; for rate in self.pool.token_rates.iter_mut() { - rate_changed = rate.update_rate_no_cache(current_time) | rate_changed; + rate_changed |= rate.force_update_rate(current_time); } if rate_changed { Self::env().emit_event(RatesUpdated { @@ -820,9 +860,7 @@ pub mod stable_pool { }); Ok(()) } - } - impl StablePoolView for StablePoolContract { #[ink(message)] fn tokens(&self) -> Vec { self.pool.tokens.clone() @@ -843,6 +881,11 @@ pub mod stable_pool { (self.pool.fees.trade_fee, self.pool.fees.protocol_fee) } + #[ink(message)] + fn fee_receiver(&self) -> Option { + self.pool.fee_receiver + } + #[ink(message)] fn token_rates(&mut self) -> Vec { self.update_rates(); @@ -855,14 +898,13 @@ pub mod stable_pool { #[ink(message)] fn get_swap_amount_out( - &mut self, + &self, token_in: AccountId, token_out: AccountId, token_in_amount: u128, ) -> Result<(u128, u128), StablePoolError> { let (token_in_id, token_out_id) = self.check_tokens(token_in, token_out)?; - self.update_rates(); - let rates = self.get_scaled_rates()?; + let rates = self.get_scaled_rates(&self.get_updated_rates())?; Ok(math::rated_swap_to( &rates, token_in_id, @@ -876,14 +918,13 @@ pub mod stable_pool { #[ink(message)] fn get_swap_amount_in( - &mut self, + &self, token_in: AccountId, token_out: AccountId, token_out_amount: u128, ) -> Result<(u128, u128), StablePoolError> { let (token_in_id, token_out_id) = self.check_tokens(token_in, token_out)?; - self.update_rates(); - let rates = self.get_scaled_rates()?; + let rates = self.get_scaled_rates(&self.get_updated_rates())?; Ok(math::rated_swap_from( &rates, token_in_id, @@ -897,15 +938,14 @@ pub mod stable_pool { #[ink(message)] fn get_mint_liquidity_for_amounts( - &mut self, + &self, amounts: Vec, ) -> Result<(u128, u128), StablePoolError> { ensure!( amounts.len() == self.pool.tokens.len(), StablePoolError::IncorrectAmountsCount ); - self.update_rates(); - let rates = self.get_scaled_rates()?; + let rates = self.get_scaled_rates(&self.get_updated_rates())?; Ok(math::rated_compute_lp_amount_for_deposit( &rates, @@ -931,15 +971,14 @@ pub mod stable_pool { #[ink(message)] fn get_burn_liquidity_for_amounts( - &mut self, + &self, amounts: Vec, ) -> Result<(u128, u128), StablePoolError> { - self.update_rates(); ensure!( amounts.len() == self.pool.tokens.len(), StablePoolError::IncorrectAmountsCount ); - let rates = self.get_scaled_rates()?; + let rates = self.get_scaled_rates(&self.get_updated_rates())?; math::rated_compute_lp_amount_for_withdraw( &rates, &amounts, @@ -956,6 +995,10 @@ pub mod stable_pool { &mut self, liquidity: u128, ) -> Result, StablePoolError> { + ensure!( + liquidity <= self.psp22.total_supply(), + StablePoolError::InsufficientLiquidity + ); Ok(math::compute_amounts_given_lp( liquidity, &self.reserves(), diff --git a/amm/contracts/stable_pool/token_rate.rs b/amm/contracts/stable_pool/token_rate.rs index ae2bc18..38c2a6d 100644 --- a/amm/contracts/stable_pool/token_rate.rs +++ b/amm/contracts/stable_pool/token_rate.rs @@ -33,7 +33,7 @@ impl TokenRate { token_rate_contract, expiration_duration_ms, )); - _ = rate.update_rate_no_cache(current_time); + _ = rate.force_update_rate(current_time); rate } @@ -60,7 +60,7 @@ impl TokenRate { /// Update rate without expiry check. /// /// Returns `true` if value of the new rate is different than the previous. - pub fn update_rate_no_cache(&mut self, current_time: u64) -> bool { + pub fn force_update_rate(&mut self, current_time: u64) -> bool { match self { Self::External(external) => external.update_rate_no_cache(current_time), Self::Constant(_) => false, diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index eb03623..650a86d 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -5,7 +5,6 @@ use primitive_types::U256; pub use stable_pool_contract::StablePool as _; pub use stable_pool_contract::StablePoolError; -pub use stable_pool_contract::StablePoolView as _; use drink::{self, runtime::MinimalRuntime, session::Session, AccountId32}; diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index 54bfc46..5faaffd 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -50,7 +50,7 @@ pub fn upload_all(session: &mut Session) { pub mod stable_swap { use super::*; - use stable_pool_contract::{StablePool as _, StablePoolError, StablePoolView as _}; + use stable_pool_contract::{StablePool as _, StablePoolError}; pub fn setup( session: &mut Session, diff --git a/amm/traits/lib.rs b/amm/traits/lib.rs index 0cd01d7..6b88ebb 100644 --- a/amm/traits/lib.rs +++ b/amm/traits/lib.rs @@ -9,4 +9,4 @@ pub type Balance = ::Bala pub use amm_helpers::math::MathError; pub use ownable2step::{Ownable2Step, Ownable2StepData, Ownable2StepError, Ownable2StepResult}; pub use rate_provider::RateProvider; -pub use stable_pool::{StablePool, StablePoolError, StablePoolView}; +pub use stable_pool::{StablePool, StablePoolError}; diff --git a/amm/traits/ownable2step.rs b/amm/traits/ownable2step.rs index 77d7402..f49d804 100644 --- a/amm/traits/ownable2step.rs +++ b/amm/traits/ownable2step.rs @@ -33,7 +33,7 @@ pub trait Ownable2Step { /// The owner of the contract renounces the ownership. /// To start the process, the owner has to initiate ownership transfer to this contract's address. - /// Can anly be caller by the current owner. + /// Can only be called by the current owner. #[ink(message)] fn renounce_ownership(&mut self) -> Ownable2StepResult<()>; diff --git a/amm/traits/stable_pool.rs b/amm/traits/stable_pool.rs index 587eba4..9bb2f53 100644 --- a/amm/traits/stable_pool.rs +++ b/amm/traits/stable_pool.rs @@ -6,7 +6,7 @@ use psp22::PSP22Error; use crate::{MathError, Ownable2StepError}; #[ink::trait_definition] -pub trait StablePoolView { +pub trait StablePool { /// Returns list of tokens in the pool. #[ink(message)] fn tokens(&self) -> Vec; @@ -23,30 +23,34 @@ pub trait StablePoolView { #[ink(message)] fn fees(&self) -> (u32, u32); + /// Protocol fees receiver (if any) + #[ink(message)] + fn fee_receiver(&self) -> Option; + /// Updates cached token rates if expired and /// returns current tokens rates with precision of 12 decimal places. #[ink(message)] fn token_rates(&mut self) -> Vec; - /// Calculate swap amount of token_out - /// given token_in amount. - /// Returns (amount_out, fee) - /// NOTE: fee is applied to token_out + /// Calculate swap amount of `token_out` + /// given `token_in amount`. + /// Returns a tuple of (amount out, fee) + /// NOTE: fee is applied on `token_out` #[ink(message)] fn get_swap_amount_out( - &mut self, + &self, token_in: AccountId, token_out: AccountId, token_in_amount: u128, ) -> Result<(u128, u128), StablePoolError>; - /// Calculate required amount of token_in - /// given swap token_out amount - /// Returns (amount_in, fee) - /// fee is applied to token_out + /// Calculate required swap amount of `token_in` + /// to get `token_out_amount`. + /// Returns a tuple of (amount in, fee) + /// NOTE: fee is applied on `token_out` #[ink(message)] fn get_swap_amount_in( - &mut self, + &self, token_in: AccountId, token_out: AccountId, token_out_amount: u128, @@ -54,10 +58,10 @@ pub trait StablePoolView { /// Calculate how many lp tokens will be minted /// given deposit `amounts`. - /// Returns (lp_amount, fee) + /// Returns a tuple of (lpt amount, fee) #[ink(message)] fn get_mint_liquidity_for_amounts( - &mut self, + &self, amounts: Vec, ) -> Result<(u128, u128), StablePoolError>; @@ -72,10 +76,10 @@ pub trait StablePoolView { /// Calculate how many lp tokens will be burned /// given withdraw `amounts`. - /// Returns (lp_amount, fee) + /// Returns a tuple of (lpt amount, fee part) #[ink(message)] fn get_burn_liquidity_for_amounts( - &mut self, + &self, amounts: Vec, ) -> Result<(u128, u128), StablePoolError>; @@ -87,16 +91,13 @@ pub trait StablePoolView { &mut self, liquidity: u128, ) -> Result, StablePoolError>; -} -#[ink::trait_definition] -pub trait StablePool { - /// Mints LP tokens to `to` account from imbalanced `amounts`. - /// `to` account must allow enough spending allowance of underlying tokens + /// Deposit `amounts` of tokens to receive lpt tokens to `to` account. + /// Caller must allow enough spending allowance of underlying tokens /// for this contract. /// Returns an error if the minted LP tokens amount is less /// than `min_share_amount`. - /// Returns (minted_share_amount, fee_part) + /// Returns a tuple of (minted lpt amount, fee) #[ink(message)] fn add_liquidity( &mut self, @@ -107,7 +108,7 @@ pub trait StablePool { /// Burns LP tokens and withdraws underlying tokens to `to` account /// in imbalanced `amounts`. - /// Returns (burned_share_amount, fee_part) + /// Returns a tuple of (burned lpt amount, fee part) #[ink(message)] fn remove_liquidity_by_amounts( &mut self, @@ -116,9 +117,9 @@ pub trait StablePool { to: AccountId, ) -> Result<(u128, u128), StablePoolError>; - /// Burns LP tokens and withdraws underlying tokens in balanced amounts to `to` account. + /// Burns lp tokens and withdraws underlying tokens in balanced amounts to `to` account. /// Fails if any of the amounts received is less than in `min_amounts`. - /// Returns (amounts_out, fee_part) + /// Returns withdrawal amounts #[ink(message)] fn remove_liquidity_by_shares( &mut self, @@ -129,11 +130,12 @@ pub trait StablePool { /// Swaps token_in to token_out. /// Swapped tokens are transferred to the `to` account. - /// caller account must allow enough spending allowance of token_in + /// caller account must allow enough spending allowance of `token_in` /// for this contract. - /// Returns an error if swapped token_out amount is less than + /// Returns an error if swapped `token_out` amount is less than /// `min_token_out_amount`. - /// Returns (token_out_amount, fee_amount) + /// NOTE: Fee is applied on `token_out`. + /// Returns a tuple of (token out amount, fee amount) #[ink(message)] fn swap_exact_in( &mut self, @@ -146,12 +148,12 @@ pub trait StablePool { /// Swaps token_in to token_out. /// Swapped tokens are transferred to the `to` account. - /// caller account must allow enough spending allowance of token_out + /// Caller account must allow enough spending allowance of `token_in` /// for this contract. - /// Returns an error if to get token_out_amount of token_out it is required - /// to spend more than `max_token_in_amount` of token_in. - /// NOTE: Fee is applied to `token_out`. - /// Returns (token_in_amount, fee_amount) + /// Returns an error if it is required to spend more than + /// `max_token_in_amount` to get `token_out_amount`. + /// NOTE: Fee is applied on `token_out`. + /// Returns a tuple of (token in amount, fee amount) #[ink(message)] fn swap_exact_out( &mut self, @@ -164,7 +166,7 @@ pub trait StablePool { /// Swaps excess reserve balance of `token_in` to `token_out`. /// Swapped tokens are transferred to the `to` account. - /// Returns (token_out_amount, fee_amount) + /// Returns a tuple of (token out amount, fee amount) #[ink(message)] fn swap_received( &mut self, @@ -174,8 +176,10 @@ pub trait StablePool { to: AccountId, ) -> Result<(u128, u128), StablePoolError>; + /// Update cached rates without expiry check. + /// Can be called by anyone. #[ink(message)] - fn force_update_rate(&mut self); + fn force_update_rates(&mut self); // --- OWNER RESTRICTED FUNCTIONS --- // @@ -210,7 +214,7 @@ pub enum StablePoolError { InsufficientLiquidityMinted, InsufficientLiquidityBurned, InsufficientOutputAmount, - TooLargeInputAmount, + InsufficientLiquidity, InsufficientInputAmount, IncorrectTokenCount, TooLargeTokenDecimal, diff --git a/helpers/stable_swap_math/mod.rs b/helpers/stable_swap_math/mod.rs index 2c23405..0f9087e 100644 --- a/helpers/stable_swap_math/mod.rs +++ b/helpers/stable_swap_math/mod.rs @@ -118,8 +118,8 @@ fn compute_d_next( .ok_or(MathError::DivByZero(2)) } -/// Returns new reserve of `y` tokens -/// given new reserve of `x` tokens +/// Returns new reserve of `token_y_id` +/// given new reserve of `token_x_id`. /// /// NOTE: it does not check if `token_x_id` != `token_y_id` and if tokens' `id`s are out of bounds fn compute_y( @@ -177,7 +177,7 @@ fn compute_y( for _ in 0..MAX_ITERATIONS { let y = compute_y_next(y_prev, b, c, d)?; if y.abs_diff(y_prev) <= 1.into() { - return Ok(y.try_into().map_err(|_| MathError::CastOverflow(11))?); + return y.try_into().map_err(|_| MathError::CastOverflow(11)); } y_prev = y; } @@ -202,30 +202,30 @@ fn compute_y_next(y_prev: U256, b: U256, c: U256, d: U256) -> Result, fees: &Fees, amp_coef: u128, ) -> Result<(u128, u128), MathError> { let y = compute_y( token_in_amount - .checked_add(current_reserves[token_in_idx]) + .checked_add(current_reserves[token_in_id]) .ok_or(MathError::AddOverflow(9))?, current_reserves, - token_in_idx, - token_out_idx, + token_in_id, + token_out_id, amp_coef, )?; // sub 1 in case there are any rounding errors // https://github.com/curvefi/curve-contract/blob/b0bbf77f8f93c9c5f4e415bce9cd71f0cdee960e/contracts/pool-templates/base/SwapTemplateBase.vy#L466 - let dy = current_reserves[token_out_idx] + let dy = current_reserves[token_out_id] .checked_sub(y) .ok_or(MathError::SubUnderflow(7))? .checked_sub(1) @@ -239,38 +239,38 @@ fn swap_to( pub fn rated_swap_to( rates: &[u128], - token_in_idx: usize, + token_in_id: usize, token_in_amount: u128, - token_out_idx: usize, + token_out_id: usize, current_reserves: &[u128], fees: &Fees, amp_coef: u128, ) -> Result<(u128, u128), MathError> { - let r_token_in_amount = amount_to_rated(token_in_amount, rates[token_in_idx])?; + let r_token_in_amount = amount_to_rated(token_in_amount, rates[token_in_id])?; let r_current_reserves = amounts_to_rated(current_reserves, rates)?; let (r_amount_swapped, r_fee) = swap_to( - token_in_idx, + token_in_id, r_token_in_amount, - token_out_idx, + token_out_id, &r_current_reserves, fees, amp_coef, )?; - let amount_swapped = amount_from_rated(r_amount_swapped, rates[token_out_idx])?; - let fee = amount_from_rated(r_fee, rates[token_out_idx])?; + let amount_swapped = amount_from_rated(r_amount_swapped, rates[token_out_id])?; + let fee = amount_from_rated(r_fee, rates[token_out_id])?; Ok((amount_swapped, fee)) } -/// Compute SwapResult after an exchange given `amount_out` of the `token_out_id` +/// Compute swap result after an exchange given `token_amount_out` of the `token_out_id` /// panics if token ids are out of bounds -/// NOTICE: it does not check if `token_in_id` != `token_out_id` -/// /// Returns (amount_in, fee_amount) +/// Returns a tuple (amount in, fee amount) +/// NOTE: it does not check if `token_in_id` != `token_out_id` fn swap_from( - token_in_idx: usize, + token_in_id: usize, token_out_amount: u128, // Net amount (w/o fee) - token_out_idx: usize, + token_out_id: usize, current_reserves: &Vec, fees: &Fees, amp_coef: u128, @@ -282,16 +282,16 @@ fn swap_from( .ok_or(MathError::AddOverflow(11))?; let y = compute_y( - current_reserves[token_out_idx] + current_reserves[token_out_id] .checked_sub(token_out_amount_plus_fee) .ok_or(MathError::SubUnderflow(12))?, current_reserves, - token_out_idx, - token_in_idx, + token_out_id, + token_in_id, amp_coef, )?; let dy: u128 = y - .checked_sub(current_reserves[token_in_idx]) + .checked_sub(current_reserves[token_in_id]) .ok_or(MathError::SubUnderflow(13))?; Ok((dy, fee)) @@ -299,33 +299,34 @@ fn swap_from( pub fn rated_swap_from( rates: &[u128], - token_in_idx: usize, + token_in_id: usize, token_out_amount: u128, - token_out_idx: usize, + token_out_id: usize, current_reserves: &[u128], fees: &Fees, amp_coef: u128, ) -> Result<(u128, u128), MathError> { - let r_token_out_amount = amount_to_rated(token_out_amount, rates[token_out_idx])?; + let r_token_out_amount = amount_to_rated(token_out_amount, rates[token_out_id])?; let r_current_reserves = amounts_to_rated(current_reserves, rates)?; let (r_dy, r_fee) = swap_from( - token_in_idx, + token_in_id, r_token_out_amount, - token_out_idx, + token_out_id, &r_current_reserves, fees, amp_coef, )?; // add one in case of rounding error, for the protocol advantage - let dy = amount_from_rated(r_dy, rates[token_in_idx])? + let dy = amount_from_rated(r_dy, rates[token_in_id])? .checked_add(1) .ok_or(MathError::AddOverflow(12))?; - let fee = amount_from_rated(r_fee, rates[token_out_idx])?; + let fee = amount_from_rated(r_fee, rates[token_out_id])?; Ok((dy, fee)) } -/// Compute the amount of LP tokens to mint after a deposit -/// return +/// Given `deposit_amounts` user want deposit, calculates how many lpt +/// are required to be minted. +/// Returns a tuple of (lpt to mint, fee) fn compute_lp_amount_for_deposit( deposit_amounts: &Vec, old_reserves: &Vec, @@ -437,19 +438,16 @@ pub fn rated_compute_lp_amount_for_deposit( ) } -/*** - * Returns amounts of tokens minted/burned for a given amount of LP tokens - * and the current reserves - */ +/// Computes proportional token amounts to the given `lpt_amount`. pub fn compute_amounts_given_lp( - lp_amount: u128, + lpt_amount: u128, reserves: &Vec, pool_token_supply: u128, ) -> Result, MathError> { let mut amounts = Vec::with_capacity(reserves.len()); for &reserve in reserves { amounts.push( - casted_mul(reserve, lp_amount) + casted_mul(reserve, lpt_amount) .checked_div(pool_token_supply.into()) .ok_or(MathError::DivByZero(13))? .try_into() @@ -459,9 +457,9 @@ pub fn compute_amounts_given_lp( Ok(amounts) } -/// given token_out user want get and total tokens in pool and lp token supply, -/// return -/// all amounts are in c_amount (comparable amount) +/// Given `withdraw_amounts` user want get, calculates how many lpt +/// are required to be burnt +/// Returns a tuple of (lpt to burn, fee part) fn compute_lp_amount_for_withdraw( withdraw_amounts: &[u128], old_reserves: &Vec,