diff --git a/dex/pair/src/fee/endpoints.rs b/dex/pair/src/fee/endpoints.rs new file mode 100644 index 000000000..ead9a99dc --- /dev/null +++ b/dex/pair/src/fee/endpoints.rs @@ -0,0 +1,138 @@ +use common_structs::{Percent, TokenPair}; + +use crate::{ + config::MAX_PERCENTAGE, ERROR_ALREADY_FEE_DEST, ERROR_ALREADY_WHITELISTED, + ERROR_BAD_TOKEN_FEE_DEST, ERROR_NOT_FEE_DEST, ERROR_NOT_WHITELISTED, + ERROR_PAIR_ALREADY_TRUSTED, ERROR_PAIR_NOT_TRUSTED, ERROR_SAME_TOKENS, +}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait EndpointsModule: + crate::config::ConfigModule + + crate::liquidity_pool::LiquidityPoolModule + + crate::amm::AmmModule + + token_send::TokenSendModule + + permissions_module::PermissionsModule + + pausable::PausableModule + + super::storage::StorageModule +{ + #[endpoint(whitelist)] + fn whitelist_endpoint(&self, address: ManagedAddress) { + self.require_caller_has_owner_permissions(); + + let is_new = self.whitelist().insert(address); + require!(is_new, ERROR_ALREADY_WHITELISTED); + } + + #[endpoint(removeWhitelist)] + fn remove_whitelist(&self, address: ManagedAddress) { + self.require_caller_has_owner_permissions(); + + let is_removed = self.whitelist().remove(&address); + require!(is_removed, ERROR_NOT_WHITELISTED); + } + + #[endpoint(addTrustedSwapPair)] + fn add_trusted_swap_pair( + &self, + pair_address: ManagedAddress, + first_token: TokenIdentifier, + second_token: TokenIdentifier, + ) { + self.require_caller_has_owner_permissions(); + require!(first_token != second_token, ERROR_SAME_TOKENS); + + let token_pair = TokenPair { + first_token, + second_token, + }; + let is_new = self + .trusted_swap_pair() + .insert(token_pair, pair_address) + .is_none(); + require!(is_new, ERROR_PAIR_ALREADY_TRUSTED); + } + + #[endpoint(removeTrustedSwapPair)] + fn remove_trusted_swap_pair( + &self, + first_token: TokenIdentifier, + second_token: TokenIdentifier, + ) { + self.require_caller_has_owner_permissions(); + + let token_pair = TokenPair { + first_token: first_token.clone(), + second_token: second_token.clone(), + }; + + let mut is_removed = self.trusted_swap_pair().remove(&token_pair).is_some(); + if !is_removed { + let token_pair_reversed = TokenPair { + first_token: second_token, + second_token: first_token, + }; + is_removed = self + .trusted_swap_pair() + .remove(&token_pair_reversed) + .is_some(); + require!(is_removed, ERROR_PAIR_NOT_TRUSTED); + } + } + + /// `fees_collector_cut_percentage` of the special fees are sent to the fees_collector_address SC + /// + /// For example, if special fees is 5%, and fees_collector_cut_percentage is 10%, + /// then of the 5%, 10% are reserved, and only the rest are split between other pair contracts. + #[endpoint(setupFeesCollector)] + fn setup_fees_collector( + &self, + fees_collector_address: ManagedAddress, + fees_collector_cut_percentage: Percent, + ) { + self.require_caller_has_owner_permissions(); + require!( + self.blockchain().is_smart_contract(&fees_collector_address), + "Invalid fees collector address" + ); + require!( + fees_collector_cut_percentage > 0 && fees_collector_cut_percentage <= MAX_PERCENTAGE, + "Invalid fees percentage" + ); + + self.fees_collector_address().set(&fees_collector_address); + self.fees_collector_cut_percentage() + .set(fees_collector_cut_percentage); + } + + #[endpoint(setFeeOn)] + fn set_fee_on(&self, fee_to_address: ManagedAddress, fee_token: TokenIdentifier) { + self.require_caller_has_owner_permissions(); + + let is_dest = self + .destination_map() + .keys() + .any(|dest_address| dest_address == fee_to_address); + require!(!is_dest, ERROR_ALREADY_FEE_DEST); + + let _ = self.destination_map().insert(fee_to_address, fee_token); + } + + #[endpoint(setFeeOn)] + fn set_fee_off(&self, fee_to_address: ManagedAddress, fee_token: TokenIdentifier) { + self.require_caller_has_owner_permissions(); + + let is_dest = self + .destination_map() + .keys() + .any(|dest_address| dest_address == fee_to_address); + require!(is_dest, ERROR_NOT_FEE_DEST); + + let dest_fee_token = self.destination_map().get(&fee_to_address).unwrap(); + require!(fee_token == dest_fee_token, ERROR_BAD_TOKEN_FEE_DEST); + + let _ = self.destination_map().remove(&fee_to_address); + } +} diff --git a/dex/pair/src/fee.rs b/dex/pair/src/fee/impls.rs similarity index 57% rename from dex/pair/src/fee.rs rename to dex/pair/src/fee/impls.rs index 45df09f82..a7a93bc57 100644 --- a/dex/pair/src/fee.rs +++ b/dex/pair/src/fee/impls.rs @@ -1,17 +1,12 @@ -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); - -use super::amm; -use super::config; -use super::errors::*; -use super::liquidity_pool; -use crate::config::MAX_PERCENTAGE; -use crate::contexts::base::StorageCache; -use crate::contexts::base::SwapTokensOrder; - use common_structs::TokenPair; use fees_collector::fees_accumulation::ProxyTrait as _; +use crate::{ + config::MAX_PERCENTAGE, StorageCache, SwapTokensOrder, ERROR_NOTHING_TO_DO_WITH_FEE_SLICE, +}; + +multiversx_sc::imports!(); + mod self_proxy { multiversx_sc::imports!(); @@ -24,104 +19,15 @@ mod self_proxy { } #[multiversx_sc::module] -pub trait FeeModule: - config::ConfigModule - + liquidity_pool::LiquidityPoolModule - + amm::AmmModule +pub trait ImplsModule: + crate::config::ConfigModule + + crate::liquidity_pool::LiquidityPoolModule + + crate::amm::AmmModule + token_send::TokenSendModule + permissions_module::PermissionsModule + pausable::PausableModule + + super::storage::StorageModule { - #[view(getFeeState)] - fn is_fee_enabled(&self) -> bool { - !self.destination_map().is_empty() || !self.fees_collector_address().is_empty() - } - - #[endpoint(whitelist)] - fn whitelist_endpoint(&self, address: ManagedAddress) { - self.require_caller_has_owner_permissions(); - let is_new = self.whitelist().insert(address); - require!(is_new, ERROR_ALREADY_WHITELISTED); - } - - #[endpoint(removeWhitelist)] - fn remove_whitelist(&self, address: ManagedAddress) { - self.require_caller_has_owner_permissions(); - let is_removed = self.whitelist().remove(&address); - require!(is_removed, ERROR_NOT_WHITELISTED); - } - - #[endpoint(addTrustedSwapPair)] - fn add_trusted_swap_pair( - &self, - pair_address: ManagedAddress, - first_token: TokenIdentifier, - second_token: TokenIdentifier, - ) { - self.require_caller_has_owner_permissions(); - require!(first_token != second_token, ERROR_SAME_TOKENS); - let token_pair = TokenPair { - first_token, - second_token, - }; - let is_new = self - .trusted_swap_pair() - .insert(token_pair, pair_address) - .is_none(); - require!(is_new, ERROR_PAIR_ALREADY_TRUSTED); - } - - #[endpoint(removeTrustedSwapPair)] - fn remove_trusted_swap_pair( - &self, - first_token: TokenIdentifier, - second_token: TokenIdentifier, - ) { - self.require_caller_has_owner_permissions(); - let token_pair = TokenPair { - first_token: first_token.clone(), - second_token: second_token.clone(), - }; - - let mut is_removed = self.trusted_swap_pair().remove(&token_pair).is_some(); - if !is_removed { - let token_pair_reversed = TokenPair { - first_token: second_token, - second_token: first_token, - }; - is_removed = self - .trusted_swap_pair() - .remove(&token_pair_reversed) - .is_some(); - require!(is_removed, ERROR_PAIR_NOT_TRUSTED); - } - } - - /// `fees_collector_cut_percentage` of the special fees are sent to the fees_collector_address SC - /// - /// For example, if special fees is 5%, and fees_collector_cut_percentage is 10%, - /// then of the 5%, 10% are reserved, and only the rest are split between other pair contracts. - #[endpoint(setupFeesCollector)] - fn setup_fees_collector( - &self, - fees_collector_address: ManagedAddress, - fees_collector_cut_percentage: u64, - ) { - self.require_caller_has_owner_permissions(); - require!( - self.blockchain().is_smart_contract(&fees_collector_address), - "Invalid fees collector address" - ); - require!( - fees_collector_cut_percentage > 0 && fees_collector_cut_percentage <= MAX_PERCENTAGE, - "Invalid fees percentage" - ); - - self.fees_collector_address().set(&fees_collector_address); - self.fees_collector_cut_percentage() - .set(fees_collector_cut_percentage); - } - fn send_fee( &self, storage_cache: &mut StorageCache, @@ -304,13 +210,6 @@ pub trait FeeModule: .execute_on_dest_context(); } - #[inline] - fn burn(&self, token: &TokenIdentifier, amount: &BigUint) { - if amount > &0 { - self.send().esdt_local_burn(token, 0, amount); - } - } - fn get_extern_swap_pair_address( &self, first_token: &TokenIdentifier, @@ -346,55 +245,11 @@ pub trait FeeModule: } } - #[endpoint(setFeeOn)] - fn set_fee_on( - &self, - enabled: bool, - fee_to_address: ManagedAddress, - fee_token: TokenIdentifier, - ) { - self.require_caller_has_owner_permissions(); - let is_dest = self - .destination_map() - .keys() - .any(|dest_address| dest_address == fee_to_address); - - if enabled { - require!(!is_dest, ERROR_ALREADY_FEE_DEST); - self.destination_map().insert(fee_to_address, fee_token); - } else { - require!(is_dest, ERROR_NOT_FEE_DEST); - let dest_fee_token = self.destination_map().get(&fee_to_address).unwrap(); - require!(fee_token == dest_fee_token, ERROR_BAD_TOKEN_FEE_DEST); - self.destination_map().remove(&fee_to_address); - } - } - - #[view(getFeeDestinations)] - fn get_fee_destinations(&self) -> MultiValueEncoded<(ManagedAddress, TokenIdentifier)> { - let mut result = MultiValueEncoded::new(); - for pair in self.destination_map().iter() { - result.push((pair.0, pair.1)) - } - result - } - - #[view(getTrustedSwapPairs)] - fn get_trusted_swap_pairs(&self) -> MultiValueEncoded<(TokenPair, ManagedAddress)> { - let mut result = MultiValueEncoded::new(); - for pair in self.trusted_swap_pair().iter() { - result.push((pair.0, pair.1)) - } - result - } - - #[view(getWhitelistedManagedAddresses)] - fn get_whitelisted_managed_addresses(&self) -> MultiValueEncoded { - let mut result = MultiValueEncoded::new(); - for pair in self.whitelist().iter() { - result.push(pair); + #[inline] + fn burn(&self, token: &TokenIdentifier, amount: &BigUint) { + if amount > &0 { + self.send().esdt_local_burn(token, 0, amount); } - result } #[proxy] @@ -402,21 +257,4 @@ pub trait FeeModule: #[proxy] fn fees_collector_proxy(&self, sc_address: ManagedAddress) -> fees_collector::Proxy; - - #[view(getFeesCollectorAddress)] - #[storage_mapper("feesCollectorAddress")] - fn fees_collector_address(&self) -> SingleValueMapper; - - #[view(getFeesCollectorCutPercentage)] - #[storage_mapper("feesCollectorCutPercentage")] - fn fees_collector_cut_percentage(&self) -> SingleValueMapper; - - #[storage_mapper("fee_destination")] - fn destination_map(&self) -> MapMapper; - - #[storage_mapper("trusted_swap_pair")] - fn trusted_swap_pair(&self) -> MapMapper, ManagedAddress>; - - #[storage_mapper("whitelist")] - fn whitelist(&self) -> SetMapper; } diff --git a/dex/pair/src/fee/mod.rs b/dex/pair/src/fee/mod.rs new file mode 100644 index 000000000..9f7633315 --- /dev/null +++ b/dex/pair/src/fee/mod.rs @@ -0,0 +1,4 @@ +pub mod endpoints; +pub mod impls; +pub mod storage; +pub mod views; diff --git a/dex/pair/src/fee/storage.rs b/dex/pair/src/fee/storage.rs new file mode 100644 index 000000000..9da4384d3 --- /dev/null +++ b/dex/pair/src/fee/storage.rs @@ -0,0 +1,23 @@ +use common_structs::{Percent, TokenPair}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait StorageModule { + #[view(getFeesCollectorAddress)] + #[storage_mapper("feesCollectorAddress")] + fn fees_collector_address(&self) -> SingleValueMapper; + + #[view(getFeesCollectorCutPercentage)] + #[storage_mapper("feesCollectorCutPercentage")] + fn fees_collector_cut_percentage(&self) -> SingleValueMapper; + + #[storage_mapper("fee_destination")] + fn destination_map(&self) -> MapMapper; + + #[storage_mapper("trusted_swap_pair")] + fn trusted_swap_pair(&self) -> MapMapper, ManagedAddress>; + + #[storage_mapper("whitelist")] + fn whitelist(&self) -> SetMapper; +} diff --git a/dex/pair/src/fee/views.rs b/dex/pair/src/fee/views.rs new file mode 100644 index 000000000..8f82397af --- /dev/null +++ b/dex/pair/src/fee/views.rs @@ -0,0 +1,41 @@ +use common_structs::TokenPair; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait ViewsModule: super::storage::StorageModule { + #[view(getFeeState)] + fn is_fee_enabled(&self) -> bool { + !self.destination_map().is_empty() || !self.fees_collector_address().is_empty() + } + + #[view(getFeeDestinations)] + fn get_fee_destinations(&self) -> MultiValueEncoded<(ManagedAddress, TokenIdentifier)> { + let mut result = MultiValueEncoded::new(); + for pair in self.destination_map().iter() { + result.push((pair.0, pair.1)) + } + + result + } + + #[view(getTrustedSwapPairs)] + fn get_trusted_swap_pairs(&self) -> MultiValueEncoded<(TokenPair, ManagedAddress)> { + let mut result = MultiValueEncoded::new(); + for pair in self.trusted_swap_pair().iter() { + result.push((pair.0, pair.1)) + } + + result + } + + #[view(getWhitelistedManagedAddresses)] + fn get_whitelisted_managed_addresses(&self) -> MultiValueEncoded { + let mut result = MultiValueEncoded::new(); + for pair in self.whitelist().iter() { + result.push(pair); + } + + result + } +} diff --git a/dex/pair/src/lib.rs b/dex/pair/src/lib.rs index e67010d67..619a0e36b 100644 --- a/dex/pair/src/lib.rs +++ b/dex/pair/src/lib.rs @@ -29,7 +29,10 @@ use permissions_module::Permissions; #[multiversx_sc::contract] pub trait Pair: amm::AmmModule - + fee::FeeModule + + fee::endpoints::EndpointsModule + + fee::impls::ImplsModule + + fee::storage::StorageModule + + fee::views::ViewsModule + liquidity_pool::LiquidityPoolModule + config::ConfigModule + token_send::TokenSendModule diff --git a/dex/pair/src/pair_actions/remove_liq.rs b/dex/pair/src/pair_actions/remove_liq.rs index 1010ac666..5b8dd5ff1 100644 --- a/dex/pair/src/pair_actions/remove_liq.rs +++ b/dex/pair/src/pair_actions/remove_liq.rs @@ -16,7 +16,10 @@ pub trait RemoveLiquidityModule: + crate::locking_wrapper::LockingWrapperModule + crate::events::EventsModule + crate::safe_price::SafePriceModule - + crate::fee::FeeModule + + crate::fee::endpoints::EndpointsModule + + crate::fee::impls::ImplsModule + + crate::fee::storage::StorageModule + + crate::fee::views::ViewsModule + crate::config::ConfigModule + token_send::TokenSendModule + permissions_module::PermissionsModule diff --git a/dex/pair/src/pair_actions/swap.rs b/dex/pair/src/pair_actions/swap.rs index 62cdc01d4..161a05f05 100644 --- a/dex/pair/src/pair_actions/swap.rs +++ b/dex/pair/src/pair_actions/swap.rs @@ -23,7 +23,10 @@ pub trait SwapModule: + crate::locking_wrapper::LockingWrapperModule + crate::events::EventsModule + crate::safe_price::SafePriceModule - + crate::fee::FeeModule + + crate::fee::endpoints::EndpointsModule + + crate::fee::impls::ImplsModule + + crate::fee::storage::StorageModule + + crate::fee::views::ViewsModule + crate::config::ConfigModule + token_send::TokenSendModule + permissions_module::PermissionsModule diff --git a/dex/pair/src/pair_actions/views.rs b/dex/pair/src/pair_actions/views.rs index 878b3bd5e..a90f3d79f 100644 --- a/dex/pair/src/pair_actions/views.rs +++ b/dex/pair/src/pair_actions/views.rs @@ -10,7 +10,10 @@ pub trait ViewsModule: + crate::locking_wrapper::LockingWrapperModule + crate::events::EventsModule + crate::safe_price::SafePriceModule - + crate::fee::FeeModule + + crate::fee::endpoints::EndpointsModule + + crate::fee::impls::ImplsModule + + crate::fee::storage::StorageModule + + crate::fee::views::ViewsModule + crate::config::ConfigModule + token_send::TokenSendModule + permissions_module::PermissionsModule diff --git a/dex/pair/tests/pair_rs_test.rs b/dex/pair/tests/pair_rs_test.rs index bd82750d8..3d5d88202 100644 --- a/dex/pair/tests/pair_rs_test.rs +++ b/dex/pair/tests/pair_rs_test.rs @@ -19,9 +19,9 @@ use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, managed_token_id_wrapped, rust_biguint, whitebox_legacy::TxTokenTransfer, DebugApi, }; +use pair::fee::endpoints::EndpointsModule; use pair::{ config::MAX_PERCENTAGE, - fee::FeeModule, locking_wrapper::LockingWrapperModule, pair_actions::swap::SwapModule, safe_price::{PriceObservation, Round, SafePriceModule}, diff --git a/dex/pair/wasm-pair-full/src/lib.rs b/dex/pair/wasm-pair-full/src/lib.rs index 5f39165a9..c5f8b252a 100644 --- a/dex/pair/wasm-pair-full/src/lib.rs +++ b/dex/pair/wasm-pair-full/src/lib.rs @@ -21,18 +21,18 @@ multiversx_sc_wasm_adapter::endpoints! { init => init upgrade => upgrade setLpTokenIdentifier => set_lp_token_identifier - getFeeState => is_fee_enabled whitelist => whitelist_endpoint removeWhitelist => remove_whitelist addTrustedSwapPair => add_trusted_swap_pair removeTrustedSwapPair => remove_trusted_swap_pair setupFeesCollector => setup_fees_collector setFeeOn => set_fee_on + getFeesCollectorAddress => fees_collector_address + getFeesCollectorCutPercentage => fees_collector_cut_percentage + getFeeState => is_fee_enabled getFeeDestinations => get_fee_destinations getTrustedSwapPairs => get_trusted_swap_pairs getWhitelistedManagedAddresses => get_whitelisted_managed_addresses - getFeesCollectorAddress => fees_collector_address - getFeesCollectorCutPercentage => fees_collector_cut_percentage setStateActiveNoSwaps => set_state_active_no_swaps setFeePercents => set_fee_percent getLpTokenIdentifier => get_lp_token_identifier diff --git a/dex/pair/wasm/src/lib.rs b/dex/pair/wasm/src/lib.rs index 7279213ee..99d1687f7 100644 --- a/dex/pair/wasm/src/lib.rs +++ b/dex/pair/wasm/src/lib.rs @@ -21,18 +21,18 @@ multiversx_sc_wasm_adapter::endpoints! { init => init upgrade => upgrade setLpTokenIdentifier => set_lp_token_identifier - getFeeState => is_fee_enabled whitelist => whitelist_endpoint removeWhitelist => remove_whitelist addTrustedSwapPair => add_trusted_swap_pair removeTrustedSwapPair => remove_trusted_swap_pair setupFeesCollector => setup_fees_collector setFeeOn => set_fee_on + getFeesCollectorAddress => fees_collector_address + getFeesCollectorCutPercentage => fees_collector_cut_percentage + getFeeState => is_fee_enabled getFeeDestinations => get_fee_destinations getTrustedSwapPairs => get_trusted_swap_pairs getWhitelistedManagedAddresses => get_whitelisted_managed_addresses - getFeesCollectorAddress => fees_collector_address - getFeesCollectorCutPercentage => fees_collector_cut_percentage setStateActiveNoSwaps => set_state_active_no_swaps setFeePercents => set_fee_percent getLpTokenIdentifier => get_lp_token_identifier diff --git a/dex/router/src/lib.rs b/dex/router/src/lib.rs index 608c3e060..d12248ee7 100644 --- a/dex/router/src/lib.rs +++ b/dex/router/src/lib.rs @@ -25,6 +25,7 @@ pub trait Router: + events::EventsModule + token_send::TokenSendModule + pair_actions::enable_swap_by_user::EnableSwapByUserModule + + pair_actions::enable_buyback_and_burn::EnableBuybackAndBurnModule + pair_actions::multi_pair_swap::MultiPairSwap + pair_actions::create::CreateModule + pair_actions::upgrade::UpgradeModule @@ -36,10 +37,15 @@ pub trait Router: + views::ViewsModule { #[init] - fn init(&self, pair_template_address_opt: OptionalValue) { + fn init( + &self, + token_to_buy: TokenIdentifier, + pair_template_address_opt: OptionalValue, + ) { + self.set_token_to_buy(token_to_buy); + self.state().set(ACTIVE); self.pair_creation_enabled().set(DISABLED); - self.temporary_owner_period() .set(DEFAULT_TEMPORARY_OWNER_PERIOD_BLOCKS); diff --git a/dex/router/src/pair_actions/enable_buyback_and_burn.rs b/dex/router/src/pair_actions/enable_buyback_and_burn.rs new file mode 100644 index 000000000..ee8558aaf --- /dev/null +++ b/dex/router/src/pair_actions/enable_buyback_and_burn.rs @@ -0,0 +1,78 @@ +use pair::fee::endpoints::ProxyTrait as _; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait EnableBuybackAndBurnModule: + crate::config::ConfigModule + + pair::read_pair_storage::ReadPairStorageModule + + crate::views::ViewsModule +{ + #[only_owner] + #[endpoint(setTokenToBuy)] + fn set_token_to_buy(&self, token_to_buy: TokenIdentifier) { + require!( + token_to_buy.is_valid_esdt_identifier(), + "Invalid token to buy" + ); + + self.token_to_buy().set(token_to_buy); + } + + fn enable_buyback_and_burn(&self, pair_address: ManagedAddress) { + let first_token_id = self.get_first_token_id_mapper(pair_address.clone()).get(); + let second_token_id = self.get_second_token_id_mapper(pair_address.clone()).get(); + let common_tokens_mapper = self.common_tokens_for_user_pairs(); + let common_token_id = if common_tokens_mapper.contains(&first_token_id) { + first_token_id + } else if common_tokens_mapper.contains(&second_token_id) { + second_token_id + } else { + return; + }; + + let token_to_buy = self.token_to_buy().get(); + let found_pair = self.get_pair(token_to_buy.clone(), common_token_id); + if found_pair.is_zero() { + return; + } + + self.whitelist_in_found_pair(found_pair.clone(), pair_address.clone()); + self.add_trusted_swap_current_pair(found_pair.clone(), pair_address.clone()); + self.set_fee_on_pair(pair_address, token_to_buy); + } + + fn whitelist_in_found_pair(&self, found_pair: ManagedAddress, current_pair: ManagedAddress) { + self.pair_contract_proxy_buyback(found_pair) + .whitelist_endpoint(current_pair) + .execute_on_dest_context() + } + + fn add_trusted_swap_current_pair( + &self, + found_pair: ManagedAddress, + current_pair: ManagedAddress, + ) { + let first_token_id_found_pair = self.get_first_token_id_mapper(found_pair.clone()).get(); + let second_token_id_found_pair = self.get_second_token_id_mapper(found_pair.clone()).get(); + self.pair_contract_proxy_buyback(current_pair) + .add_trusted_swap_pair( + found_pair, + first_token_id_found_pair, + second_token_id_found_pair, + ) + .execute_on_dest_context() + } + + fn set_fee_on_pair(&self, current_pair: ManagedAddress, fee_token_id: TokenIdentifier) { + self.pair_contract_proxy_buyback(current_pair) + .set_fee_on(ManagedAddress::zero(), fee_token_id) + .execute_on_dest_context() + } + + #[proxy] + fn pair_contract_proxy_buyback(&self, to: ManagedAddress) -> pair::Proxy; + + #[storage_mapper("tokenToBuy")] + fn token_to_buy(&self) -> SingleValueMapper; +} diff --git a/dex/router/src/pair_actions/enable_swap_by_user.rs b/dex/router/src/pair_actions/enable_swap_by_user.rs index fc4e907a7..88887e869 100644 --- a/dex/router/src/pair_actions/enable_swap_by_user.rs +++ b/dex/router/src/pair_actions/enable_swap_by_user.rs @@ -32,6 +32,8 @@ pub trait EnableSwapByUserModule: + read_pair_storage::ReadPairStorageModule + crate::events::EventsModule + crate::state::StateModule + + super::enable_buyback_and_burn::EnableBuybackAndBurnModule + + crate::views::ViewsModule { #[only_owner] #[endpoint(configEnableByUserParameters)] @@ -81,7 +83,8 @@ pub trait EnableSwapByUserModule: fn remove_common_tokens_for_user_pairs(&self, tokens: MultiValueEncoded) { let mut whitelist = self.common_tokens_for_user_pairs(); for token in tokens { - let _ = whitelist.swap_remove(&token); + let removed = whitelist.swap_remove(&token); + require!(removed, "Token not present in whitelist"); } } @@ -138,6 +141,7 @@ pub trait EnableSwapByUserModule: self.set_fee_percents(pair_address.clone()); self.pair_resume(pair_address.clone()); + self.enable_buyback_and_burn(pair_address.clone()); self.send().direct_esdt( &caller, diff --git a/dex/router/src/pair_actions/fees.rs b/dex/router/src/pair_actions/fees.rs index d301b80c9..fe248d73c 100644 --- a/dex/router/src/pair_actions/fees.rs +++ b/dex/router/src/pair_actions/fees.rs @@ -1,4 +1,4 @@ -use pair::fee::ProxyTrait as _; +use pair::fee::endpoints::ProxyTrait as _; multiversx_sc::imports!(); @@ -20,10 +20,9 @@ pub trait FeesModule: self.require_active(); self.check_is_pair_sc(&pair_address); - let _: IgnoreValue = self - .pair_contract_proxy_fees(pair_address) - .set_fee_on(true, fee_to_address, fee_token) - .execute_on_dest_context(); + self.pair_contract_proxy_fees(pair_address) + .set_fee_on(fee_to_address, fee_token) + .execute_on_dest_context() } #[only_owner] @@ -37,10 +36,9 @@ pub trait FeesModule: self.require_active(); self.check_is_pair_sc(&pair_address); - let _: IgnoreValue = self - .pair_contract_proxy_fees(pair_address) - .set_fee_on(false, fee_to_address, fee_token) - .execute_on_dest_context(); + self.pair_contract_proxy_fees(pair_address) + .set_fee_off(fee_to_address, fee_token) + .execute_on_dest_context() } #[proxy] diff --git a/dex/router/src/pair_actions/mod.rs b/dex/router/src/pair_actions/mod.rs index 2ef1ff893..82dd4e573 100644 --- a/dex/router/src/pair_actions/mod.rs +++ b/dex/router/src/pair_actions/mod.rs @@ -1,4 +1,5 @@ pub mod create; +pub mod enable_buyback_and_burn; pub mod enable_swap_by_user; pub mod fees; pub mod multi_pair_swap; diff --git a/dex/router/src/temp_owner.rs b/dex/router/src/temp_owner.rs index f8d9ca2b5..b283b7c66 100644 --- a/dex/router/src/temp_owner.rs +++ b/dex/router/src/temp_owner.rs @@ -12,11 +12,8 @@ pub trait TempOwnerModule { #[only_owner] #[endpoint(clearPairTemporaryOwnerStorage)] - fn clear_pair_temporary_owner_storage(&self) -> usize { - let size = self.pair_temporary_owner().len(); + fn clear_pair_temporary_owner_storage(&self) { self.pair_temporary_owner().clear(); - - size } fn get_pair_temporary_owner(&self, pair_address: &ManagedAddress) -> Option { @@ -24,7 +21,8 @@ pub trait TempOwnerModule { match result { Some((temporary_owner, creation_block)) => { let expire_block = creation_block + self.temporary_owner_period().get(); - if expire_block <= self.blockchain().get_block_nonce() { + let block_nonce = self.blockchain().get_block_nonce(); + if expire_block <= block_nonce { self.pair_temporary_owner().remove(pair_address); None diff --git a/dex/router/tests/router_setup/mod.rs b/dex/router/tests/router_setup/mod.rs index 02b372f71..09b8267a3 100644 --- a/dex/router/tests/router_setup/mod.rs +++ b/dex/router/tests/router_setup/mod.rs @@ -137,7 +137,7 @@ where blockchain_wrapper .execute_tx(&owner_addr, &router_wrapper, &rust_zero, |sc| { - sc.init(OptionalValue::None); + sc.init(managed_token_id!(MEX_TOKEN_ID), OptionalValue::None); sc.pair_map().insert( PairTokens { diff --git a/dex/router/tests/router_test.rs b/dex/router/tests/router_test.rs index 189dd817c..9bb11bf62 100644 --- a/dex/router/tests/router_test.rs +++ b/dex/router/tests/router_test.rs @@ -94,9 +94,10 @@ fn test_router_upgrade_pair() { b_mock .execute_tx(&owner, &router_wrapper, &rust_zero, |sc| { - sc.init(OptionalValue::Some(managed_address!( - pair_template_wrapper.address_ref() - ))); + sc.init( + managed_token_id!(MEX_TOKEN_ID), + OptionalValue::Some(managed_address!(pair_template_wrapper.address_ref())), + ); sc.set_pair_creation_enabled(); }) .assert_ok(); @@ -244,7 +245,7 @@ fn user_enable_pair_swaps_through_router_test() { // setup router b_mock .execute_tx(&owner, &router_wrapper, &rust_zero, |sc| { - sc.init(OptionalValue::None); + sc.init(managed_token_id!(MEX_TOKEN_ID), OptionalValue::None); sc.pair_map().insert( PairTokens { @@ -429,7 +430,7 @@ fn user_enable_pair_swaps_fail_test() { // setup router b_mock .execute_tx(&owner, &router_wrapper, &rust_zero, |sc| { - sc.init(OptionalValue::None); + sc.init(managed_token_id!(MEX_TOKEN_ID), OptionalValue::None); sc.pair_map().insert( PairTokens { diff --git a/dex/router/wasm/src/lib.rs b/dex/router/wasm/src/lib.rs index 89cab68cd..2592ff2c4 100644 --- a/dex/router/wasm/src/lib.rs +++ b/dex/router/wasm/src/lib.rs @@ -6,9 +6,9 @@ // Init: 1 // Upgrade: 1 -// Endpoints: 30 +// Endpoints: 31 // Async Callback: 1 -// Total number of exported functions: 33 +// Total number of exported functions: 34 #![no_std] @@ -32,6 +32,7 @@ multiversx_sc_wasm_adapter::endpoints! { removeCommonTokensForUserPairs => remove_common_tokens_for_user_pairs setSwapEnabledByUser => set_swap_enabled_by_user getEnableSwapByUserConfig => try_get_config + setTokenToBuy => set_token_to_buy multiPairSwap => multi_pair_swap createPair => create_pair_endpoint upgradePair => upgrade_pair_endpoint