diff --git a/Cargo.lock b/Cargo.lock index 0f857da80..42951acbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -523,9 +523,11 @@ dependencies = [ "multiversx-sc-modules", "multiversx-sc-scenario", "num-bigint", + "original_owner_helper", "pair", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -584,9 +586,11 @@ dependencies = [ "multiversx-sc-modules", "multiversx-sc-scenario", "num-bigint", + "original_owner_helper", "pair", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -629,6 +633,7 @@ dependencies = [ "pair", "pausable", "permissions-hub", + "permissions_hub_module", "rewards", "sc_whitelist_module", "simple-lock", @@ -768,8 +773,10 @@ dependencies = [ "multiversx-sc-modules", "multiversx-sc-scenario", "num-bigint", + "original_owner_helper", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -1366,6 +1373,14 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "original_owner_helper" +version = "0.0.0" +dependencies = [ + "common_structs", + "multiversx-sc", +] + [[package]] name = "pair" version = "0.0.0" @@ -1462,6 +1477,14 @@ dependencies = [ "permissions-hub", ] +[[package]] +name = "permissions_hub_module" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "permissions-hub", +] + [[package]] name = "permissions_module" version = "0.0.0" diff --git a/common/modules/original_owner_helper/Cargo.toml b/common/modules/original_owner_helper/Cargo.toml new file mode 100644 index 000000000..21fa393dc --- /dev/null +++ b/common/modules/original_owner_helper/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "original_owner_helper" +version = "0.0.0" +authors = ["MultiversX "] +edition = "2021" + +[lib] +path = "src/lib.rs" + +[dependencies.multiversx-sc] +version = "=0.53.2" +features = ["esdt-token-payment-legacy-decode"] + +[dependencies.common_structs] +path = "../../common_structs" diff --git a/common/modules/original_owner_helper/src/lib.rs b/common/modules/original_owner_helper/src/lib.rs new file mode 100644 index 000000000..3f5126929 --- /dev/null +++ b/common/modules/original_owner_helper/src/lib.rs @@ -0,0 +1,62 @@ +#![no_std] + +multiversx_sc::imports!(); + +use common_structs::{FarmToken, PaymentsVec}; + +#[multiversx_sc::module] +pub trait OriginalOwnerHelperModule { + fn check_and_return_original_owner + TopDecode>( + &self, + payments: &PaymentsVec, + farm_token_mapper: &NonFungibleTokenMapper, + ) -> ManagedAddress { + let mut original_owner = ManagedAddress::zero(); + for payment in payments.iter() { + let attributes: T = farm_token_mapper.get_token_attributes(payment.token_nonce); + let payment_original_owner = attributes.get_original_owner(); + + if original_owner.is_zero() { + original_owner = payment_original_owner; + } else { + require!( + original_owner == payment_original_owner, + "All position must have the same original owner" + ); + } + } + + require!( + !original_owner.is_zero(), + "Original owner could not be identified" + ); + + original_owner + } + + fn check_additional_payments_original_owner + TopDecode>( + &self, + user: &ManagedAddress, + payments: &PaymentsVec, + farm_token_mapper: &NonFungibleTokenMapper, + ) { + if payments.len() == 1 { + return; + } + + let farm_token_id = farm_token_mapper.get_token_id(); + for payment in payments.into_iter() { + if payment.token_identifier != farm_token_id { + continue; + } + + let attributes: T = farm_token_mapper.get_token_attributes(payment.token_nonce); + let payment_original_owner = attributes.get_original_owner(); + + require!( + user == &payment_original_owner, + "Provided address is not the same as the original owner" + ); + } + } +} diff --git a/common/modules/permissions_hub_module/Cargo.toml b/common/modules/permissions_hub_module/Cargo.toml new file mode 100644 index 000000000..503fe9d60 --- /dev/null +++ b/common/modules/permissions_hub_module/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "permissions_hub_module" +version = "0.0.0" +authors = ["MultiversX "] +edition = "2021" + +[lib] +path = "src/permissions_hub_module.rs" + +[dependencies.permissions-hub] +path = "../../../dex/permissions-hub" + +[dependencies.multiversx-sc] +version = "=0.53.2" +features = ["esdt-token-payment-legacy-decode"] diff --git a/common/modules/permissions_hub_module/src/permissions_hub_module.rs b/common/modules/permissions_hub_module/src/permissions_hub_module.rs new file mode 100644 index 000000000..3b7832d06 --- /dev/null +++ b/common/modules/permissions_hub_module/src/permissions_hub_module.rs @@ -0,0 +1,32 @@ +#![no_std] + +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +#[multiversx_sc::module] +pub trait PermissionsHubModule { + fn require_user_whitelisted(&self, user: &ManagedAddress, authorized_address: &ManagedAddress) { + let permissions_hub_address = self.permissions_hub_address().get(); + let is_whitelisted: bool = self + .permissions_hub_proxy(permissions_hub_address) + .is_whitelisted(user, authorized_address) + .execute_on_dest_context(); + + require!(is_whitelisted, "Caller is not whitelisted by the user"); + } + + #[only_owner] + #[endpoint(setPermissionsHubAddress)] + fn set_permissions_hub_address(&self, address: ManagedAddress) { + self.permissions_hub_address().set(&address); + } + + #[proxy] + fn permissions_hub_proxy( + &self, + sc_address: ManagedAddress, + ) -> permissions_hub::Proxy; + + #[storage_mapper("permissionsHubAddress")] + fn permissions_hub_address(&self) -> SingleValueMapper; +} diff --git a/dex/farm-with-locked-rewards/Cargo.toml b/dex/farm-with-locked-rewards/Cargo.toml index 9e96ef3e4..1968a43a9 100644 --- a/dex/farm-with-locked-rewards/Cargo.toml +++ b/dex/farm-with-locked-rewards/Cargo.toml @@ -41,6 +41,12 @@ path = "../../common/modules/utils" [dependencies.permissions_module] path = "../../common/modules/permissions_module" +[dependencies.permissions_hub_module] +path = "../../common/modules/permissions_hub_module" + +[dependencies.original_owner_helper] +path = "../../common/modules/original_owner_helper" + [dependencies.sc_whitelist_module] path = "../../common/modules/sc_whitelist_module" diff --git a/dex/farm-with-locked-rewards/src/external_interaction.rs b/dex/farm-with-locked-rewards/src/external_interaction.rs index d2e97f513..e435812d1 100644 --- a/dex/farm-with-locked-rewards/src/external_interaction.rs +++ b/dex/farm-with-locked-rewards/src/external_interaction.rs @@ -16,6 +16,8 @@ pub trait ExternalInteractionsModule: + farm_token::FarmTokenModule + pausable::PausableModule + permissions_module::PermissionsModule + + permissions_hub_module::PermissionsHubModule + + original_owner_helper::OriginalOwnerHelperModule + sc_whitelist_module::SCWhitelistModule + events::EventsModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule @@ -45,7 +47,13 @@ pub trait ExternalInteractionsModule: let caller = self.blockchain().get_caller(); self.require_user_whitelisted(&user, &caller); - self.check_additional_payments_original_owner(&user); + let payments = self.get_non_empty_payments(); + let farm_token_mapper = self.farm_token(); + self.check_additional_payments_original_owner::>( + &user, + &payments, + &farm_token_mapper, + ); let boosted_rewards = self.claim_only_boosted_payment(&user); let new_farm_token = self.enter_farm::>(user.clone()); @@ -71,8 +79,13 @@ pub trait ExternalInteractionsModule: #[payable("*")] #[endpoint(claimRewardsOnBehalf)] fn claim_rewards_on_behalf(&self) -> ClaimRewardsResultType { - let user = self.check_and_return_original_owner(); + let payments = self.get_non_empty_payments(); + let farm_token_mapper = self.farm_token(); let caller = self.blockchain().get_caller(); + let user = self.check_and_return_original_owner::>( + &payments, + &farm_token_mapper, + ); self.require_user_whitelisted(&user, &caller); let claim_rewards_result = self.claim_rewards::>(user.clone()); @@ -94,78 +107,4 @@ pub trait ExternalInteractionsModule: (claim_rewards_result.new_farm_token, locked_rewards_payment).into() } - - fn check_and_return_original_owner(&self) -> ManagedAddress { - let payments = self.call_value().all_esdt_transfers().clone_value(); - let farm_token_mapper = self.farm_token(); - let mut original_owner = ManagedAddress::zero(); - for payment in payments.into_iter() { - let attributes: FarmTokenAttributes = - farm_token_mapper.get_token_attributes(payment.token_nonce); - - if original_owner.is_zero() { - original_owner = attributes.original_owner; - } else { - require!( - original_owner == attributes.original_owner, - "All position must have the same original owner" - ); - } - } - - require!( - !original_owner.is_zero(), - "Original owner could not be identified" - ); - - original_owner - } - - fn check_additional_payments_original_owner(&self, user: &ManagedAddress) { - let payments = self.call_value().all_esdt_transfers().clone_value(); - if payments.len() == 1 { - return; - } - - let farm_token_mapper = self.farm_token(); - let farm_token_id = farm_token_mapper.get_token_id(); - for payment in payments.into_iter() { - if payment.token_identifier != farm_token_id { - continue; - } - - let attributes: FarmTokenAttributes = - farm_token_mapper.get_token_attributes(payment.token_nonce); - - require!( - user == &attributes.original_owner, - "Provided address is not the same as the original owner" - ); - } - } - - fn require_user_whitelisted(&self, user: &ManagedAddress, authorized_address: &ManagedAddress) { - let permissions_hub_address = self.permissions_hub_address().get(); - let is_whitelisted: bool = self - .permissions_hub_proxy(permissions_hub_address) - .is_whitelisted(user, authorized_address) - .execute_on_dest_context(); - - require!(is_whitelisted, "Caller is not whitelisted by the user"); - } - - #[only_owner] - #[endpoint(setPermissionsHubAddress)] - fn set_permissions_hub_address(&self, address: ManagedAddress) { - self.permissions_hub_address().set(&address); - } - - #[proxy] - fn permissions_hub_proxy( - &self, - sc_address: ManagedAddress, - ) -> permissions_hub::Proxy; - - #[storage_mapper("permissionsHubAddress")] - fn permissions_hub_address(&self) -> SingleValueMapper; } diff --git a/dex/farm-with-locked-rewards/src/lib.rs b/dex/farm-with-locked-rewards/src/lib.rs index 499dc993e..98a048dfe 100644 --- a/dex/farm-with-locked-rewards/src/lib.rs +++ b/dex/farm-with-locked-rewards/src/lib.rs @@ -26,6 +26,8 @@ pub trait Farm: + utils::UtilsModule + pausable::PausableModule + permissions_module::PermissionsModule + + permissions_hub_module::PermissionsHubModule + + original_owner_helper::OriginalOwnerHelperModule + sc_whitelist_module::SCWhitelistModule + events::EventsModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule diff --git a/dex/farm-with-locked-rewards/tests/farm_with_locked_rewards_setup/mod.rs b/dex/farm-with-locked-rewards/tests/farm_with_locked_rewards_setup/mod.rs index df53f285f..d7cc9ab23 100644 --- a/dex/farm-with-locked-rewards/tests/farm_with_locked_rewards_setup/mod.rs +++ b/dex/farm-with-locked-rewards/tests/farm_with_locked_rewards_setup/mod.rs @@ -24,6 +24,7 @@ use locking_module::lock_with_energy_module::LockWithEnergyModule; use multiversx_sc_modules::pause::PauseModule; use pausable::{PausableModule, State}; use permissions_hub::PermissionsHub; +use permissions_hub_module::PermissionsHubModule; use rewards::RewardsModule; use sc_whitelist_module::SCWhitelistModule; use simple_lock::locked_token::LockedTokenModule; @@ -596,7 +597,9 @@ where &self.permissions_hub_wrapper, &rust_biguint!(0), |sc| { - sc.whitelist(managed_address!(address_to_whitelist)); + let mut addresses = MultiValueEncoded::new(); + addresses.push(managed_address!(address_to_whitelist)); + sc.whitelist(addresses); }, ) .assert_ok(); diff --git a/dex/farm-with-locked-rewards/wasm/Cargo.lock b/dex/farm-with-locked-rewards/wasm/Cargo.lock index 4461437a9..87136c504 100644 --- a/dex/farm-with-locked-rewards/wasm/Cargo.lock +++ b/dex/farm-with-locked-rewards/wasm/Cargo.lock @@ -129,9 +129,11 @@ dependencies = [ "mergeable", "multiversx-sc", "multiversx-sc-modules", + "original_owner_helper", "pair", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -178,8 +180,10 @@ dependencies = [ "mergeable", "multiversx-sc", "multiversx-sc-modules", + "original_owner_helper", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -393,6 +397,14 @@ dependencies = [ "autocfg", ] +[[package]] +name = "original_owner_helper" +version = "0.0.0" +dependencies = [ + "common_structs", + "multiversx-sc", +] + [[package]] name = "pair" version = "0.0.0" @@ -424,6 +436,14 @@ dependencies = [ "multiversx-sc", ] +[[package]] +name = "permissions_hub_module" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "permissions-hub", +] + [[package]] name = "permissions_module" version = "0.0.0" diff --git a/dex/farm-with-locked-rewards/wasm/src/lib.rs b/dex/farm-with-locked-rewards/wasm/src/lib.rs index a2c843da9..5635a0d71 100644 --- a/dex/farm-with-locked-rewards/wasm/src/lib.rs +++ b/dex/farm-with-locked-rewards/wasm/src/lib.rs @@ -56,12 +56,12 @@ multiversx_sc_wasm_adapter::endpoints! { removeAdmin => remove_admin_endpoint updateOwnerOrAdmin => update_owner_or_admin_endpoint getPermissions => permissions + setPermissionsHubAddress => set_permissions_hub_address addSCAddressToWhitelist => add_sc_address_to_whitelist removeSCAddressFromWhitelist => remove_sc_address_from_whitelist isSCAddressWhitelisted => is_sc_address_whitelisted enterFarmOnBehalf => enter_farm_on_behalf claimRewardsOnBehalf => claim_rewards_on_behalf - setPermissionsHubAddress => set_permissions_hub_address setBoostedYieldsFactors => set_boosted_yields_factors getBoostedYieldsFactors => get_boosted_yields_factors setTimestampOracleAddress => set_timestamp_oracle_address diff --git a/dex/farm/Cargo.toml b/dex/farm/Cargo.toml index 6429824be..f2e0e3202 100644 --- a/dex/farm/Cargo.toml +++ b/dex/farm/Cargo.toml @@ -38,6 +38,12 @@ path = "../../common/modules/pausable" [dependencies.permissions_module] path = "../../common/modules/permissions_module" +[dependencies.permissions_hub_module] +path = "../../common/modules/permissions_hub_module" + +[dependencies.original_owner_helper] +path = "../../common/modules/original_owner_helper" + [dependencies.sc_whitelist_module] path = "../../common/modules/sc_whitelist_module" diff --git a/dex/farm/src/external_interaction.rs b/dex/farm/src/external_interaction.rs index f1778cb3e..99f602c36 100644 --- a/dex/farm/src/external_interaction.rs +++ b/dex/farm/src/external_interaction.rs @@ -15,6 +15,8 @@ pub trait ExternalInteractionsModule: + farm_token::FarmTokenModule + pausable::PausableModule + permissions_module::PermissionsModule + + permissions_hub_module::PermissionsHubModule + + original_owner_helper::OriginalOwnerHelperModule + sc_whitelist_module::SCWhitelistModule + events::EventsModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule @@ -43,7 +45,13 @@ pub trait ExternalInteractionsModule: let caller = self.blockchain().get_caller(); self.require_user_whitelisted(&user, &caller); - self.check_additional_payments_original_owner(&user); + let payments = self.get_non_empty_payments(); + let farm_token_mapper = self.farm_token(); + self.check_additional_payments_original_owner::>( + &user, + &payments, + &farm_token_mapper, + ); let boosted_rewards = self.claim_only_boosted_payment(&user); @@ -62,8 +70,14 @@ pub trait ExternalInteractionsModule: #[payable("*")] #[endpoint(claimRewardsOnBehalf)] fn claim_rewards_on_behalf(&self) -> ClaimRewardsResultType { - let user = self.check_and_return_original_owner(); + let payments = self.get_non_empty_payments(); + let farm_token_mapper = self.farm_token(); + let caller = self.blockchain().get_caller(); + let user = self.check_and_return_original_owner::>( + &payments, + &farm_token_mapper, + ); self.require_user_whitelisted(&user, &caller); let claim_rewards_result = self.claim_rewards::>(user.clone()); @@ -73,78 +87,4 @@ pub trait ExternalInteractionsModule: claim_rewards_result.into() } - - fn check_and_return_original_owner(&self) -> ManagedAddress { - let payments = self.call_value().all_esdt_transfers().clone_value(); - let farm_token_mapper = self.farm_token(); - let mut original_owner = ManagedAddress::zero(); - for payment in payments.into_iter() { - let attributes: FarmTokenAttributes = - farm_token_mapper.get_token_attributes(payment.token_nonce); - - if original_owner.is_zero() { - original_owner = attributes.original_owner; - } else { - require!( - original_owner == attributes.original_owner, - "All position must have the same original owner" - ); - } - } - - require!( - !original_owner.is_zero(), - "Original owner could not be identified" - ); - - original_owner - } - - fn check_additional_payments_original_owner(&self, user: &ManagedAddress) { - let payments = self.call_value().all_esdt_transfers().clone_value(); - if payments.len() == 1 { - return; - } - - let farm_token_mapper = self.farm_token(); - let farm_token_id = farm_token_mapper.get_token_id(); - for payment in payments.into_iter() { - if payment.token_identifier != farm_token_id { - continue; - } - - let attributes: FarmTokenAttributes = - farm_token_mapper.get_token_attributes(payment.token_nonce); - - require!( - user == &attributes.original_owner, - "Provided address is not the same as the original owner" - ); - } - } - - fn require_user_whitelisted(&self, user: &ManagedAddress, authorized_address: &ManagedAddress) { - let permissions_hub_address = self.permissions_hub_address().get(); - let is_whitelisted: bool = self - .permissions_hub_proxy(permissions_hub_address) - .is_whitelisted(user, authorized_address) - .execute_on_dest_context(); - - require!(is_whitelisted, "Caller is not whitelisted by the user"); - } - - #[only_owner] - #[endpoint(setPermissionsHubAddress)] - fn set_permissions_hub_address(&self, address: ManagedAddress) { - self.permissions_hub_address().set(&address); - } - - #[proxy] - fn permissions_hub_proxy( - &self, - sc_address: ManagedAddress, - ) -> permissions_hub::Proxy; - - #[storage_mapper("permissionsHubAddress")] - fn permissions_hub_address(&self) -> SingleValueMapper; } diff --git a/dex/farm/src/lib.rs b/dex/farm/src/lib.rs index 3e3a86e92..93f06c8cc 100644 --- a/dex/farm/src/lib.rs +++ b/dex/farm/src/lib.rs @@ -26,6 +26,8 @@ pub trait Farm: + farm_token::FarmTokenModule + pausable::PausableModule + permissions_module::PermissionsModule + + permissions_hub_module::PermissionsHubModule + + original_owner_helper::OriginalOwnerHelperModule + sc_whitelist_module::SCWhitelistModule + events::EventsModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule diff --git a/dex/farm/tests/farm_setup/multi_user_farm_setup.rs b/dex/farm/tests/farm_setup/multi_user_farm_setup.rs index 344f688b0..e9ec051ca 100644 --- a/dex/farm/tests/farm_setup/multi_user_farm_setup.rs +++ b/dex/farm/tests/farm_setup/multi_user_farm_setup.rs @@ -24,6 +24,7 @@ use farm_boosted_yields::boosted_yields_factors::BoostedYieldsFactorsModule; use farm_token::FarmTokenModule; use pausable::{PausableModule, State}; use permissions_hub::PermissionsHub; +use permissions_hub_module::PermissionsHubModule; use sc_whitelist_module::SCWhitelistModule; use timestamp_oracle::epoch_to_timestamp::EpochToTimestampModule; use timestamp_oracle::TimestampOracle; @@ -688,7 +689,9 @@ where &self.permissions_hub_wrapper, &rust_biguint!(0), |sc| { - sc.whitelist(managed_address!(address_to_whitelist)); + let mut addresses = MultiValueEncoded::new(); + addresses.push(managed_address!(address_to_whitelist)); + sc.whitelist(addresses); }, ) .assert_ok(); @@ -697,7 +700,7 @@ where pub fn remove_whitelist_address_on_behalf( &mut self, user: &Address, - address_to_whitelist: &Address, + address_to_remove: &Address, ) { self.b_mock .execute_tx( @@ -705,7 +708,9 @@ where &self.permissions_hub_wrapper, &rust_biguint!(0), |sc| { - sc.remove_whitelist(managed_address!(address_to_whitelist)); + let mut addresses = MultiValueEncoded::new(); + addresses.push(managed_address!(address_to_remove)); + sc.remove_whitelist(addresses); }, ) .assert_ok(); diff --git a/dex/farm/wasm/Cargo.lock b/dex/farm/wasm/Cargo.lock index a40853d06..cceb61c15 100644 --- a/dex/farm/wasm/Cargo.lock +++ b/dex/farm/wasm/Cargo.lock @@ -129,9 +129,11 @@ dependencies = [ "mergeable", "multiversx-sc", "multiversx-sc-modules", + "original_owner_helper", "pair", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -362,6 +364,14 @@ dependencies = [ "autocfg", ] +[[package]] +name = "original_owner_helper" +version = "0.0.0" +dependencies = [ + "common_structs", + "multiversx-sc", +] + [[package]] name = "pair" version = "0.0.0" @@ -393,6 +403,14 @@ dependencies = [ "multiversx-sc", ] +[[package]] +name = "permissions_hub_module" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "permissions-hub", +] + [[package]] name = "permissions_module" version = "0.0.0" diff --git a/dex/farm/wasm/src/lib.rs b/dex/farm/wasm/src/lib.rs index b300f6917..2ae1d5525 100644 --- a/dex/farm/wasm/src/lib.rs +++ b/dex/farm/wasm/src/lib.rs @@ -53,12 +53,12 @@ multiversx_sc_wasm_adapter::endpoints! { removeAdmin => remove_admin_endpoint updateOwnerOrAdmin => update_owner_or_admin_endpoint getPermissions => permissions + setPermissionsHubAddress => set_permissions_hub_address addSCAddressToWhitelist => add_sc_address_to_whitelist removeSCAddressFromWhitelist => remove_sc_address_from_whitelist isSCAddressWhitelisted => is_sc_address_whitelisted enterFarmOnBehalf => enter_farm_on_behalf claimRewardsOnBehalf => claim_rewards_on_behalf - setPermissionsHubAddress => set_permissions_hub_address setBoostedYieldsFactors => set_boosted_yields_factors getBoostedYieldsFactors => get_boosted_yields_factors setTimestampOracleAddress => set_timestamp_oracle_address diff --git a/dex/permissions-hub/src/lib.rs b/dex/permissions-hub/src/lib.rs index 9887fe90c..7dfe4392d 100644 --- a/dex/permissions-hub/src/lib.rs +++ b/dex/permissions-hub/src/lib.rs @@ -11,18 +11,28 @@ pub trait PermissionsHub { #[upgrade] fn upgrade(&self) {} - #[endpoint(whitelist)] - fn whitelist(&self, address_to_whitelist: ManagedAddress) { + #[endpoint] + fn whitelist(&self, addresses_to_whitelist: MultiValueEncoded) { let caller = self.blockchain().get_caller(); - self.user_whitelisted_addresses(&caller) - .insert(address_to_whitelist); + for address_to_whitelist in addresses_to_whitelist.into_iter() { + require!( + self.user_whitelisted_addresses(&caller) + .insert(address_to_whitelist), + "Address is already whitelisted" + ); + } } #[endpoint(removeWhitelist)] - fn remove_whitelist(&self, address_to_remove: ManagedAddress) { + fn remove_whitelist(&self, addresses_to_remove: MultiValueEncoded) { let caller = self.blockchain().get_caller(); - self.user_whitelisted_addresses(&caller) - .swap_remove(&address_to_remove); + for address_to_remove in addresses_to_remove.into_iter() { + require!( + self.user_whitelisted_addresses(&caller) + .swap_remove(&address_to_remove), + "Address is not whitelisted" + ); + } } #[only_owner] diff --git a/energy-integration/common-modules/weekly-rewards-splitting/src/lib.rs b/energy-integration/common-modules/weekly-rewards-splitting/src/lib.rs index 52c71d4dc..5b6686739 100644 --- a/energy-integration/common-modules/weekly-rewards-splitting/src/lib.rs +++ b/energy-integration/common-modules/weekly-rewards-splitting/src/lib.rs @@ -184,60 +184,3 @@ pub trait WeeklyRewardsSplittingModule: } } } - -#[cfg(test)] -mod tests { - use multiversx_sc_scenario::{managed_biguint, DebugApi}; - - use super::*; - - #[derive(TypeAbi, TopEncode, Clone, PartialEq, Debug)] - pub struct OldClaimProgress { - pub energy: Energy, - pub week: Week, - } - - #[test] - fn decode_old_claim_progress_to_new_test() { - DebugApi::dummy(); - - let old_progress = OldClaimProgress { - energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), - week: 2, - }; - let mut old_progress_encoded = ManagedBuffer::::new(); - let _ = old_progress.top_encode(&mut old_progress_encoded); - - let new_progress_decoded = ClaimProgress::top_decode(old_progress_encoded).unwrap(); - assert_eq!( - new_progress_decoded, - ClaimProgress { - energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), - week: 2, - enter_timestamp: 0, - } - ); - } - - #[test] - fn encoded_decode_new_progress_test() { - DebugApi::dummy(); - - let new_progress = ClaimProgress { - energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), - week: 2, - enter_timestamp: 0, - }; - let mut new_progress_encoded = ManagedBuffer::::new(); - let _ = new_progress.top_encode(&mut new_progress_encoded); - let new_progress_decoded = ClaimProgress::top_decode(new_progress_encoded).unwrap(); - assert_eq!( - new_progress_decoded, - ClaimProgress { - energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), - week: 2, - enter_timestamp: 0, - } - ); - } -} diff --git a/energy-integration/common-modules/weekly-rewards-splitting/tests/encode_decode_test.rs b/energy-integration/common-modules/weekly-rewards-splitting/tests/encode_decode_test.rs new file mode 100644 index 000000000..0d917c71c --- /dev/null +++ b/energy-integration/common-modules/weekly-rewards-splitting/tests/encode_decode_test.rs @@ -0,0 +1,57 @@ +multiversx_sc::imports!(); +multiversx_sc::derive_imports!(); + +use common_structs::Week; +use energy_query::Energy; +use multiversx_sc_scenario::{managed_biguint, DebugApi}; +use weekly_rewards_splitting::ClaimProgress; + +#[derive(TypeAbi, TopEncode, Clone, PartialEq, Debug)] +pub struct OldClaimProgress { + pub energy: Energy, + pub week: Week, +} + +#[test] +fn decode_old_claim_progress_to_new_test() { + DebugApi::dummy(); + + let old_progress = OldClaimProgress { + energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), + week: 2, + }; + let mut old_progress_encoded = ManagedBuffer::::new(); + let _ = old_progress.top_encode(&mut old_progress_encoded); + + let new_progress_decoded = ClaimProgress::top_decode(old_progress_encoded).unwrap(); + assert_eq!( + new_progress_decoded, + ClaimProgress { + energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), + week: 2, + enter_timestamp: 0, + } + ); +} + +#[test] +fn encoded_decode_new_progress_test() { + DebugApi::dummy(); + + let new_progress = ClaimProgress { + energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), + week: 2, + enter_timestamp: 0, + }; + let mut new_progress_encoded = ManagedBuffer::::new(); + let _ = new_progress.top_encode(&mut new_progress_encoded); + let new_progress_decoded = ClaimProgress::top_decode(new_progress_encoded).unwrap(); + assert_eq!( + new_progress_decoded, + ClaimProgress { + energy: Energy::new(BigInt::::zero(), 10, managed_biguint!(20)), + week: 2, + enter_timestamp: 0, + } + ); +} diff --git a/farm-staking/farm-staking-proxy/Cargo.toml b/farm-staking/farm-staking-proxy/Cargo.toml index ee0e406e3..4720c7ee1 100644 --- a/farm-staking/farm-staking-proxy/Cargo.toml +++ b/farm-staking/farm-staking-proxy/Cargo.toml @@ -66,6 +66,9 @@ path = "../../energy-integration/common-modules/energy-query" [dependencies.permissions-hub] path = "../../dex/permissions-hub" +[dependencies.permissions_hub_module] +path = "../../common/modules/permissions_hub_module" + [dev-dependencies] num-bigint = "0.4.2" diff --git a/farm-staking/farm-staking-proxy/src/lib.rs b/farm-staking/farm-staking-proxy/src/lib.rs index 4840bd965..f28d5d083 100644 --- a/farm-staking/farm-staking-proxy/src/lib.rs +++ b/farm-staking/farm-staking-proxy/src/lib.rs @@ -14,6 +14,7 @@ pub trait FarmStakingProxy: + external_contracts_interactions::ExternalContractsInteractionsModule + lp_farm_token::LpFarmTokenModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule + + permissions_hub_module::PermissionsHubModule + utils::UtilsModule + token_send::TokenSendModule + energy_query::EnergyQueryModule diff --git a/farm-staking/farm-staking-proxy/src/proxy_actions/claim.rs b/farm-staking/farm-staking-proxy/src/proxy_actions/claim.rs index 057c59206..a3a40a5de 100644 --- a/farm-staking/farm-staking-proxy/src/proxy_actions/claim.rs +++ b/farm-staking/farm-staking-proxy/src/proxy_actions/claim.rs @@ -83,14 +83,12 @@ pub trait ProxyClaimModule: let lp_farm_rewards = lp_farm_claim_rewards_result.lp_farm_rewards; let staking_farm_rewards = staking_farm_claim_rewards_result.staking_farm_rewards; - let claim_result = ClaimDualYieldResult { + dual_yield_token_mapper.nft_burn(payment.token_nonce, &payment.amount); + + ClaimDualYieldResult { lp_farm_rewards, staking_farm_rewards, new_dual_yield_tokens, - }; - - dual_yield_token_mapper.nft_burn(payment.token_nonce, &payment.amount); - - claim_result + } } } diff --git a/farm-staking/farm-staking-proxy/src/proxy_actions/external_interaction.rs b/farm-staking/farm-staking-proxy/src/proxy_actions/external_interaction.rs index 12d8b257d..722bc2eb8 100644 --- a/farm-staking/farm-staking-proxy/src/proxy_actions/external_interaction.rs +++ b/farm-staking/farm-staking-proxy/src/proxy_actions/external_interaction.rs @@ -15,6 +15,7 @@ pub trait ProxyExternalInteractionsModule: + crate::proxy_actions::stake::ProxyStakeModule + crate::proxy_actions::claim::ProxyClaimModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule + + permissions_hub_module::PermissionsHubModule + utils::UtilsModule + token_send::TokenSendModule + energy_query::EnergyQueryModule @@ -115,29 +116,4 @@ pub trait ProxyExternalInteractionsModule: attributes.original_owner } - - fn require_user_whitelisted(&self, user: &ManagedAddress, authorized_address: &ManagedAddress) { - let permissions_hub_address = self.permissions_hub_address().get(); - let is_whitelisted: bool = self - .permissions_hub_proxy(permissions_hub_address) - .is_whitelisted(user, authorized_address) - .execute_on_dest_context(); - - require!(is_whitelisted, "Caller is not whitelisted by the user"); - } - - #[only_owner] - #[endpoint(setPermissionsHubAddress)] - fn set_permissions_hub_address(&self, address: ManagedAddress) { - self.permissions_hub_address().set(&address); - } - - #[proxy] - fn permissions_hub_proxy( - &self, - sc_address: ManagedAddress, - ) -> permissions_hub::Proxy; - - #[storage_mapper("permissionsHubAddress")] - fn permissions_hub_address(&self) -> SingleValueMapper; } diff --git a/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_staking_contract_interactions/mod.rs b/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_staking_contract_interactions/mod.rs index 6aef1b170..c0d4ec4d3 100644 --- a/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_staking_contract_interactions/mod.rs +++ b/farm-staking/farm-staking-proxy/tests/staking_farm_with_lp_staking_contract_interactions/mod.rs @@ -6,7 +6,7 @@ use energy_query::Energy; use farm_with_locked_rewards::Farm; use multiversx_sc::{ codec::multi_types::OptionalValue, - types::{Address, BigInt}, + types::{Address, BigInt, MultiValueEncoded}, }; use multiversx_sc_scenario::{ managed_address, managed_biguint, managed_token_id, rust_biguint, @@ -31,6 +31,7 @@ use farm_staking_proxy::proxy_actions::stake::ProxyStakeModule; use farm_staking_proxy::proxy_actions::unstake::ProxyUnstakeModule; use permissions_hub::PermissionsHub; +use permissions_hub_module::PermissionsHubModule; use sc_whitelist_module::SCWhitelistModule; use timestamp_oracle::{epoch_to_timestamp::EpochToTimestampModule, TimestampOracle}; @@ -738,7 +739,9 @@ where &self.permissions_hub_wrapper, &rust_biguint!(0), |sc| { - sc.whitelist(managed_address!(address_to_whitelist)); + let mut addresses = MultiValueEncoded::new(); + addresses.push(managed_address!(address_to_whitelist)); + sc.whitelist(addresses); }, ) .assert_ok(); diff --git a/farm-staking/farm-staking/Cargo.toml b/farm-staking/farm-staking/Cargo.toml index 1253b39f6..11ec5acb0 100644 --- a/farm-staking/farm-staking/Cargo.toml +++ b/farm-staking/farm-staking/Cargo.toml @@ -53,6 +53,12 @@ path = "../../common/modules/pausable" [dependencies.permissions_module] path = "../../common/modules/permissions_module" +[dependencies.permissions_hub_module] +path = "../../common/modules/permissions_hub_module" + +[dependencies.original_owner_helper] +path = "../../common/modules/original_owner_helper" + [dependencies.sc_whitelist_module] path = "../../common/modules/sc_whitelist_module" diff --git a/farm-staking/farm-staking/src/external_interaction.rs b/farm-staking/farm-staking/src/external_interaction.rs index 8dfa3107b..3e99d1465 100644 --- a/farm-staking/farm-staking/src/external_interaction.rs +++ b/farm-staking/farm-staking/src/external_interaction.rs @@ -19,6 +19,8 @@ pub trait ExternalInteractionsModule: + sc_whitelist_module::SCWhitelistModule + pausable::PausableModule + permissions_module::PermissionsModule + + permissions_hub_module::PermissionsHubModule + + original_owner_helper::OriginalOwnerHelperModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule + farm_base_impl::base_farm_init::BaseFarmInitModule + farm_base_impl::base_farm_validation::BaseFarmValidationModule @@ -52,7 +54,12 @@ pub trait ExternalInteractionsModule: self.require_user_whitelisted(&user, &caller); let payments = self.get_non_empty_payments(); - self.check_additional_payments_original_owner(&user, &payments); + let farm_token_mapper = self.farm_token(); + self.check_additional_payments_original_owner::>( + &user, + &payments, + &farm_token_mapper, + ); let boosted_rewards = self.claim_only_boosted_payment(&user); let boosted_rewards_payment = @@ -82,14 +89,18 @@ pub trait ExternalInteractionsModule: #[payable("*")] #[endpoint(claimRewardsOnBehalf)] fn claim_rewards_on_behalf(&self) -> ClaimRewardsResultType { - let payment = self.call_value().single_esdt(); - let user = self.check_and_return_original_owner(&payment); + let payments = self.get_non_empty_payments(); + let farm_token_mapper = self.farm_token(); let caller = self.blockchain().get_caller(); + let user = self.check_and_return_original_owner::>( + &payments, + &farm_token_mapper, + ); self.require_user_whitelisted(&user, &caller); let claim_result = self.claim_rewards_base_no_farm_token_mint::>( user.clone(), - ManagedVec::from_single_item(payment), + payments, ); let mut virtual_farm_token = claim_result.new_farm_token.clone(); @@ -120,68 +131,4 @@ pub trait ExternalInteractionsModule: (virtual_farm_token.payment, claim_result.rewards).into() } - - fn check_and_return_original_owner(&self, payment: &EsdtTokenPayment) -> ManagedAddress { - let farm_token_mapper = self.farm_token(); - let attributes: StakingFarmTokenAttributes = - farm_token_mapper.get_token_attributes(payment.token_nonce); - - require!( - !attributes.original_owner.is_zero(), - "Original owner could not be identified" - ); - - attributes.original_owner - } - - fn check_additional_payments_original_owner( - &self, - user: &ManagedAddress, - payments: &ManagedVec, - ) { - if payments.len() == 1 { - return; - } - - let farm_token_mapper = self.farm_token(); - let farm_token_id = farm_token_mapper.get_token_id(); - for payment in payments.into_iter() { - if payment.token_identifier != farm_token_id { - continue; - } - - let attributes: StakingFarmTokenAttributes = - farm_token_mapper.get_token_attributes(payment.token_nonce); - - require!( - user == &attributes.original_owner, - "Provided address is not the same as the original owner" - ); - } - } - - fn require_user_whitelisted(&self, user: &ManagedAddress, authorized_address: &ManagedAddress) { - let permissions_hub_address = self.permissions_hub_address().get(); - let is_whitelisted: bool = self - .permissions_hub_proxy(permissions_hub_address) - .is_whitelisted(user, authorized_address) - .execute_on_dest_context(); - - require!(is_whitelisted, "Caller is not whitelisted by the user"); - } - - #[only_owner] - #[endpoint(setPermissionsHubAddress)] - fn set_permissions_hub_address(&self, address: ManagedAddress) { - self.permissions_hub_address().set(&address); - } - - #[proxy] - fn permissions_hub_proxy( - &self, - sc_address: ManagedAddress, - ) -> permissions_hub::Proxy; - - #[storage_mapper("permissionsHubAddress")] - fn permissions_hub_address(&self) -> SingleValueMapper; } diff --git a/farm-staking/farm-staking/src/lib.rs b/farm-staking/farm-staking/src/lib.rs index 59d497ba3..7399c4602 100644 --- a/farm-staking/farm-staking/src/lib.rs +++ b/farm-staking/farm-staking/src/lib.rs @@ -36,6 +36,8 @@ pub trait FarmStaking: + sc_whitelist_module::SCWhitelistModule + pausable::PausableModule + permissions_module::PermissionsModule + + permissions_hub_module::PermissionsHubModule + + original_owner_helper::OriginalOwnerHelperModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule + farm_base_impl::base_farm_init::BaseFarmInitModule + farm_base_impl::base_farm_validation::BaseFarmValidationModule diff --git a/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs b/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs index f887b7e7b..7a46618cd 100644 --- a/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs +++ b/farm-staking/farm-staking/tests/farm_staking_setup/mod.rs @@ -26,6 +26,7 @@ use farm_staking::*; use farm_token::FarmTokenModule; use pausable::{PausableModule, State}; use permissions_hub::PermissionsHub; +use permissions_hub_module::PermissionsHubModule; use rewards::RewardsModule; use timestamp_oracle::epoch_to_timestamp::EpochToTimestampModule; use timestamp_oracle::TimestampOracle; @@ -713,7 +714,9 @@ where &self.permissions_hub_wrapper, &rust_biguint!(0), |sc| { - sc.whitelist(managed_address!(address_to_whitelist)); + let mut addresses = MultiValueEncoded::new(); + addresses.push(managed_address!(address_to_whitelist)); + sc.whitelist(addresses); }, ) .assert_ok(); diff --git a/farm-staking/farm-staking/wasm/Cargo.lock b/farm-staking/farm-staking/wasm/Cargo.lock index fb13bc4e4..5bdef3ac7 100644 --- a/farm-staking/farm-staking/wasm/Cargo.lock +++ b/farm-staking/farm-staking/wasm/Cargo.lock @@ -129,9 +129,11 @@ dependencies = [ "mergeable", "multiversx-sc", "multiversx-sc-modules", + "original_owner_helper", "pair", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -178,9 +180,11 @@ dependencies = [ "mergeable", "multiversx-sc", "multiversx-sc-modules", + "original_owner_helper", "pair", "pausable", "permissions-hub", + "permissions_hub_module", "permissions_module", "rewards", "sc_whitelist_module", @@ -394,6 +398,14 @@ dependencies = [ "autocfg", ] +[[package]] +name = "original_owner_helper" +version = "0.0.0" +dependencies = [ + "common_structs", + "multiversx-sc", +] + [[package]] name = "pair" version = "0.0.0" @@ -425,6 +437,14 @@ dependencies = [ "multiversx-sc", ] +[[package]] +name = "permissions_hub_module" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "permissions-hub", +] + [[package]] name = "permissions_module" version = "0.0.0" diff --git a/farm-staking/farm-staking/wasm/src/lib.rs b/farm-staking/farm-staking/wasm/src/lib.rs index 0a45a0182..a8411b08a 100644 --- a/farm-staking/farm-staking/wasm/src/lib.rs +++ b/farm-staking/farm-staking/wasm/src/lib.rs @@ -59,6 +59,7 @@ multiversx_sc_wasm_adapter::endpoints! { removeAdmin => remove_admin_endpoint updateOwnerOrAdmin => update_owner_or_admin_endpoint getPermissions => permissions + setPermissionsHubAddress => set_permissions_hub_address setBurnRoleForAddress => set_burn_role_for_address stakeFarmThroughProxy => stake_farm_through_proxy stakeFarm => stake_farm_endpoint @@ -70,7 +71,6 @@ multiversx_sc_wasm_adapter::endpoints! { unbondFarm => unbond_farm stakeFarmOnBehalf => stake_farm_on_behalf claimRewardsOnBehalf => claim_rewards_on_behalf - setPermissionsHubAddress => set_permissions_hub_address claimBoostedRewards => claim_boosted_rewards setBoostedYieldsFactors => set_boosted_yields_factors getBoostedYieldsFactors => get_boosted_yields_factors