From 670a8a5fd33b548056193f7019542293fb8e0112 Mon Sep 17 00:00:00 2001 From: Dorin Marian Iancu Date: Thu, 25 Jan 2024 10:10:35 +0200 Subject: [PATCH 1/6] add initial liq --- dex/pair/src/lib.rs | 86 ++---------------- dex/pair/src/pair_actions/common_methods.rs | 11 +++ .../src/pair_actions/common_result_types.rs | 10 +++ dex/pair/src/pair_actions/initial_liq.rs | 87 +++++++++++++++++++ dex/pair/src/pair_actions/mod.rs | 3 + dex/pair/wasm-pair-full/src/lib.rs | 2 +- dex/pair/wasm/src/lib.rs | 2 +- dex/router/tests/router_test.rs | 2 +- .../src/external_contracts_interactions.rs | 5 +- .../proxy_dex/src/pair_interactions.rs | 5 +- 10 files changed, 128 insertions(+), 85 deletions(-) create mode 100644 dex/pair/src/pair_actions/common_methods.rs create mode 100644 dex/pair/src/pair_actions/common_result_types.rs create mode 100644 dex/pair/src/pair_actions/initial_liq.rs create mode 100644 dex/pair/src/pair_actions/mod.rs diff --git a/dex/pair/src/lib.rs b/dex/pair/src/lib.rs index 9b800e67a..2cd827740 100644 --- a/dex/pair/src/lib.rs +++ b/dex/pair/src/lib.rs @@ -11,6 +11,7 @@ mod events; pub mod fee; mod liquidity_pool; pub mod locking_wrapper; +pub mod pair_actions; pub mod safe_price; pub mod safe_price_view; @@ -18,23 +19,15 @@ use crate::contexts::add_liquidity::AddLiquidityContext; use crate::contexts::remove_liquidity::RemoveLiquidityContext; use crate::errors::*; -use common_errors::ERROR_PERMISSION_DENIED; use contexts::base::*; use contexts::swap::SwapContext; +use pair_actions::common_result_types::{ + AddLiquidityResultType, RemoveLiquidityResultType, SwapTokensFixedInputResultType, + SwapTokensFixedOutputResultType, +}; use pausable::State; use permissions_module::Permissions; -pub type AddLiquidityResultType = - MultiValue3, EsdtTokenPayment, EsdtTokenPayment>; - -pub type RemoveLiquidityResultType = - MultiValue2, EsdtTokenPayment>; - -pub type SwapTokensFixedInputResultType = EsdtTokenPayment; - -pub type SwapTokensFixedOutputResultType = - MultiValue2, EsdtTokenPayment>; - #[multiversx_sc::contract] pub trait Pair: amm::AmmModule @@ -49,6 +42,8 @@ pub trait Pair: + locking_wrapper::LockingWrapperModule + permissions_module::PermissionsModule + pausable::PausableModule + + pair_actions::initial_liq::InitialLiquidityModule + + pair_actions::common_methods::CommonMethodsModule { #[init] fn init( @@ -105,68 +100,6 @@ pub trait Pair: #[endpoint] fn upgrade(&self) {} - #[payable("*")] - #[endpoint(addInitialLiquidity)] - fn add_initial_liquidity(&self) -> AddLiquidityResultType { - let mut storage_cache = StorageCache::new(self); - let caller = self.blockchain().get_caller(); - - let opt_initial_liq_adder = self.initial_liquidity_adder().get(); - if let Some(initial_liq_adder) = opt_initial_liq_adder { - require!(caller == initial_liq_adder, ERROR_PERMISSION_DENIED); - } - - let [first_payment, second_payment] = self.call_value().multi_esdt(); - require!( - first_payment.token_identifier == storage_cache.first_token_id - && first_payment.amount > 0, - ERROR_BAD_PAYMENT_TOKENS - ); - require!( - second_payment.token_identifier == storage_cache.second_token_id - && second_payment.amount > 0, - ERROR_BAD_PAYMENT_TOKENS - ); - require!( - !self.is_state_active(storage_cache.contract_state), - ERROR_ACTIVE - ); - require!( - storage_cache.lp_token_supply == 0, - ERROR_INITIAL_LIQUIDITY_ALREADY_ADDED - ); - - let first_token_optimal_amount = &first_payment.amount; - let second_token_optimal_amount = &second_payment.amount; - let liq_added = self.pool_add_initial_liquidity( - first_token_optimal_amount, - second_token_optimal_amount, - &mut storage_cache, - ); - - self.send() - .esdt_local_mint(&storage_cache.lp_token_id, 0, &liq_added); - self.send() - .direct_esdt(&caller, &storage_cache.lp_token_id, 0, &liq_added); - - self.state().set(State::PartialActive); - - let add_liq_context = AddLiquidityContext { - first_payment: first_payment.clone(), - second_payment: second_payment.clone(), - first_token_amount_min: BigUint::from(1u32), - second_token_amount_min: BigUint::from(1u32), - first_token_optimal_amount: first_token_optimal_amount.clone(), - second_token_optimal_amount: second_token_optimal_amount.clone(), - liq_added, - }; - let output = self.build_add_initial_liq_results(&storage_cache, &add_liq_context); - - self.emit_add_liquidity_event(&storage_cache, add_liq_context); - - output - } - #[payable("*")] #[endpoint(addLiquidity)] fn add_liquidity( @@ -675,11 +608,6 @@ pub trait Pair: } } - #[inline] - fn is_state_active(&self, state: State) -> bool { - state == State::Active || state == State::PartialActive - } - #[inline] fn can_swap(&self, state: State) -> bool { state == State::Active diff --git a/dex/pair/src/pair_actions/common_methods.rs b/dex/pair/src/pair_actions/common_methods.rs new file mode 100644 index 000000000..5d145e9bc --- /dev/null +++ b/dex/pair/src/pair_actions/common_methods.rs @@ -0,0 +1,11 @@ +use pausable::State; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait CommonMethodsModule { + #[inline] + fn is_state_active(&self, state: State) -> bool { + state == State::Active || state == State::PartialActive + } +} diff --git a/dex/pair/src/pair_actions/common_result_types.rs b/dex/pair/src/pair_actions/common_result_types.rs new file mode 100644 index 000000000..7fb6407b0 --- /dev/null +++ b/dex/pair/src/pair_actions/common_result_types.rs @@ -0,0 +1,10 @@ +multiversx_sc::imports!(); + +pub type AddLiquidityResultType = + MultiValue3, EsdtTokenPayment, EsdtTokenPayment>; + +pub type RemoveLiquidityResultType = MultiValue2, EsdtTokenPayment>; + +pub type SwapTokensFixedInputResultType = EsdtTokenPayment; + +pub type SwapTokensFixedOutputResultType = MultiValue2, EsdtTokenPayment>; diff --git a/dex/pair/src/pair_actions/initial_liq.rs b/dex/pair/src/pair_actions/initial_liq.rs new file mode 100644 index 000000000..e98cbb61e --- /dev/null +++ b/dex/pair/src/pair_actions/initial_liq.rs @@ -0,0 +1,87 @@ +use common_errors::ERROR_PERMISSION_DENIED; +use pausable::State; + +use crate::{ + contexts::add_liquidity::AddLiquidityContext, StorageCache, ERROR_ACTIVE, + ERROR_BAD_PAYMENT_TOKENS, ERROR_INITIAL_LIQUIDITY_ALREADY_ADDED, +}; + +use super::common_result_types::AddLiquidityResultType; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait InitialLiquidityModule: + crate::liquidity_pool::LiquidityPoolModule + + crate::amm::AmmModule + + crate::contexts::output_builder::OutputBuilderModule + + crate::locking_wrapper::LockingWrapperModule + + crate::events::EventsModule + + crate::config::ConfigModule + + token_send::TokenSendModule + + permissions_module::PermissionsModule + + pausable::PausableModule + + super::common_methods::CommonMethodsModule +{ + #[payable("*")] + #[endpoint(addInitialLiquidity)] + fn add_initial_liquidity(&self) -> AddLiquidityResultType { + let mut storage_cache = StorageCache::new(self); + let caller = self.blockchain().get_caller(); + + let opt_initial_liq_adder = self.initial_liquidity_adder().get(); + if let Some(initial_liq_adder) = opt_initial_liq_adder { + require!(caller == initial_liq_adder, ERROR_PERMISSION_DENIED); + } + + let [first_payment, second_payment] = self.call_value().multi_esdt(); + require!( + first_payment.token_identifier == storage_cache.first_token_id + && first_payment.amount > 0, + ERROR_BAD_PAYMENT_TOKENS + ); + require!( + second_payment.token_identifier == storage_cache.second_token_id + && second_payment.amount > 0, + ERROR_BAD_PAYMENT_TOKENS + ); + require!( + !self.is_state_active(storage_cache.contract_state), + ERROR_ACTIVE + ); + require!( + storage_cache.lp_token_supply == 0, + ERROR_INITIAL_LIQUIDITY_ALREADY_ADDED + ); + + let first_token_optimal_amount = &first_payment.amount; + let second_token_optimal_amount = &second_payment.amount; + let liq_added = self.pool_add_initial_liquidity( + first_token_optimal_amount, + second_token_optimal_amount, + &mut storage_cache, + ); + + self.send() + .esdt_local_mint(&storage_cache.lp_token_id, 0, &liq_added); + self.send() + .direct_esdt(&caller, &storage_cache.lp_token_id, 0, &liq_added); + + self.state().set(State::PartialActive); + + let add_liq_context = AddLiquidityContext { + first_payment: first_payment.clone(), + second_payment: second_payment.clone(), + first_token_amount_min: BigUint::from(1u32), + second_token_amount_min: BigUint::from(1u32), + first_token_optimal_amount: first_token_optimal_amount.clone(), + second_token_optimal_amount: second_token_optimal_amount.clone(), + liq_added, + }; + let output = self.build_add_initial_liq_results(&storage_cache, &add_liq_context); + + self.emit_add_liquidity_event(&storage_cache, add_liq_context); + + output + } +} diff --git a/dex/pair/src/pair_actions/mod.rs b/dex/pair/src/pair_actions/mod.rs new file mode 100644 index 000000000..e05e00482 --- /dev/null +++ b/dex/pair/src/pair_actions/mod.rs @@ -0,0 +1,3 @@ +pub mod common_methods; +pub mod common_result_types; +pub mod initial_liq; diff --git a/dex/pair/wasm-pair-full/src/lib.rs b/dex/pair/wasm-pair-full/src/lib.rs index 17b626ecc..fe3d65503 100644 --- a/dex/pair/wasm-pair-full/src/lib.rs +++ b/dex/pair/wasm-pair-full/src/lib.rs @@ -21,7 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - addInitialLiquidity => add_initial_liquidity addLiquidity => add_liquidity removeLiquidity => remove_liquidity removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token @@ -75,6 +74,7 @@ multiversx_sc_wasm_adapter::endpoints! { pause => pause resume => resume getState => state + addInitialLiquidity => add_initial_liquidity getLpTokensSafePriceByDefaultOffset => get_lp_tokens_safe_price_by_default_offset getLpTokensSafePriceByRoundOffset => get_lp_tokens_safe_price_by_round_offset getLpTokensSafePriceByTimestampOffset => get_lp_tokens_safe_price_by_timestamp_offset diff --git a/dex/pair/wasm/src/lib.rs b/dex/pair/wasm/src/lib.rs index 57339355b..45f56c90d 100644 --- a/dex/pair/wasm/src/lib.rs +++ b/dex/pair/wasm/src/lib.rs @@ -21,7 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - addInitialLiquidity => add_initial_liquidity addLiquidity => add_liquidity removeLiquidity => remove_liquidity removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token @@ -75,6 +74,7 @@ multiversx_sc_wasm_adapter::endpoints! { pause => pause resume => resume getState => state + addInitialLiquidity => add_initial_liquidity ) } diff --git a/dex/router/tests/router_test.rs b/dex/router/tests/router_test.rs index b4b7ad010..cb5f1a78f 100644 --- a/dex/router/tests/router_test.rs +++ b/dex/router/tests/router_test.rs @@ -9,7 +9,7 @@ use multiversx_sc::{ MultiValueEncoded, }, }; -use pair::{config::ConfigModule, Pair}; +use pair::{config::ConfigModule, pair_actions::initial_liq::InitialLiquidityModule, Pair}; use pausable::{PausableModule, State}; use router::{ enable_swap_by_user::EnableSwapByUserModule, diff --git a/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs b/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs index 163ebb922..fce01d4fa 100644 --- a/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs +++ b/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs @@ -9,10 +9,11 @@ use farm_staking::{ unstake_farm::ProxyTrait as _, }; use farm_with_locked_rewards::ProxyTrait as _; -use pair::safe_price_view::ProxyTrait as _; +use pair::{ + pair_actions::common_result_types::RemoveLiquidityResultType, safe_price_view::ProxyTrait as _, +}; use crate::result_types::*; -use pair::RemoveLiquidityResultType; pub type SafePriceResult = MultiValue2, EsdtTokenPayment>; diff --git a/locked-asset/proxy_dex/src/pair_interactions.rs b/locked-asset/proxy_dex/src/pair_interactions.rs index 40b6b46a9..24cf27759 100644 --- a/locked-asset/proxy_dex/src/pair_interactions.rs +++ b/locked-asset/proxy_dex/src/pair_interactions.rs @@ -1,6 +1,9 @@ multiversx_sc::imports!(); -use pair::{AddLiquidityResultType, ProxyTrait as _, RemoveLiquidityResultType}; +use pair::{ + pair_actions::common_result_types::{AddLiquidityResultType, RemoveLiquidityResultType}, + ProxyTrait as _, +}; pub struct AddLiquidityResultWrapper { pub lp_tokens_received: EsdtTokenPayment, From 3b5df875c1f51c0f22e08bfc472c99e5751e7433 Mon Sep 17 00:00:00 2001 From: Dorin Marian Iancu Date: Thu, 25 Jan 2024 10:37:29 +0200 Subject: [PATCH 2/6] add liq --- dex/fuzz/src/fuzz_pair.rs | 2 +- dex/pair/src/lib.rs | 92 +------------- dex/pair/src/pair_actions/add_liq.rs | 114 ++++++++++++++++++ dex/pair/src/pair_actions/mod.rs | 1 + dex/pair/tests/pair_setup/mod.rs | 1 + dex/pair/wasm-pair-full/src/lib.rs | 2 +- dex/pair/wasm/src/lib.rs | 2 +- dex/router/tests/router_setup/mod.rs | 1 + .../mod.rs | 1 + .../proxy_dex/src/pair_interactions.rs | 5 +- 10 files changed, 126 insertions(+), 95 deletions(-) create mode 100644 dex/pair/src/pair_actions/add_liq.rs diff --git a/dex/fuzz/src/fuzz_pair.rs b/dex/fuzz/src/fuzz_pair.rs index 3ccc5031a..b9c1853e7 100644 --- a/dex/fuzz/src/fuzz_pair.rs +++ b/dex/fuzz/src/fuzz_pair.rs @@ -12,7 +12,7 @@ pub mod fuzz_pair_test { use rand::prelude::*; use crate::fuzz_data::fuzz_data_tests::*; - use pair::*; + use pair::{pair_actions::add_liq::AddLiquidityModule, *}; pub fn add_liquidity( fuzzer_data: &mut FuzzerData< diff --git a/dex/pair/src/lib.rs b/dex/pair/src/lib.rs index 2cd827740..3de95d572 100644 --- a/dex/pair/src/lib.rs +++ b/dex/pair/src/lib.rs @@ -15,7 +15,6 @@ pub mod pair_actions; pub mod safe_price; pub mod safe_price_view; -use crate::contexts::add_liquidity::AddLiquidityContext; use crate::contexts::remove_liquidity::RemoveLiquidityContext; use crate::errors::*; @@ -43,6 +42,7 @@ pub trait Pair: + permissions_module::PermissionsModule + pausable::PausableModule + pair_actions::initial_liq::InitialLiquidityModule + + pair_actions::add_liq::AddLiquidityModule + pair_actions::common_methods::CommonMethodsModule { #[init] @@ -100,96 +100,6 @@ pub trait Pair: #[endpoint] fn upgrade(&self) {} - #[payable("*")] - #[endpoint(addLiquidity)] - fn add_liquidity( - &self, - first_token_amount_min: BigUint, - second_token_amount_min: BigUint, - ) -> AddLiquidityResultType { - require!( - first_token_amount_min > 0 && second_token_amount_min > 0, - ERROR_INVALID_ARGS - ); - - let mut storage_cache = StorageCache::new(self); - let caller = self.blockchain().get_caller(); - - let [first_payment, second_payment] = self.call_value().multi_esdt(); - require!( - first_payment.token_identifier == storage_cache.first_token_id - && first_payment.amount > 0, - ERROR_BAD_PAYMENT_TOKENS - ); - require!( - second_payment.token_identifier == storage_cache.second_token_id - && second_payment.amount > 0, - ERROR_BAD_PAYMENT_TOKENS - ); - require!( - self.is_state_active(storage_cache.contract_state), - ERROR_NOT_ACTIVE - ); - require!( - storage_cache.lp_token_id.is_valid_esdt_identifier(), - ERROR_LP_TOKEN_NOT_ISSUED - ); - require!( - self.initial_liquidity_adder().get().is_none() || storage_cache.lp_token_supply != 0, - ERROR_INITIAL_LIQUIDITY_NOT_ADDED - ); - - self.update_safe_price( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let initial_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let mut add_liq_context = AddLiquidityContext::new( - first_payment, - second_payment, - first_token_amount_min, - second_token_amount_min, - ); - self.set_optimal_amounts(&mut add_liq_context, &storage_cache); - - add_liq_context.liq_added = if storage_cache.lp_token_supply == 0u64 { - self.pool_add_initial_liquidity( - &add_liq_context.first_token_optimal_amount, - &add_liq_context.second_token_optimal_amount, - &mut storage_cache, - ) - } else { - self.pool_add_liquidity( - &add_liq_context.first_token_optimal_amount, - &add_liq_context.second_token_optimal_amount, - &mut storage_cache, - ) - }; - - let new_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); - - self.send() - .esdt_local_mint(&storage_cache.lp_token_id, 0, &add_liq_context.liq_added); - - let output_payments = self.build_add_liq_output_payments(&storage_cache, &add_liq_context); - self.send_multiple_tokens_if_not_zero(&caller, &output_payments); - - let output = self.build_add_liq_results(&storage_cache, &add_liq_context); - - self.emit_add_liquidity_event(&storage_cache, add_liq_context); - - output - } - #[payable("*")] #[endpoint(removeLiquidity)] fn remove_liquidity( diff --git a/dex/pair/src/pair_actions/add_liq.rs b/dex/pair/src/pair_actions/add_liq.rs new file mode 100644 index 000000000..0878219a7 --- /dev/null +++ b/dex/pair/src/pair_actions/add_liq.rs @@ -0,0 +1,114 @@ +use crate::{ + contexts::add_liquidity::AddLiquidityContext, StorageCache, ERROR_BAD_PAYMENT_TOKENS, + ERROR_INITIAL_LIQUIDITY_NOT_ADDED, ERROR_INVALID_ARGS, ERROR_K_INVARIANT_FAILED, + ERROR_LP_TOKEN_NOT_ISSUED, ERROR_NOT_ACTIVE, +}; + +use super::common_result_types::AddLiquidityResultType; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait AddLiquidityModule: + crate::liquidity_pool::LiquidityPoolModule + + crate::amm::AmmModule + + crate::contexts::output_builder::OutputBuilderModule + + crate::locking_wrapper::LockingWrapperModule + + crate::events::EventsModule + + crate::safe_price::SafePriceModule + + crate::config::ConfigModule + + token_send::TokenSendModule + + permissions_module::PermissionsModule + + pausable::PausableModule + + super::common_methods::CommonMethodsModule +{ + #[payable("*")] + #[endpoint(addLiquidity)] + fn add_liquidity( + &self, + first_token_amount_min: BigUint, + second_token_amount_min: BigUint, + ) -> AddLiquidityResultType { + require!( + first_token_amount_min > 0 && second_token_amount_min > 0, + ERROR_INVALID_ARGS + ); + + let mut storage_cache = StorageCache::new(self); + let caller = self.blockchain().get_caller(); + + let [first_payment, second_payment] = self.call_value().multi_esdt(); + require!( + first_payment.token_identifier == storage_cache.first_token_id + && first_payment.amount > 0, + ERROR_BAD_PAYMENT_TOKENS + ); + require!( + second_payment.token_identifier == storage_cache.second_token_id + && second_payment.amount > 0, + ERROR_BAD_PAYMENT_TOKENS + ); + require!( + self.is_state_active(storage_cache.contract_state), + ERROR_NOT_ACTIVE + ); + require!( + storage_cache.lp_token_id.is_valid_esdt_identifier(), + ERROR_LP_TOKEN_NOT_ISSUED + ); + require!( + self.initial_liquidity_adder().get().is_none() || storage_cache.lp_token_supply != 0, + ERROR_INITIAL_LIQUIDITY_NOT_ADDED + ); + + self.update_safe_price( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let initial_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let mut add_liq_context = AddLiquidityContext::new( + first_payment, + second_payment, + first_token_amount_min, + second_token_amount_min, + ); + self.set_optimal_amounts(&mut add_liq_context, &storage_cache); + + add_liq_context.liq_added = if storage_cache.lp_token_supply == 0u64 { + self.pool_add_initial_liquidity( + &add_liq_context.first_token_optimal_amount, + &add_liq_context.second_token_optimal_amount, + &mut storage_cache, + ) + } else { + self.pool_add_liquidity( + &add_liq_context.first_token_optimal_amount, + &add_liq_context.second_token_optimal_amount, + &mut storage_cache, + ) + }; + + let new_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); + + self.send() + .esdt_local_mint(&storage_cache.lp_token_id, 0, &add_liq_context.liq_added); + + let output_payments = self.build_add_liq_output_payments(&storage_cache, &add_liq_context); + self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + + let output = self.build_add_liq_results(&storage_cache, &add_liq_context); + + self.emit_add_liquidity_event(&storage_cache, add_liq_context); + + output + } +} diff --git a/dex/pair/src/pair_actions/mod.rs b/dex/pair/src/pair_actions/mod.rs index e05e00482..0d67ed85b 100644 --- a/dex/pair/src/pair_actions/mod.rs +++ b/dex/pair/src/pair_actions/mod.rs @@ -1,3 +1,4 @@ +pub mod add_liq; pub mod common_methods; pub mod common_result_types; pub mod initial_liq; diff --git a/dex/pair/tests/pair_setup/mod.rs b/dex/pair/tests/pair_setup/mod.rs index e7311eca5..d13f17d75 100644 --- a/dex/pair/tests/pair_setup/mod.rs +++ b/dex/pair/tests/pair_setup/mod.rs @@ -20,6 +20,7 @@ pub const USER_TOTAL_MEX_TOKENS: u64 = 5_000_000_000; pub const USER_TOTAL_WEGLD_TOKENS: u64 = 5_000_000_000; use pair::config::ConfigModule as PairConfigModule; +use pair::pair_actions::add_liq::AddLiquidityModule; use pair::safe_price_view::*; use pair::*; use pausable::{PausableModule, State}; diff --git a/dex/pair/wasm-pair-full/src/lib.rs b/dex/pair/wasm-pair-full/src/lib.rs index fe3d65503..df90222ae 100644 --- a/dex/pair/wasm-pair-full/src/lib.rs +++ b/dex/pair/wasm-pair-full/src/lib.rs @@ -21,7 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - addLiquidity => add_liquidity removeLiquidity => remove_liquidity removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token swapNoFeeAndForward => swap_no_fee @@ -75,6 +74,7 @@ multiversx_sc_wasm_adapter::endpoints! { resume => resume getState => state addInitialLiquidity => add_initial_liquidity + addLiquidity => add_liquidity getLpTokensSafePriceByDefaultOffset => get_lp_tokens_safe_price_by_default_offset getLpTokensSafePriceByRoundOffset => get_lp_tokens_safe_price_by_round_offset getLpTokensSafePriceByTimestampOffset => get_lp_tokens_safe_price_by_timestamp_offset diff --git a/dex/pair/wasm/src/lib.rs b/dex/pair/wasm/src/lib.rs index 45f56c90d..b2bfec007 100644 --- a/dex/pair/wasm/src/lib.rs +++ b/dex/pair/wasm/src/lib.rs @@ -21,7 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - addLiquidity => add_liquidity removeLiquidity => remove_liquidity removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token swapNoFeeAndForward => swap_no_fee @@ -75,6 +74,7 @@ multiversx_sc_wasm_adapter::endpoints! { resume => resume getState => state addInitialLiquidity => add_initial_liquidity + addLiquidity => add_liquidity ) } diff --git a/dex/router/tests/router_setup/mod.rs b/dex/router/tests/router_setup/mod.rs index 54f6330a3..7b2969361 100644 --- a/dex/router/tests/router_setup/mod.rs +++ b/dex/router/tests/router_setup/mod.rs @@ -28,6 +28,7 @@ pub const USER_CUSTOM_TOKEN_BALANCE: u64 = 1_000_000_000; pub const USER_USDC_BALANCE: u64 = 1_000_000; use pair::config::*; +use pair::pair_actions::add_liq::AddLiquidityModule; use pair::*; use pausable::{PausableModule, State}; use router::factory::*; diff --git a/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs b/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs index 95c734663..d223bf9f1 100644 --- a/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs +++ b/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs @@ -12,6 +12,7 @@ use multiversx_sc_scenario::whitebox_legacy::TxTokenTransfer; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, rust_biguint, whitebox_legacy::*, DebugApi, }; +use pair::pair_actions::add_liq::AddLiquidityModule; use simple_lock::locked_token::LockedTokenModule; use farm::exit_penalty::ExitPenaltyModule; diff --git a/locked-asset/proxy_dex/src/pair_interactions.rs b/locked-asset/proxy_dex/src/pair_interactions.rs index 24cf27759..ce4fdf7a0 100644 --- a/locked-asset/proxy_dex/src/pair_interactions.rs +++ b/locked-asset/proxy_dex/src/pair_interactions.rs @@ -1,7 +1,10 @@ multiversx_sc::imports!(); use pair::{ - pair_actions::common_result_types::{AddLiquidityResultType, RemoveLiquidityResultType}, + pair_actions::{ + add_liq::ProxyTrait as _, + common_result_types::{AddLiquidityResultType, RemoveLiquidityResultType}, + }, ProxyTrait as _, }; From 8f8075ae32e459f53790c6ded0e09498729f1233 Mon Sep 17 00:00:00 2001 From: Dorin Marian Iancu Date: Thu, 25 Jan 2024 10:45:26 +0200 Subject: [PATCH 3/6] remove liq --- dex/farm/src/exit_penalty.rs | 1 + dex/fuzz/src/fuzz_pair.rs | 5 +- dex/pair/src/lib.rs | 121 +-------------- dex/pair/src/pair_actions/mod.rs | 1 + dex/pair/src/pair_actions/remove_liq.rs | 140 ++++++++++++++++++ dex/pair/wasm-pair-full/src/lib.rs | 4 +- dex/pair/wasm/src/lib.rs | 4 +- .../src/external_contracts_interactions.rs | 3 +- .../mod.rs | 1 + .../proxy_dex/src/pair_interactions.rs | 10 +- 10 files changed, 158 insertions(+), 132 deletions(-) create mode 100644 dex/pair/src/pair_actions/remove_liq.rs diff --git a/dex/farm/src/exit_penalty.rs b/dex/farm/src/exit_penalty.rs index 388a8b1f2..e8905fade 100644 --- a/dex/farm/src/exit_penalty.rs +++ b/dex/farm/src/exit_penalty.rs @@ -2,6 +2,7 @@ multiversx_sc::imports!(); use common_errors::ERROR_PARAMETERS; use common_structs::Epoch; +use pair::pair_actions::remove_liq::ProxyTrait as _; pub const MAX_PERCENT: u64 = 10_000; pub const DEFAULT_PENALTY_PERCENT: u64 = 100; diff --git a/dex/fuzz/src/fuzz_pair.rs b/dex/fuzz/src/fuzz_pair.rs index b9c1853e7..480eed510 100644 --- a/dex/fuzz/src/fuzz_pair.rs +++ b/dex/fuzz/src/fuzz_pair.rs @@ -12,7 +12,10 @@ pub mod fuzz_pair_test { use rand::prelude::*; use crate::fuzz_data::fuzz_data_tests::*; - use pair::{pair_actions::add_liq::AddLiquidityModule, *}; + use pair::{ + pair_actions::{add_liq::AddLiquidityModule, remove_liq::RemoveLiquidityModule}, + *, + }; pub fn add_liquidity( fuzzer_data: &mut FuzzerData< diff --git a/dex/pair/src/lib.rs b/dex/pair/src/lib.rs index 3de95d572..021f61d6f 100644 --- a/dex/pair/src/lib.rs +++ b/dex/pair/src/lib.rs @@ -15,7 +15,6 @@ pub mod pair_actions; pub mod safe_price; pub mod safe_price_view; -use crate::contexts::remove_liquidity::RemoveLiquidityContext; use crate::errors::*; use contexts::base::*; @@ -43,6 +42,7 @@ pub trait Pair: + pausable::PausableModule + pair_actions::initial_liq::InitialLiquidityModule + pair_actions::add_liq::AddLiquidityModule + + pair_actions::remove_liq::RemoveLiquidityModule + pair_actions::common_methods::CommonMethodsModule { #[init] @@ -100,125 +100,6 @@ pub trait Pair: #[endpoint] fn upgrade(&self) {} - #[payable("*")] - #[endpoint(removeLiquidity)] - fn remove_liquidity( - &self, - first_token_amount_min: BigUint, - second_token_amount_min: BigUint, - ) -> RemoveLiquidityResultType { - require!( - first_token_amount_min > 0 && second_token_amount_min > 0, - ERROR_INVALID_ARGS - ); - - let mut storage_cache = StorageCache::new(self); - let caller = self.blockchain().get_caller(); - let payment = self.call_value().single_esdt(); - - require!( - self.is_state_active(storage_cache.contract_state), - ERROR_NOT_ACTIVE - ); - require!( - storage_cache.lp_token_id.is_valid_esdt_identifier(), - ERROR_LP_TOKEN_NOT_ISSUED - ); - require!( - payment.token_identifier == storage_cache.lp_token_id && payment.amount > 0, - ERROR_BAD_PAYMENT_TOKENS - ); - - self.update_safe_price( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let initial_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let mut remove_liq_context = RemoveLiquidityContext::new( - payment.amount, - first_token_amount_min, - second_token_amount_min, - ); - self.pool_remove_liquidity(&mut remove_liq_context, &mut storage_cache); - - let new_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - require!(new_k <= initial_k, ERROR_K_INVARIANT_FAILED); - - self.burn( - &storage_cache.lp_token_id, - &remove_liq_context.lp_token_payment_amount, - ); - - let output_payments = - self.build_remove_liq_output_payments(&storage_cache, &remove_liq_context); - self.send_multiple_tokens_if_not_zero(&caller, &output_payments); - - self.emit_remove_liquidity_event(&storage_cache, remove_liq_context); - - self.build_remove_liq_results(output_payments) - } - - #[payable("*")] - #[endpoint(removeLiquidityAndBuyBackAndBurnToken)] - fn remove_liquidity_and_burn_token(&self, token_to_buyback_and_burn: TokenIdentifier) { - let mut storage_cache = StorageCache::new(self); - let caller = self.blockchain().get_caller(); - let payment = self.call_value().single_esdt(); - - require!(self.whitelist().contains(&caller), ERROR_NOT_WHITELISTED); - require!( - storage_cache.lp_token_id.is_valid_esdt_identifier(), - ERROR_LP_TOKEN_NOT_ISSUED - ); - require!( - payment.token_identifier == storage_cache.lp_token_id && payment.amount > 0, - ERROR_BAD_PAYMENT_TOKENS - ); - - self.update_safe_price( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let mut remove_liq_context = - RemoveLiquidityContext::new(payment.amount, BigUint::from(1u64), BigUint::from(1u64)); - self.pool_remove_liquidity(&mut remove_liq_context, &mut storage_cache); - - self.burn( - &storage_cache.lp_token_id, - &remove_liq_context.lp_token_payment_amount, - ); - - let dest_address = ManagedAddress::zero(); - let first_token_id = storage_cache.first_token_id.clone(); - self.send_fee_slice( - &mut storage_cache, - SwapTokensOrder::PoolOrder, - &first_token_id, - &remove_liq_context.first_token_amount_removed, - &dest_address, - &token_to_buyback_and_burn, - ); - - let second_token_id = storage_cache.second_token_id.clone(); - self.send_fee_slice( - &mut storage_cache, - SwapTokensOrder::ReverseOrder, - &second_token_id, - &remove_liq_context.second_token_amount_removed, - &dest_address, - &token_to_buyback_and_burn, - ); - } - #[payable("*")] #[endpoint(swapNoFeeAndForward)] fn swap_no_fee(&self, token_out: TokenIdentifier, destination_address: ManagedAddress) { diff --git a/dex/pair/src/pair_actions/mod.rs b/dex/pair/src/pair_actions/mod.rs index 0d67ed85b..13495c791 100644 --- a/dex/pair/src/pair_actions/mod.rs +++ b/dex/pair/src/pair_actions/mod.rs @@ -2,3 +2,4 @@ pub mod add_liq; pub mod common_methods; pub mod common_result_types; pub mod initial_liq; +pub mod remove_liq; diff --git a/dex/pair/src/pair_actions/remove_liq.rs b/dex/pair/src/pair_actions/remove_liq.rs new file mode 100644 index 000000000..a1f234226 --- /dev/null +++ b/dex/pair/src/pair_actions/remove_liq.rs @@ -0,0 +1,140 @@ +use crate::{contexts::remove_liquidity::RemoveLiquidityContext, StorageCache, SwapTokensOrder, ERROR_BAD_PAYMENT_TOKENS, ERROR_INVALID_ARGS, ERROR_K_INVARIANT_FAILED, ERROR_LP_TOKEN_NOT_ISSUED, ERROR_NOT_ACTIVE, ERROR_NOT_WHITELISTED}; + +use super::common_result_types::RemoveLiquidityResultType; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait RemoveLiquidityModule: + crate::liquidity_pool::LiquidityPoolModule + + crate::amm::AmmModule + + crate::contexts::output_builder::OutputBuilderModule + + crate::locking_wrapper::LockingWrapperModule + + crate::events::EventsModule + + crate::safe_price::SafePriceModule + + crate::fee::FeeModule + + crate::config::ConfigModule + + token_send::TokenSendModule + + permissions_module::PermissionsModule + + pausable::PausableModule + + super::common_methods::CommonMethodsModule +{ + #[payable("*")] + #[endpoint(removeLiquidity)] + fn remove_liquidity( + &self, + first_token_amount_min: BigUint, + second_token_amount_min: BigUint, + ) -> RemoveLiquidityResultType { + require!( + first_token_amount_min > 0 && second_token_amount_min > 0, + ERROR_INVALID_ARGS + ); + + let mut storage_cache = StorageCache::new(self); + let caller = self.blockchain().get_caller(); + let payment = self.call_value().single_esdt(); + + require!( + self.is_state_active(storage_cache.contract_state), + ERROR_NOT_ACTIVE + ); + require!( + storage_cache.lp_token_id.is_valid_esdt_identifier(), + ERROR_LP_TOKEN_NOT_ISSUED + ); + require!( + payment.token_identifier == storage_cache.lp_token_id && payment.amount > 0, + ERROR_BAD_PAYMENT_TOKENS + ); + + self.update_safe_price( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let initial_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let mut remove_liq_context = RemoveLiquidityContext::new( + payment.amount, + first_token_amount_min, + second_token_amount_min, + ); + self.pool_remove_liquidity(&mut remove_liq_context, &mut storage_cache); + + let new_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + require!(new_k <= initial_k, ERROR_K_INVARIANT_FAILED); + + self.burn( + &storage_cache.lp_token_id, + &remove_liq_context.lp_token_payment_amount, + ); + + let output_payments = + self.build_remove_liq_output_payments(&storage_cache, &remove_liq_context); + self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + + self.emit_remove_liquidity_event(&storage_cache, remove_liq_context); + + self.build_remove_liq_results(output_payments) + } + + #[payable("*")] + #[endpoint(removeLiquidityAndBuyBackAndBurnToken)] + fn remove_liquidity_and_burn_token(&self, token_to_buyback_and_burn: TokenIdentifier) { + let mut storage_cache = StorageCache::new(self); + let caller = self.blockchain().get_caller(); + let payment = self.call_value().single_esdt(); + + require!(self.whitelist().contains(&caller), ERROR_NOT_WHITELISTED); + require!( + storage_cache.lp_token_id.is_valid_esdt_identifier(), + ERROR_LP_TOKEN_NOT_ISSUED + ); + require!( + payment.token_identifier == storage_cache.lp_token_id && payment.amount > 0, + ERROR_BAD_PAYMENT_TOKENS + ); + + self.update_safe_price( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let mut remove_liq_context = + RemoveLiquidityContext::new(payment.amount, BigUint::from(1u64), BigUint::from(1u64)); + self.pool_remove_liquidity(&mut remove_liq_context, &mut storage_cache); + + self.burn( + &storage_cache.lp_token_id, + &remove_liq_context.lp_token_payment_amount, + ); + + let dest_address = ManagedAddress::zero(); + let first_token_id = storage_cache.first_token_id.clone(); + self.send_fee_slice( + &mut storage_cache, + SwapTokensOrder::PoolOrder, + &first_token_id, + &remove_liq_context.first_token_amount_removed, + &dest_address, + &token_to_buyback_and_burn, + ); + + let second_token_id = storage_cache.second_token_id.clone(); + self.send_fee_slice( + &mut storage_cache, + SwapTokensOrder::ReverseOrder, + &second_token_id, + &remove_liq_context.second_token_amount_removed, + &dest_address, + &token_to_buyback_and_burn, + ); + } +} diff --git a/dex/pair/wasm-pair-full/src/lib.rs b/dex/pair/wasm-pair-full/src/lib.rs index df90222ae..b08a363d5 100644 --- a/dex/pair/wasm-pair-full/src/lib.rs +++ b/dex/pair/wasm-pair-full/src/lib.rs @@ -21,8 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - removeLiquidity => remove_liquidity - removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token swapNoFeeAndForward => swap_no_fee swapTokensFixedInput => swap_tokens_fixed_input swapTokensFixedOutput => swap_tokens_fixed_output @@ -75,6 +73,8 @@ multiversx_sc_wasm_adapter::endpoints! { getState => state addInitialLiquidity => add_initial_liquidity addLiquidity => add_liquidity + removeLiquidity => remove_liquidity + removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token getLpTokensSafePriceByDefaultOffset => get_lp_tokens_safe_price_by_default_offset getLpTokensSafePriceByRoundOffset => get_lp_tokens_safe_price_by_round_offset getLpTokensSafePriceByTimestampOffset => get_lp_tokens_safe_price_by_timestamp_offset diff --git a/dex/pair/wasm/src/lib.rs b/dex/pair/wasm/src/lib.rs index b2bfec007..b711412a3 100644 --- a/dex/pair/wasm/src/lib.rs +++ b/dex/pair/wasm/src/lib.rs @@ -21,8 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - removeLiquidity => remove_liquidity - removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token swapNoFeeAndForward => swap_no_fee swapTokensFixedInput => swap_tokens_fixed_input swapTokensFixedOutput => swap_tokens_fixed_output @@ -75,6 +73,8 @@ multiversx_sc_wasm_adapter::endpoints! { getState => state addInitialLiquidity => add_initial_liquidity addLiquidity => add_liquidity + removeLiquidity => remove_liquidity + removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token ) } diff --git a/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs b/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs index fce01d4fa..f8048d66b 100644 --- a/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs +++ b/farm-staking/farm-staking-proxy/src/external_contracts_interactions.rs @@ -10,7 +10,8 @@ use farm_staking::{ }; use farm_with_locked_rewards::ProxyTrait as _; use pair::{ - pair_actions::common_result_types::RemoveLiquidityResultType, safe_price_view::ProxyTrait as _, + pair_actions::{common_result_types::RemoveLiquidityResultType, remove_liq::ProxyTrait as _}, + safe_price_view::ProxyTrait as _, }; use crate::result_types::*; diff --git a/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs b/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs index d223bf9f1..327897bfb 100644 --- a/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs +++ b/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_external_contracts/mod.rs @@ -13,6 +13,7 @@ use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, rust_biguint, whitebox_legacy::*, DebugApi, }; use pair::pair_actions::add_liq::AddLiquidityModule; +use pair::pair_actions::remove_liq::RemoveLiquidityModule; use simple_lock::locked_token::LockedTokenModule; use farm::exit_penalty::ExitPenaltyModule; diff --git a/locked-asset/proxy_dex/src/pair_interactions.rs b/locked-asset/proxy_dex/src/pair_interactions.rs index ce4fdf7a0..7e959a4e1 100644 --- a/locked-asset/proxy_dex/src/pair_interactions.rs +++ b/locked-asset/proxy_dex/src/pair_interactions.rs @@ -1,11 +1,9 @@ multiversx_sc::imports!(); -use pair::{ - pair_actions::{ - add_liq::ProxyTrait as _, - common_result_types::{AddLiquidityResultType, RemoveLiquidityResultType}, - }, - ProxyTrait as _, +use pair::pair_actions::{ + add_liq::ProxyTrait as _, + common_result_types::{AddLiquidityResultType, RemoveLiquidityResultType}, + remove_liq::ProxyTrait as _, }; pub struct AddLiquidityResultWrapper { From a9016e57384654765ab7f3b6d66e5a984dc03a07 Mon Sep 17 00:00:00 2001 From: Dorin Marian Iancu Date: Thu, 25 Jan 2024 10:50:55 +0200 Subject: [PATCH 4/6] swap --- dex/fuzz/src/fuzz_pair.rs | 5 +- dex/pair/src/lib.rs | 259 +----------------- dex/pair/src/pair_actions/common_methods.rs | 5 + dex/pair/src/pair_actions/mod.rs | 1 + dex/pair/src/pair_actions/swap.rs | 277 ++++++++++++++++++++ dex/pair/tests/pair_rs_test.rs | 6 +- dex/pair/tests/pair_setup/mod.rs | 1 + dex/pair/wasm-pair-full/src/lib.rs | 6 +- dex/pair/wasm/src/lib.rs | 6 +- dex/router/src/multi_pair_swap.rs | 4 +- 10 files changed, 299 insertions(+), 271 deletions(-) create mode 100644 dex/pair/src/pair_actions/swap.rs diff --git a/dex/fuzz/src/fuzz_pair.rs b/dex/fuzz/src/fuzz_pair.rs index 480eed510..cd22614cb 100644 --- a/dex/fuzz/src/fuzz_pair.rs +++ b/dex/fuzz/src/fuzz_pair.rs @@ -12,9 +12,8 @@ pub mod fuzz_pair_test { use rand::prelude::*; use crate::fuzz_data::fuzz_data_tests::*; - use pair::{ - pair_actions::{add_liq::AddLiquidityModule, remove_liq::RemoveLiquidityModule}, - *, + use pair::pair_actions::{ + add_liq::AddLiquidityModule, remove_liq::RemoveLiquidityModule, swap::SwapModule, }; pub fn add_liquidity( diff --git a/dex/pair/src/lib.rs b/dex/pair/src/lib.rs index 021f61d6f..b4dd4a3cf 100644 --- a/dex/pair/src/lib.rs +++ b/dex/pair/src/lib.rs @@ -18,7 +18,6 @@ pub mod safe_price_view; use crate::errors::*; use contexts::base::*; -use contexts::swap::SwapContext; use pair_actions::common_result_types::{ AddLiquidityResultType, RemoveLiquidityResultType, SwapTokensFixedInputResultType, SwapTokensFixedOutputResultType, @@ -43,6 +42,7 @@ pub trait Pair: + pair_actions::initial_liq::InitialLiquidityModule + pair_actions::add_liq::AddLiquidityModule + pair_actions::remove_liq::RemoveLiquidityModule + + pair_actions::swap::SwapModule + pair_actions::common_methods::CommonMethodsModule { #[init] @@ -100,191 +100,6 @@ pub trait Pair: #[endpoint] fn upgrade(&self) {} - #[payable("*")] - #[endpoint(swapNoFeeAndForward)] - fn swap_no_fee(&self, token_out: TokenIdentifier, destination_address: ManagedAddress) { - let caller = self.blockchain().get_caller(); - require!(self.whitelist().contains(&caller), ERROR_NOT_WHITELISTED); - - let mut storage_cache = StorageCache::new(self); - let (token_in, _, amount_in) = self.call_value().single_esdt().into_tuple(); - let swap_tokens_order = storage_cache.get_swap_tokens_order(&token_in, &token_out); - - require!( - self.can_swap(storage_cache.contract_state), - ERROR_SWAP_NOT_ENABLED - ); - - self.update_safe_price( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let initial_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let mut swap_context = SwapContext::new( - token_in, - amount_in.clone(), - token_out, - BigUint::from(1u32), - swap_tokens_order, - ); - swap_context.final_input_amount = amount_in; - - let amount_out = self.swap_safe_no_fee( - &mut storage_cache, - swap_context.swap_tokens_order, - &swap_context.final_input_amount, - ); - require!(amount_out > 0u64, ERROR_ZERO_AMOUNT); - - swap_context.final_output_amount = amount_out; - - let new_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); - - self.burn( - &swap_context.output_token_id, - &swap_context.final_output_amount, - ); - - self.emit_swap_no_fee_and_forward_event(swap_context, destination_address); - } - - #[payable("*")] - #[endpoint(swapTokensFixedInput)] - fn swap_tokens_fixed_input( - &self, - token_out: TokenIdentifier, - amount_out_min: BigUint, - ) -> SwapTokensFixedInputResultType { - require!(amount_out_min > 0, ERROR_INVALID_ARGS); - - let mut storage_cache = StorageCache::new(self); - let (token_in, _, amount_in) = self.call_value().single_esdt().into_tuple(); - let swap_tokens_order = storage_cache.get_swap_tokens_order(&token_in, &token_out); - - require!( - self.can_swap(storage_cache.contract_state), - ERROR_SWAP_NOT_ENABLED - ); - - let reserve_out = storage_cache.get_mut_reserve_out(swap_tokens_order); - require!(*reserve_out > amount_out_min, ERROR_NOT_ENOUGH_RESERVE); - - self.update_safe_price( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let initial_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let mut swap_context = SwapContext::new( - token_in, - amount_in, - token_out, - amount_out_min, - swap_tokens_order, - ); - self.perform_swap_fixed_input(&mut swap_context, &mut storage_cache); - - let new_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); - - if swap_context.fee_amount > 0 { - self.send_fee( - &mut storage_cache, - swap_context.swap_tokens_order, - &swap_context.input_token_id, - &swap_context.fee_amount, - ); - } - - let caller = self.blockchain().get_caller(); - let output_payments = self.build_swap_output_payments(&swap_context); - self.send_multiple_tokens_if_not_zero(&caller, &output_payments); - - self.emit_swap_event(&storage_cache, swap_context); - - self.build_swap_fixed_input_results(output_payments) - } - - #[payable("*")] - #[endpoint(swapTokensFixedOutput)] - fn swap_tokens_fixed_output( - &self, - token_out: TokenIdentifier, - amount_out: BigUint, - ) -> SwapTokensFixedOutputResultType { - require!(amount_out > 0, ERROR_INVALID_ARGS); - - let mut storage_cache = StorageCache::new(self); - let (token_in, _, amount_in_max) = self.call_value().single_esdt().into_tuple(); - let swap_tokens_order = storage_cache.get_swap_tokens_order(&token_in, &token_out); - - require!( - self.can_swap(storage_cache.contract_state), - ERROR_SWAP_NOT_ENABLED - ); - - let reserve_out = storage_cache.get_mut_reserve_out(swap_tokens_order); - require!(*reserve_out > amount_out, ERROR_NOT_ENOUGH_RESERVE); - - self.update_safe_price( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let initial_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - - let mut swap_context = SwapContext::new( - token_in, - amount_in_max, - token_out, - amount_out, - swap_tokens_order, - ); - self.perform_swap_fixed_output(&mut swap_context, &mut storage_cache); - - let new_k = self.calculate_k_constant( - &storage_cache.first_token_reserve, - &storage_cache.second_token_reserve, - ); - require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); - - if swap_context.fee_amount > 0 { - self.send_fee( - &mut storage_cache, - swap_context.swap_tokens_order, - &swap_context.input_token_id, - &swap_context.fee_amount, - ); - } - - let caller = self.blockchain().get_caller(); - let output_payments = self.build_swap_output_payments(&swap_context); - self.send_multiple_tokens_if_not_zero(&caller, &output_payments); - - self.emit_swap_event(&storage_cache, swap_context); - - self.build_swap_fixed_output_results(output_payments) - } - #[endpoint(setLpTokenIdentifier)] fn set_lp_token_identifier(&self, token_identifier: TokenIdentifier) { self.require_caller_has_owner_permissions(); @@ -398,76 +213,4 @@ pub trait Pair: sc_panic!(ERROR_UNKNOWN_TOKEN); } } - - #[inline] - fn can_swap(&self, state: State) -> bool { - state == State::Active - } - - fn perform_swap_fixed_input( - &self, - context: &mut SwapContext, - storage_cache: &mut StorageCache, - ) { - context.final_input_amount = context.input_token_amount.clone(); - - let reserve_in = storage_cache.get_reserve_in(context.swap_tokens_order); - let reserve_out = storage_cache.get_reserve_out(context.swap_tokens_order); - - let amount_out_optimal = - self.get_amount_out(&context.input_token_amount, reserve_in, reserve_out); - require!( - amount_out_optimal >= context.output_token_amount, - ERROR_SLIPPAGE_EXCEEDED - ); - require!(*reserve_out > amount_out_optimal, ERROR_NOT_ENOUGH_RESERVE); - require!(amount_out_optimal != 0u64, ERROR_ZERO_AMOUNT); - - context.final_output_amount = amount_out_optimal; - - let mut amount_in_after_fee = context.input_token_amount.clone(); - if self.is_fee_enabled() { - let fee_amount = self.get_special_fee_from_input(&amount_in_after_fee); - amount_in_after_fee -= &fee_amount; - - context.fee_amount = fee_amount; - } - - *storage_cache.get_mut_reserve_in(context.swap_tokens_order) += amount_in_after_fee; - *storage_cache.get_mut_reserve_out(context.swap_tokens_order) -= - &context.final_output_amount; - } - - fn perform_swap_fixed_output( - &self, - context: &mut SwapContext, - storage_cache: &mut StorageCache, - ) { - context.final_output_amount = context.output_token_amount.clone(); - - let reserve_in = storage_cache.get_reserve_in(context.swap_tokens_order); - let reserve_out = storage_cache.get_reserve_out(context.swap_tokens_order); - - let amount_in_optimal = - self.get_amount_in(&context.output_token_amount, reserve_in, reserve_out); - require!( - amount_in_optimal <= context.input_token_amount, - ERROR_SLIPPAGE_EXCEEDED - ); - require!(amount_in_optimal != 0, ERROR_ZERO_AMOUNT); - - context.final_input_amount = amount_in_optimal.clone(); - - let mut amount_in_optimal_after_fee = amount_in_optimal; - if self.is_fee_enabled() { - let fee_amount = self.get_special_fee_from_input(&amount_in_optimal_after_fee); - amount_in_optimal_after_fee -= &fee_amount; - - context.fee_amount = fee_amount; - } - - *storage_cache.get_mut_reserve_in(context.swap_tokens_order) += amount_in_optimal_after_fee; - *storage_cache.get_mut_reserve_out(context.swap_tokens_order) -= - &context.final_output_amount; - } } diff --git a/dex/pair/src/pair_actions/common_methods.rs b/dex/pair/src/pair_actions/common_methods.rs index 5d145e9bc..8839a85d5 100644 --- a/dex/pair/src/pair_actions/common_methods.rs +++ b/dex/pair/src/pair_actions/common_methods.rs @@ -8,4 +8,9 @@ pub trait CommonMethodsModule { fn is_state_active(&self, state: State) -> bool { state == State::Active || state == State::PartialActive } + + #[inline] + fn can_swap(&self, state: State) -> bool { + state == State::Active + } } diff --git a/dex/pair/src/pair_actions/mod.rs b/dex/pair/src/pair_actions/mod.rs index 13495c791..1b4c36ed1 100644 --- a/dex/pair/src/pair_actions/mod.rs +++ b/dex/pair/src/pair_actions/mod.rs @@ -3,3 +3,4 @@ pub mod common_methods; pub mod common_result_types; pub mod initial_liq; pub mod remove_liq; +pub mod swap; diff --git a/dex/pair/src/pair_actions/swap.rs b/dex/pair/src/pair_actions/swap.rs new file mode 100644 index 000000000..6e028bad0 --- /dev/null +++ b/dex/pair/src/pair_actions/swap.rs @@ -0,0 +1,277 @@ +use crate::{ + contexts::swap::SwapContext, StorageCache, ERROR_INVALID_ARGS, ERROR_K_INVARIANT_FAILED, + ERROR_NOT_ENOUGH_RESERVE, ERROR_NOT_WHITELISTED, ERROR_SLIPPAGE_EXCEEDED, + ERROR_SWAP_NOT_ENABLED, ERROR_ZERO_AMOUNT, +}; + +use super::common_result_types::{SwapTokensFixedInputResultType, SwapTokensFixedOutputResultType}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait SwapModule: + crate::liquidity_pool::LiquidityPoolModule + + crate::amm::AmmModule + + crate::contexts::output_builder::OutputBuilderModule + + crate::locking_wrapper::LockingWrapperModule + + crate::events::EventsModule + + crate::safe_price::SafePriceModule + + crate::fee::FeeModule + + crate::config::ConfigModule + + token_send::TokenSendModule + + permissions_module::PermissionsModule + + pausable::PausableModule + + super::common_methods::CommonMethodsModule +{ + #[payable("*")] + #[endpoint(swapNoFeeAndForward)] + fn swap_no_fee(&self, token_out: TokenIdentifier, destination_address: ManagedAddress) { + let caller = self.blockchain().get_caller(); + require!(self.whitelist().contains(&caller), ERROR_NOT_WHITELISTED); + + let mut storage_cache = StorageCache::new(self); + let (token_in, _, amount_in) = self.call_value().single_esdt().into_tuple(); + let swap_tokens_order = storage_cache.get_swap_tokens_order(&token_in, &token_out); + + require!( + self.can_swap(storage_cache.contract_state), + ERROR_SWAP_NOT_ENABLED + ); + + self.update_safe_price( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let initial_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let mut swap_context = SwapContext::new( + token_in, + amount_in.clone(), + token_out, + BigUint::from(1u32), + swap_tokens_order, + ); + swap_context.final_input_amount = amount_in; + + let amount_out = self.swap_safe_no_fee( + &mut storage_cache, + swap_context.swap_tokens_order, + &swap_context.final_input_amount, + ); + require!(amount_out > 0u64, ERROR_ZERO_AMOUNT); + + swap_context.final_output_amount = amount_out; + + let new_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); + + self.burn( + &swap_context.output_token_id, + &swap_context.final_output_amount, + ); + + self.emit_swap_no_fee_and_forward_event(swap_context, destination_address); + } + + #[payable("*")] + #[endpoint(swapTokensFixedInput)] + fn swap_tokens_fixed_input( + &self, + token_out: TokenIdentifier, + amount_out_min: BigUint, + ) -> SwapTokensFixedInputResultType { + require!(amount_out_min > 0, ERROR_INVALID_ARGS); + + let mut storage_cache = StorageCache::new(self); + let (token_in, _, amount_in) = self.call_value().single_esdt().into_tuple(); + let swap_tokens_order = storage_cache.get_swap_tokens_order(&token_in, &token_out); + + require!( + self.can_swap(storage_cache.contract_state), + ERROR_SWAP_NOT_ENABLED + ); + + let reserve_out = storage_cache.get_mut_reserve_out(swap_tokens_order); + require!(*reserve_out > amount_out_min, ERROR_NOT_ENOUGH_RESERVE); + + self.update_safe_price( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let initial_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let mut swap_context = SwapContext::new( + token_in, + amount_in, + token_out, + amount_out_min, + swap_tokens_order, + ); + self.perform_swap_fixed_input(&mut swap_context, &mut storage_cache); + + let new_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); + + if swap_context.fee_amount > 0 { + self.send_fee( + &mut storage_cache, + swap_context.swap_tokens_order, + &swap_context.input_token_id, + &swap_context.fee_amount, + ); + } + + let caller = self.blockchain().get_caller(); + let output_payments = self.build_swap_output_payments(&swap_context); + self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + + self.emit_swap_event(&storage_cache, swap_context); + + self.build_swap_fixed_input_results(output_payments) + } + + #[payable("*")] + #[endpoint(swapTokensFixedOutput)] + fn swap_tokens_fixed_output( + &self, + token_out: TokenIdentifier, + amount_out: BigUint, + ) -> SwapTokensFixedOutputResultType { + require!(amount_out > 0, ERROR_INVALID_ARGS); + + let mut storage_cache = StorageCache::new(self); + let (token_in, _, amount_in_max) = self.call_value().single_esdt().into_tuple(); + let swap_tokens_order = storage_cache.get_swap_tokens_order(&token_in, &token_out); + + require!( + self.can_swap(storage_cache.contract_state), + ERROR_SWAP_NOT_ENABLED + ); + + let reserve_out = storage_cache.get_mut_reserve_out(swap_tokens_order); + require!(*reserve_out > amount_out, ERROR_NOT_ENOUGH_RESERVE); + + self.update_safe_price( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let initial_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + + let mut swap_context = SwapContext::new( + token_in, + amount_in_max, + token_out, + amount_out, + swap_tokens_order, + ); + self.perform_swap_fixed_output(&mut swap_context, &mut storage_cache); + + let new_k = self.calculate_k_constant( + &storage_cache.first_token_reserve, + &storage_cache.second_token_reserve, + ); + require!(initial_k <= new_k, ERROR_K_INVARIANT_FAILED); + + if swap_context.fee_amount > 0 { + self.send_fee( + &mut storage_cache, + swap_context.swap_tokens_order, + &swap_context.input_token_id, + &swap_context.fee_amount, + ); + } + + let caller = self.blockchain().get_caller(); + let output_payments = self.build_swap_output_payments(&swap_context); + self.send_multiple_tokens_if_not_zero(&caller, &output_payments); + + self.emit_swap_event(&storage_cache, swap_context); + + self.build_swap_fixed_output_results(output_payments) + } + + fn perform_swap_fixed_input( + &self, + context: &mut SwapContext, + storage_cache: &mut StorageCache, + ) { + context.final_input_amount = context.input_token_amount.clone(); + + let reserve_in = storage_cache.get_reserve_in(context.swap_tokens_order); + let reserve_out = storage_cache.get_reserve_out(context.swap_tokens_order); + + let amount_out_optimal = + self.get_amount_out(&context.input_token_amount, reserve_in, reserve_out); + require!( + amount_out_optimal >= context.output_token_amount, + ERROR_SLIPPAGE_EXCEEDED + ); + require!(*reserve_out > amount_out_optimal, ERROR_NOT_ENOUGH_RESERVE); + require!(amount_out_optimal != 0u64, ERROR_ZERO_AMOUNT); + + context.final_output_amount = amount_out_optimal; + + let mut amount_in_after_fee = context.input_token_amount.clone(); + if self.is_fee_enabled() { + let fee_amount = self.get_special_fee_from_input(&amount_in_after_fee); + amount_in_after_fee -= &fee_amount; + + context.fee_amount = fee_amount; + } + + *storage_cache.get_mut_reserve_in(context.swap_tokens_order) += amount_in_after_fee; + *storage_cache.get_mut_reserve_out(context.swap_tokens_order) -= + &context.final_output_amount; + } + + fn perform_swap_fixed_output( + &self, + context: &mut SwapContext, + storage_cache: &mut StorageCache, + ) { + context.final_output_amount = context.output_token_amount.clone(); + + let reserve_in = storage_cache.get_reserve_in(context.swap_tokens_order); + let reserve_out = storage_cache.get_reserve_out(context.swap_tokens_order); + + let amount_in_optimal = + self.get_amount_in(&context.output_token_amount, reserve_in, reserve_out); + require!( + amount_in_optimal <= context.input_token_amount, + ERROR_SLIPPAGE_EXCEEDED + ); + require!(amount_in_optimal != 0, ERROR_ZERO_AMOUNT); + + context.final_input_amount = amount_in_optimal.clone(); + + let mut amount_in_optimal_after_fee = amount_in_optimal; + if self.is_fee_enabled() { + let fee_amount = self.get_special_fee_from_input(&amount_in_optimal_after_fee); + amount_in_optimal_after_fee -= &fee_amount; + + context.fee_amount = fee_amount; + } + + *storage_cache.get_mut_reserve_in(context.swap_tokens_order) += amount_in_optimal_after_fee; + *storage_cache.get_mut_reserve_out(context.swap_tokens_order) -= + &context.final_output_amount; + } +} diff --git a/dex/pair/tests/pair_rs_test.rs b/dex/pair/tests/pair_rs_test.rs index eb90a88f6..5ff6fbce9 100644 --- a/dex/pair/tests/pair_rs_test.rs +++ b/dex/pair/tests/pair_rs_test.rs @@ -13,8 +13,10 @@ use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, managed_token_id_wrapped, rust_biguint, whitebox_legacy::TxTokenTransfer, DebugApi, }; -// use pair::safe_price::MAX_OBSERVATIONS; -use pair::{config::MAX_PERCENTAGE, fee::FeeModule, locking_wrapper::LockingWrapperModule, Pair}; +use pair::{ + config::MAX_PERCENTAGE, fee::FeeModule, locking_wrapper::LockingWrapperModule, + pair_actions::swap::SwapModule, +}; use pair_setup::*; use simple_lock::{ locked_token::{LockedTokenAttributes, LockedTokenModule}, diff --git a/dex/pair/tests/pair_setup/mod.rs b/dex/pair/tests/pair_setup/mod.rs index d13f17d75..5ca0fcd84 100644 --- a/dex/pair/tests/pair_setup/mod.rs +++ b/dex/pair/tests/pair_setup/mod.rs @@ -21,6 +21,7 @@ pub const USER_TOTAL_WEGLD_TOKENS: u64 = 5_000_000_000; use pair::config::ConfigModule as PairConfigModule; use pair::pair_actions::add_liq::AddLiquidityModule; +use pair::pair_actions::swap::SwapModule; use pair::safe_price_view::*; use pair::*; use pausable::{PausableModule, State}; diff --git a/dex/pair/wasm-pair-full/src/lib.rs b/dex/pair/wasm-pair-full/src/lib.rs index b08a363d5..ea7c4e8d2 100644 --- a/dex/pair/wasm-pair-full/src/lib.rs +++ b/dex/pair/wasm-pair-full/src/lib.rs @@ -21,9 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - swapNoFeeAndForward => swap_no_fee - swapTokensFixedInput => swap_tokens_fixed_input - swapTokensFixedOutput => swap_tokens_fixed_output setLpTokenIdentifier => set_lp_token_identifier getTokensForGivenPosition => get_tokens_for_given_position getReservesAndTotalSupply => get_reserves_and_total_supply @@ -75,6 +72,9 @@ multiversx_sc_wasm_adapter::endpoints! { addLiquidity => add_liquidity removeLiquidity => remove_liquidity removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token + swapNoFeeAndForward => swap_no_fee + swapTokensFixedInput => swap_tokens_fixed_input + swapTokensFixedOutput => swap_tokens_fixed_output getLpTokensSafePriceByDefaultOffset => get_lp_tokens_safe_price_by_default_offset getLpTokensSafePriceByRoundOffset => get_lp_tokens_safe_price_by_round_offset getLpTokensSafePriceByTimestampOffset => get_lp_tokens_safe_price_by_timestamp_offset diff --git a/dex/pair/wasm/src/lib.rs b/dex/pair/wasm/src/lib.rs index b711412a3..268a50e9c 100644 --- a/dex/pair/wasm/src/lib.rs +++ b/dex/pair/wasm/src/lib.rs @@ -21,9 +21,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - swapNoFeeAndForward => swap_no_fee - swapTokensFixedInput => swap_tokens_fixed_input - swapTokensFixedOutput => swap_tokens_fixed_output setLpTokenIdentifier => set_lp_token_identifier getTokensForGivenPosition => get_tokens_for_given_position getReservesAndTotalSupply => get_reserves_and_total_supply @@ -75,6 +72,9 @@ multiversx_sc_wasm_adapter::endpoints! { addLiquidity => add_liquidity removeLiquidity => remove_liquidity removeLiquidityAndBuyBackAndBurnToken => remove_liquidity_and_burn_token + swapNoFeeAndForward => swap_no_fee + swapTokensFixedInput => swap_tokens_fixed_input + swapTokensFixedOutput => swap_tokens_fixed_output ) } diff --git a/dex/router/src/multi_pair_swap.rs b/dex/router/src/multi_pair_swap.rs index e537beed9..3b0f73620 100644 --- a/dex/router/src/multi_pair_swap.rs +++ b/dex/router/src/multi_pair_swap.rs @@ -1,9 +1,9 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use super::factory; +use pair::pair_actions::swap::ProxyTrait as _; -use pair::ProxyTrait as _; +use super::factory; type SwapOperationType = MultiValue4, ManagedBuffer, TokenIdentifier, BigUint>; From 7b683db451d85c3d9a82593ace3cc3fc893c93cc Mon Sep 17 00:00:00 2001 From: Dorin Marian Iancu Date: Thu, 25 Jan 2024 10:53:28 +0200 Subject: [PATCH 5/6] views --- dex/pair/src/lib.rs | 95 +--------------------- dex/pair/src/pair_actions/mod.rs | 1 + dex/pair/src/pair_actions/views.rs | 113 ++++++++++++++++++++++++++ dex/pair/wasm-pair-full/src/lib.rs | 10 +-- dex/pair/wasm/src/lib.rs | 10 +-- dex/router/src/enable_swap_by_user.rs | 2 +- 6 files changed, 126 insertions(+), 105 deletions(-) create mode 100644 dex/pair/src/pair_actions/views.rs diff --git a/dex/pair/src/lib.rs b/dex/pair/src/lib.rs index b4dd4a3cf..9da3d5067 100644 --- a/dex/pair/src/lib.rs +++ b/dex/pair/src/lib.rs @@ -43,6 +43,7 @@ pub trait Pair: + pair_actions::add_liq::AddLiquidityModule + pair_actions::remove_liq::RemoveLiquidityModule + pair_actions::swap::SwapModule + + pair_actions::views::ViewsModule + pair_actions::common_methods::CommonMethodsModule { #[init] @@ -119,98 +120,4 @@ pub trait Pair: ); self.lp_token_identifier().set(&token_identifier); } - - #[view(getTokensForGivenPosition)] - fn get_tokens_for_given_position( - &self, - liquidity: BigUint, - ) -> MultiValue2, EsdtTokenPayment> { - self.get_both_tokens_for_given_position(liquidity) - } - - #[view(getReservesAndTotalSupply)] - fn get_reserves_and_total_supply(&self) -> MultiValue3 { - let first_token_id = self.first_token_id().get(); - let second_token_id = self.second_token_id().get(); - let first_token_reserve = self.pair_reserve(&first_token_id).get(); - let second_token_reserve = self.pair_reserve(&second_token_id).get(); - let total_supply = self.lp_token_supply().get(); - (first_token_reserve, second_token_reserve, total_supply).into() - } - - #[view(getAmountOut)] - fn get_amount_out_view(&self, token_in: TokenIdentifier, amount_in: BigUint) -> BigUint { - require!(amount_in > 0u64, ERROR_ZERO_AMOUNT); - - let first_token_id = self.first_token_id().get(); - let second_token_id = self.second_token_id().get(); - let first_token_reserve = self.pair_reserve(&first_token_id).get(); - let second_token_reserve = self.pair_reserve(&second_token_id).get(); - - if token_in == first_token_id { - require!(second_token_reserve > 0u64, ERROR_NOT_ENOUGH_RESERVE); - let amount_out = - self.get_amount_out(&amount_in, &first_token_reserve, &second_token_reserve); - require!(second_token_reserve > amount_out, ERROR_NOT_ENOUGH_RESERVE); - amount_out - } else if token_in == second_token_id { - require!(first_token_reserve > 0u64, ERROR_NOT_ENOUGH_RESERVE); - let amount_out = - self.get_amount_out(&amount_in, &second_token_reserve, &first_token_reserve); - require!(first_token_reserve > amount_out, ERROR_NOT_ENOUGH_RESERVE); - amount_out - } else { - sc_panic!(ERROR_UNKNOWN_TOKEN); - } - } - - #[view(getAmountIn)] - fn get_amount_in_view(&self, token_wanted: TokenIdentifier, amount_wanted: BigUint) -> BigUint { - require!(amount_wanted > 0u64, ERROR_ZERO_AMOUNT); - - let first_token_id = self.first_token_id().get(); - let second_token_id = self.second_token_id().get(); - let first_token_reserve = self.pair_reserve(&first_token_id).get(); - let second_token_reserve = self.pair_reserve(&second_token_id).get(); - - if token_wanted == first_token_id { - require!( - first_token_reserve > amount_wanted, - ERROR_NOT_ENOUGH_RESERVE - ); - - self.get_amount_in(&amount_wanted, &second_token_reserve, &first_token_reserve) - } else if token_wanted == second_token_id { - require!( - second_token_reserve > amount_wanted, - ERROR_NOT_ENOUGH_RESERVE - ); - - self.get_amount_in(&amount_wanted, &first_token_reserve, &second_token_reserve) - } else { - sc_panic!(ERROR_UNKNOWN_TOKEN); - } - } - - #[view(getEquivalent)] - fn get_equivalent(&self, token_in: TokenIdentifier, amount_in: BigUint) -> BigUint { - require!(amount_in > 0u64, ERROR_ZERO_AMOUNT); - let zero = BigUint::zero(); - - let first_token_id = self.first_token_id().get(); - let second_token_id = self.second_token_id().get(); - let first_token_reserve = self.pair_reserve(&first_token_id).get(); - let second_token_reserve = self.pair_reserve(&second_token_id).get(); - if first_token_reserve == 0u64 || second_token_reserve == 0u64 { - return zero; - } - - if token_in == first_token_id { - self.quote(&amount_in, &first_token_reserve, &second_token_reserve) - } else if token_in == second_token_id { - self.quote(&amount_in, &second_token_reserve, &first_token_reserve) - } else { - sc_panic!(ERROR_UNKNOWN_TOKEN); - } - } } diff --git a/dex/pair/src/pair_actions/mod.rs b/dex/pair/src/pair_actions/mod.rs index 1b4c36ed1..277650055 100644 --- a/dex/pair/src/pair_actions/mod.rs +++ b/dex/pair/src/pair_actions/mod.rs @@ -4,3 +4,4 @@ pub mod common_result_types; pub mod initial_liq; pub mod remove_liq; pub mod swap; +pub mod views; diff --git a/dex/pair/src/pair_actions/views.rs b/dex/pair/src/pair_actions/views.rs new file mode 100644 index 000000000..878b3bd5e --- /dev/null +++ b/dex/pair/src/pair_actions/views.rs @@ -0,0 +1,113 @@ +use crate::{ERROR_NOT_ENOUGH_RESERVE, ERROR_UNKNOWN_TOKEN, ERROR_ZERO_AMOUNT}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait ViewsModule: + crate::liquidity_pool::LiquidityPoolModule + + crate::amm::AmmModule + + crate::contexts::output_builder::OutputBuilderModule + + crate::locking_wrapper::LockingWrapperModule + + crate::events::EventsModule + + crate::safe_price::SafePriceModule + + crate::fee::FeeModule + + crate::config::ConfigModule + + token_send::TokenSendModule + + permissions_module::PermissionsModule + + pausable::PausableModule + + super::common_methods::CommonMethodsModule +{ + #[view(getTokensForGivenPosition)] + fn get_tokens_for_given_position( + &self, + liquidity: BigUint, + ) -> MultiValue2, EsdtTokenPayment> { + self.get_both_tokens_for_given_position(liquidity) + } + + #[view(getReservesAndTotalSupply)] + fn get_reserves_and_total_supply(&self) -> MultiValue3 { + let first_token_id = self.first_token_id().get(); + let second_token_id = self.second_token_id().get(); + let first_token_reserve = self.pair_reserve(&first_token_id).get(); + let second_token_reserve = self.pair_reserve(&second_token_id).get(); + let total_supply = self.lp_token_supply().get(); + (first_token_reserve, second_token_reserve, total_supply).into() + } + + #[view(getAmountOut)] + fn get_amount_out_view(&self, token_in: TokenIdentifier, amount_in: BigUint) -> BigUint { + require!(amount_in > 0u64, ERROR_ZERO_AMOUNT); + + let first_token_id = self.first_token_id().get(); + let second_token_id = self.second_token_id().get(); + let first_token_reserve = self.pair_reserve(&first_token_id).get(); + let second_token_reserve = self.pair_reserve(&second_token_id).get(); + + if token_in == first_token_id { + require!(second_token_reserve > 0u64, ERROR_NOT_ENOUGH_RESERVE); + let amount_out = + self.get_amount_out(&amount_in, &first_token_reserve, &second_token_reserve); + require!(second_token_reserve > amount_out, ERROR_NOT_ENOUGH_RESERVE); + amount_out + } else if token_in == second_token_id { + require!(first_token_reserve > 0u64, ERROR_NOT_ENOUGH_RESERVE); + let amount_out = + self.get_amount_out(&amount_in, &second_token_reserve, &first_token_reserve); + require!(first_token_reserve > amount_out, ERROR_NOT_ENOUGH_RESERVE); + amount_out + } else { + sc_panic!(ERROR_UNKNOWN_TOKEN); + } + } + + #[view(getAmountIn)] + fn get_amount_in_view(&self, token_wanted: TokenIdentifier, amount_wanted: BigUint) -> BigUint { + require!(amount_wanted > 0u64, ERROR_ZERO_AMOUNT); + + let first_token_id = self.first_token_id().get(); + let second_token_id = self.second_token_id().get(); + let first_token_reserve = self.pair_reserve(&first_token_id).get(); + let second_token_reserve = self.pair_reserve(&second_token_id).get(); + + if token_wanted == first_token_id { + require!( + first_token_reserve > amount_wanted, + ERROR_NOT_ENOUGH_RESERVE + ); + + self.get_amount_in(&amount_wanted, &second_token_reserve, &first_token_reserve) + } else if token_wanted == second_token_id { + require!( + second_token_reserve > amount_wanted, + ERROR_NOT_ENOUGH_RESERVE + ); + + self.get_amount_in(&amount_wanted, &first_token_reserve, &second_token_reserve) + } else { + sc_panic!(ERROR_UNKNOWN_TOKEN); + } + } + + #[view(getEquivalent)] + fn get_equivalent(&self, token_in: TokenIdentifier, amount_in: BigUint) -> BigUint { + require!(amount_in > 0u64, ERROR_ZERO_AMOUNT); + let zero = BigUint::zero(); + + let first_token_id = self.first_token_id().get(); + let second_token_id = self.second_token_id().get(); + let first_token_reserve = self.pair_reserve(&first_token_id).get(); + let second_token_reserve = self.pair_reserve(&second_token_id).get(); + if first_token_reserve == 0u64 || second_token_reserve == 0u64 { + return zero; + } + + if token_in == first_token_id { + self.quote(&amount_in, &first_token_reserve, &second_token_reserve) + } else if token_in == second_token_id { + self.quote(&amount_in, &second_token_reserve, &first_token_reserve) + } else { + sc_panic!(ERROR_UNKNOWN_TOKEN); + } + } +} diff --git a/dex/pair/wasm-pair-full/src/lib.rs b/dex/pair/wasm-pair-full/src/lib.rs index ea7c4e8d2..149c4a91b 100644 --- a/dex/pair/wasm-pair-full/src/lib.rs +++ b/dex/pair/wasm-pair-full/src/lib.rs @@ -22,11 +22,6 @@ multiversx_sc_wasm_adapter::endpoints! { init => init upgrade => upgrade setLpTokenIdentifier => set_lp_token_identifier - getTokensForGivenPosition => get_tokens_for_given_position - getReservesAndTotalSupply => get_reserves_and_total_supply - getAmountOut => get_amount_out_view - getAmountIn => get_amount_in_view - getEquivalent => get_equivalent getFeeState => is_fee_enabled whitelist => whitelist_endpoint removeWhitelist => remove_whitelist @@ -75,6 +70,11 @@ multiversx_sc_wasm_adapter::endpoints! { swapNoFeeAndForward => swap_no_fee swapTokensFixedInput => swap_tokens_fixed_input swapTokensFixedOutput => swap_tokens_fixed_output + getTokensForGivenPosition => get_tokens_for_given_position + getReservesAndTotalSupply => get_reserves_and_total_supply + getAmountOut => get_amount_out_view + getAmountIn => get_amount_in_view + getEquivalent => get_equivalent getLpTokensSafePriceByDefaultOffset => get_lp_tokens_safe_price_by_default_offset getLpTokensSafePriceByRoundOffset => get_lp_tokens_safe_price_by_round_offset getLpTokensSafePriceByTimestampOffset => get_lp_tokens_safe_price_by_timestamp_offset diff --git a/dex/pair/wasm/src/lib.rs b/dex/pair/wasm/src/lib.rs index 268a50e9c..82a357b8a 100644 --- a/dex/pair/wasm/src/lib.rs +++ b/dex/pair/wasm/src/lib.rs @@ -22,11 +22,6 @@ multiversx_sc_wasm_adapter::endpoints! { init => init upgrade => upgrade setLpTokenIdentifier => set_lp_token_identifier - getTokensForGivenPosition => get_tokens_for_given_position - getReservesAndTotalSupply => get_reserves_and_total_supply - getAmountOut => get_amount_out_view - getAmountIn => get_amount_in_view - getEquivalent => get_equivalent getFeeState => is_fee_enabled whitelist => whitelist_endpoint removeWhitelist => remove_whitelist @@ -75,6 +70,11 @@ multiversx_sc_wasm_adapter::endpoints! { swapNoFeeAndForward => swap_no_fee swapTokensFixedInput => swap_tokens_fixed_input swapTokensFixedOutput => swap_tokens_fixed_output + getTokensForGivenPosition => get_tokens_for_given_position + getReservesAndTotalSupply => get_reserves_and_total_supply + getAmountOut => get_amount_out_view + getAmountIn => get_amount_in_view + getEquivalent => get_equivalent ) } diff --git a/dex/router/src/enable_swap_by_user.rs b/dex/router/src/enable_swap_by_user.rs index eec3f4d02..f1857403e 100644 --- a/dex/router/src/enable_swap_by_user.rs +++ b/dex/router/src/enable_swap_by_user.rs @@ -1,7 +1,7 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use pair::config::ProxyTrait as _; +use pair::{config::ProxyTrait as _, pair_actions::views::ProxyTrait as _}; use pausable::{ProxyTrait as _, State}; use simple_lock::locked_token::LockedTokenAttributes; From 489f715e9e2e6fc6d6830bafb5eec3a6e2ca838c Mon Sep 17 00:00:00 2001 From: Dorin Marian Iancu Date: Thu, 25 Jan 2024 10:55:48 +0200 Subject: [PATCH 6/6] fmt --- dex/pair/src/liquidity_pool.rs | 16 ++++++++-------- dex/pair/src/pair_actions/remove_liq.rs | 6 +++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/dex/pair/src/liquidity_pool.rs b/dex/pair/src/liquidity_pool.rs index 5e292e199..4797772e3 100644 --- a/dex/pair/src/liquidity_pool.rs +++ b/dex/pair/src/liquidity_pool.rs @@ -154,14 +154,14 @@ pub trait LiquidityPoolModule: context.first_token_optimal_amount = first_token_amount_optimal; context.second_token_optimal_amount = second_token_amount_desired.clone(); } - require!( - context.first_token_optimal_amount >= context.first_token_amount_min, - ERROR_INSUFFICIENT_FIRST_TOKEN - ); - require!( - context.second_token_optimal_amount >= context.second_token_amount_min, - ERROR_INSUFFICIENT_SECOND_TOKEN - ); + require!( + context.first_token_optimal_amount >= context.first_token_amount_min, + ERROR_INSUFFICIENT_FIRST_TOKEN + ); + require!( + context.second_token_optimal_amount >= context.second_token_amount_min, + ERROR_INSUFFICIENT_SECOND_TOKEN + ); } fn get_token_for_given_position( diff --git a/dex/pair/src/pair_actions/remove_liq.rs b/dex/pair/src/pair_actions/remove_liq.rs index a1f234226..898d99ccf 100644 --- a/dex/pair/src/pair_actions/remove_liq.rs +++ b/dex/pair/src/pair_actions/remove_liq.rs @@ -1,4 +1,8 @@ -use crate::{contexts::remove_liquidity::RemoveLiquidityContext, StorageCache, SwapTokensOrder, ERROR_BAD_PAYMENT_TOKENS, ERROR_INVALID_ARGS, ERROR_K_INVARIANT_FAILED, ERROR_LP_TOKEN_NOT_ISSUED, ERROR_NOT_ACTIVE, ERROR_NOT_WHITELISTED}; +use crate::{ + contexts::remove_liquidity::RemoveLiquidityContext, StorageCache, SwapTokensOrder, + ERROR_BAD_PAYMENT_TOKENS, ERROR_INVALID_ARGS, ERROR_K_INVARIANT_FAILED, + ERROR_LP_TOKEN_NOT_ISSUED, ERROR_NOT_ACTIVE, ERROR_NOT_WHITELISTED, +}; use super::common_result_types::RemoveLiquidityResultType;