From c8f3f213f78f54656a3eda2ed22b9c1f96e2ad4e Mon Sep 17 00:00:00 2001 From: Dorin Marian Iancu Date: Mon, 13 May 2024 12:07:10 +0300 Subject: [PATCH] farm energy fix --- common/common_structs/src/farm_types.rs | 7 +++ .../contexts/src/claim_rewards_context.rs | 30 +++++++--- .../farm/contexts/src/enter_farm_context.rs | 28 +++++++-- common/modules/farm/events/src/events.rs | 4 +- .../farm_base_impl/src/base_traits_impl.rs | 34 ++++------- .../farm/farm_base_impl/src/claim_rewards.rs | 12 +++- .../farm_base_impl/src/compound_rewards.rs | 10 +++- .../farm/farm_base_impl/src/enter_farm.rs | 7 ++- .../farm/farm_base_impl/src/exit_farm.rs | 2 +- common/modules/utils/src/lib.rs | 24 +++++--- dex/farm-with-locked-rewards/src/lib.rs | 2 - dex/farm/src/base_functions.rs | 45 +++++++++++++- dex/farm/src/lib.rs | 2 - .../farm-boosted-yields/src/lib.rs | 2 +- .../farm-staking/src/base_impl_wrapper.rs | 58 ------------------- .../src/claim_stake_farm_rewards.rs | 5 ++ .../src/compound_stake_farm_rewards.rs | 5 ++ .../farm-staking/src/delete_energy.rs | 43 ++++++++++++++ farm-staking/farm-staking/src/lib.rs | 15 ++++- farm-staking/farm-staking/src/stake_farm.rs | 5 ++ .../farm-staking/src/token_attributes.rs | 4 ++ farm-staking/farm-staking/src/unstake_farm.rs | 6 +- 22 files changed, 230 insertions(+), 120 deletions(-) create mode 100644 farm-staking/farm-staking/src/delete_energy.rs diff --git a/common/common_structs/src/farm_types.rs b/common/common_structs/src/farm_types.rs index d7d85e20b..676b26e36 100644 --- a/common/common_structs/src/farm_types.rs +++ b/common/common_structs/src/farm_types.rs @@ -80,6 +80,8 @@ pub trait FarmToken { fn get_compounded_rewards(&self) -> BigUint; fn get_initial_farming_tokens(&self) -> BigUint; + + fn get_original_owner(&self) -> ManagedAddress; } impl FarmToken for FarmTokenAttributes { @@ -97,4 +99,9 @@ impl FarmToken for FarmTokenAttributes { fn get_initial_farming_tokens(&self) -> BigUint { &self.current_farm_amount - &self.compounded_reward } + + #[inline] + fn get_original_owner(&self) -> ManagedAddress { + self.original_owner.clone() + } } diff --git a/common/modules/farm/contexts/src/claim_rewards_context.rs b/common/modules/farm/contexts/src/claim_rewards_context.rs index 653c6b2e6..78b8f4e67 100644 --- a/common/modules/farm/contexts/src/claim_rewards_context.rs +++ b/common/modules/farm/contexts/src/claim_rewards_context.rs @@ -2,26 +2,28 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); use common_errors::{ERROR_BAD_PAYMENTS, ERROR_EMPTY_PAYMENTS}; -use common_structs::PaymentAttributesPair; +use common_structs::{PaymentAttributesPair, PaymentsVec}; use multiversx_sc::api::BlockchainApi; use multiversx_sc::contract_base::BlockchainWrapper; pub struct ClaimRewardsContext where M: ManagedTypeApi, - T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode, + T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, { pub first_farm_token: PaymentAttributesPair, - pub additional_payments: ManagedVec>, + pub additional_payments: PaymentsVec, + pub additional_attributes: ManagedVec, + pub all_attributes: ManagedVec, } impl ClaimRewardsContext where M: ManagedTypeApi + BlockchainApi, - T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode, + T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, { pub fn new( - mut payments: ManagedVec>, + mut payments: PaymentsVec, farm_token_id: &TokenIdentifier, api_wrapper: BlockchainWrapper, ) -> Self { @@ -29,22 +31,32 @@ where M::error_api_impl().signal_error(ERROR_EMPTY_PAYMENTS); } + let own_sc_address = api_wrapper.get_sc_address(); + let mut all_attributes = ManagedVec::new(); for p in &payments { if &p.token_identifier != farm_token_id { M::error_api_impl().signal_error(ERROR_BAD_PAYMENTS); } + + let token_data = + api_wrapper.get_esdt_token_data(&own_sc_address, farm_token_id, p.token_nonce); + let token_attributes: T = token_data.decode_attributes(); + all_attributes.push(token_attributes); } let first_payment = payments.get(0); payments.remove(0); - let own_sc_address = api_wrapper.get_sc_address(); - let token_data = api_wrapper.get_esdt_token_data( + // dumb framework errors otherwise + let first_token_data = api_wrapper.get_esdt_token_data( &own_sc_address, farm_token_id, first_payment.token_nonce, ); - let first_token_attributes: T = token_data.decode_attributes(); + let first_token_attributes: T = first_token_data.decode_attributes(); + + let mut additional_attributes = all_attributes.clone(); + additional_attributes.remove(0); ClaimRewardsContext { first_farm_token: PaymentAttributesPair { @@ -52,6 +64,8 @@ where attributes: first_token_attributes, }, additional_payments: payments, + additional_attributes, + all_attributes, } } } diff --git a/common/modules/farm/contexts/src/enter_farm_context.rs b/common/modules/farm/contexts/src/enter_farm_context.rs index 9da789d9a..27a060015 100644 --- a/common/modules/farm/contexts/src/enter_farm_context.rs +++ b/common/modules/farm/contexts/src/enter_farm_context.rs @@ -2,17 +2,28 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); use common_errors::{ERROR_BAD_PAYMENTS, ERROR_EMPTY_PAYMENTS}; +use common_structs::PaymentsVec; +use multiversx_sc::{api::BlockchainApi, contract_base::BlockchainWrapper}; -pub struct EnterFarmContext { +pub struct EnterFarmContext< + M: ManagedTypeApi, + T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, +> { pub farming_token_payment: EsdtTokenPayment, - pub additional_farm_tokens: ManagedVec>, + pub additional_farm_tokens: PaymentsVec, + pub additional_attributes: ManagedVec, } -impl EnterFarmContext { +impl< + M: ManagedTypeApi + BlockchainApi, + T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, + > EnterFarmContext +{ pub fn new( - mut payments: ManagedVec>, + mut payments: PaymentsVec, farming_token_id: &TokenIdentifier, farm_token_id: &TokenIdentifier, + api_wrapper: BlockchainWrapper, ) -> Self { if payments.is_empty() { M::error_api_impl().signal_error(ERROR_EMPTY_PAYMENTS); @@ -24,15 +35,24 @@ impl EnterFarmContext { } payments.remove(0); + + let own_sc_address = api_wrapper.get_sc_address(); + let mut additional_attributes = ManagedVec::new(); for p in &payments { if &p.token_identifier != farm_token_id { M::error_api_impl().signal_error(ERROR_BAD_PAYMENTS); } + + let token_data = + api_wrapper.get_esdt_token_data(&own_sc_address, farm_token_id, p.token_nonce); + let token_attributes: T = token_data.decode_attributes(); + additional_attributes.push(token_attributes); } EnterFarmContext { farming_token_payment, additional_farm_tokens: payments, + additional_attributes, } } } diff --git a/common/modules/farm/events/src/events.rs b/common/modules/farm/events/src/events.rs index c32988130..6b55fed0c 100644 --- a/common/modules/farm/events/src/events.rs +++ b/common/modules/farm/events/src/events.rs @@ -142,7 +142,7 @@ pub trait EventsModule { fn emit_claim_rewards_event< 'a, C: FarmContracTraitBounds, - AttributesType: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode, + AttributesType: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, >( &self, original_caller: &ManagedAddress, @@ -189,7 +189,7 @@ pub trait EventsModule { fn emit_compound_rewards_event< 'a, C: FarmContracTraitBounds, - AttributesType: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode, + AttributesType: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, >( self, original_caller: &ManagedAddress, diff --git a/common/modules/farm/farm_base_impl/src/base_traits_impl.rs b/common/modules/farm/farm_base_impl/src/base_traits_impl.rs index f2ccc293c..7fdb6cdc3 100644 --- a/common/modules/farm/farm_base_impl/src/base_traits_impl.rs +++ b/common/modules/farm/farm_base_impl/src/base_traits_impl.rs @@ -1,12 +1,11 @@ multiversx_sc::imports!(); -use common_structs::{FarmToken, FarmTokenAttributes, Nonce}; +use common_structs::{FarmToken, FarmTokenAttributes, Nonce, PaymentsVec}; use config::ConfigModule; use contexts::storage_cache::StorageCache; use core::marker::PhantomData; use fixed_supply_token::FixedSupplyToken; use mergeable::Mergeable; -use multiversx_sc_modules::transfer_role_proxy::PaymentsVec; use rewards::RewardsModule; pub trait AllBaseFarmImplTraits = @@ -30,8 +29,8 @@ pub trait FarmContract { + FixedSupplyToken<::Api> + FarmToken<::Api> + From::Api>> - + Into::Api>> = - FarmTokenAttributes<::Api>; + + Into::Api>> + + ManagedVecItem = FarmTokenAttributes<::Api>; #[inline] fn mint_rewards( @@ -192,27 +191,21 @@ pub trait FarmContract { fn check_and_update_user_farm_position( sc: &Self::FarmSc, user: &ManagedAddress<::Api>, - farm_positions: &PaymentsVec<::Api>, + farm_tokens: &PaymentsVec<::Api>, + farm_attributes: &ManagedVec<::Api, Self::AttributesType>, ) { - let farm_token_mapper = sc.farm_token(); - for farm_position in farm_positions { - farm_token_mapper.require_same_token(&farm_position.token_identifier); - - if sc.is_old_farm_position(farm_position.token_nonce) { + for (attr, farm_token) in farm_attributes.into_iter().zip(farm_tokens.iter()) { + if sc.is_old_farm_position(farm_token.token_nonce) { continue; } - let token_attributes: FarmTokenAttributes<::Api> = - farm_token_mapper.get_token_attributes(farm_position.token_nonce); - - if &token_attributes.original_owner != user { - Self::decrease_user_farm_position(sc, &farm_position); - Self::increase_user_farm_position(sc, user, &farm_position.amount); + if &attr.get_original_owner() != user { + Self::decrease_user_farm_position(sc, &farm_token, &attr); + Self::increase_user_farm_position(sc, user, &farm_token.amount); } } } - #[inline] fn increase_user_farm_position( sc: &Self::FarmSc, user: &ManagedAddress<::Api>, @@ -227,16 +220,13 @@ pub trait FarmContract { fn decrease_user_farm_position( sc: &Self::FarmSc, farm_position: &EsdtTokenPayment<::Api>, + attributes: &Self::AttributesType, ) { if sc.is_old_farm_position(farm_position.token_nonce) { return; } - let farm_token_mapper = sc.farm_token(); - let token_attributes: FarmTokenAttributes<::Api> = - farm_token_mapper.get_token_attributes(farm_position.token_nonce); - - sc.user_total_farm_position(&token_attributes.original_owner) + sc.user_total_farm_position(&attributes.get_original_owner()) .update(|user_total_farm_position| { if user_total_farm_position.total_farm_position > farm_position.amount { user_total_farm_position.total_farm_position -= &farm_position.amount; diff --git a/common/modules/farm/farm_base_impl/src/claim_rewards.rs b/common/modules/farm/farm_base_impl/src/claim_rewards.rs index d9dfe293e..30b943089 100644 --- a/common/modules/farm/farm_base_impl/src/claim_rewards.rs +++ b/common/modules/farm/farm_base_impl/src/claim_rewards.rs @@ -11,7 +11,7 @@ use fixed_supply_token::FixedSupplyToken; pub struct InternalClaimRewardsResult<'a, C, T> where C: FarmContracTraitBounds, - T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode, + T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, { pub context: ClaimRewardsContext, pub storage_cache: StorageCache<'a, C>, @@ -81,7 +81,12 @@ pub trait BaseClaimRewardsModule: ); storage_cache.reward_reserve -= &reward; - FC::check_and_update_user_farm_position(self, &caller, &payments); + FC::check_and_update_user_farm_position( + self, + &caller, + &payments, + &claim_rewards_context.all_attributes, + ); let farm_token_mapper = self.farm_token(); let base_attributes = FC::create_claim_rewards_initial_attributes( @@ -90,10 +95,11 @@ pub trait BaseClaimRewardsModule: token_attributes, storage_cache.reward_per_share.clone(), ); + let new_token_attributes = self.merge_attributes_from_payments( base_attributes, + &claim_rewards_context.additional_attributes, &claim_rewards_context.additional_payments, - &farm_token_mapper, ); let new_farm_token = PaymentAttributesPair { payment: EsdtTokenPayment::new( diff --git a/common/modules/farm/farm_base_impl/src/compound_rewards.rs b/common/modules/farm/farm_base_impl/src/compound_rewards.rs index 06e52585c..530f732c0 100644 --- a/common/modules/farm/farm_base_impl/src/compound_rewards.rs +++ b/common/modules/farm/farm_base_impl/src/compound_rewards.rs @@ -12,7 +12,7 @@ use fixed_supply_token::FixedSupplyToken; pub struct InternalCompoundRewardsResult<'a, C, T> where C: FarmContracTraitBounds, - T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode, + T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, { pub context: CompoundRewardsContext, pub storage_cache: StorageCache<'a, C>, @@ -70,7 +70,12 @@ pub trait BaseCompoundRewardsModule: storage_cache.reward_reserve -= &reward; storage_cache.farm_token_supply += &reward; - FC::check_and_update_user_farm_position(self, &caller, &payments); + FC::check_and_update_user_farm_position( + self, + &caller, + &payments, + &compound_rewards_context.all_attributes, + ); let farm_token_mapper = self.farm_token(); let base_attributes = FC::create_compound_rewards_initial_attributes( @@ -82,6 +87,7 @@ pub trait BaseCompoundRewardsModule: ); let new_farm_token = self.merge_and_create_token( base_attributes, + &compound_rewards_context.additional_attributes, &compound_rewards_context.additional_payments, &farm_token_mapper, ); diff --git a/common/modules/farm/farm_base_impl/src/enter_farm.rs b/common/modules/farm/farm_base_impl/src/enter_farm.rs index 02e20d42a..850606829 100644 --- a/common/modules/farm/farm_base_impl/src/enter_farm.rs +++ b/common/modules/farm/farm_base_impl/src/enter_farm.rs @@ -10,9 +10,9 @@ use contexts::{ pub struct InternalEnterFarmResult<'a, C, T> where C: FarmContracTraitBounds, - T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode, + T: Clone + TopEncode + TopDecode + NestedEncode + NestedDecode + ManagedVecItem, { - pub context: EnterFarmContext, + pub context: EnterFarmContext, pub storage_cache: StorageCache<'a, C>, pub new_farm_token: PaymentAttributesPair, pub created_with_merge: bool, @@ -42,6 +42,7 @@ pub trait BaseEnterFarmModule: payments, &storage_cache.farming_token_id, &storage_cache.farm_token_id, + self.blockchain(), ); // The order is important - first check and update, then increase position @@ -49,6 +50,7 @@ pub trait BaseEnterFarmModule: self, &caller, &enter_farm_context.additional_farm_tokens, + &enter_farm_context.additional_attributes, ); FC::increase_user_farm_position( self, @@ -69,6 +71,7 @@ pub trait BaseEnterFarmModule: ); let new_farm_token = self.merge_and_create_token( base_attributes, + &enter_farm_context.additional_attributes, &enter_farm_context.additional_farm_tokens, &farm_token_mapper, ); diff --git a/common/modules/farm/farm_base_impl/src/exit_farm.rs b/common/modules/farm/farm_base_impl/src/exit_farm.rs index 315abe421..30d420787 100644 --- a/common/modules/farm/farm_base_impl/src/exit_farm.rs +++ b/common/modules/farm/farm_base_impl/src/exit_farm.rs @@ -62,7 +62,7 @@ pub trait BaseExitFarmModule: ); storage_cache.reward_reserve -= &reward; - FC::decrease_user_farm_position(self, &payment); + FC::decrease_user_farm_position(self, &payment, &exit_farm_context.farm_token.attributes); let farming_token_amount = token_attributes.get_total_supply(); let farming_token_payment = EsdtTokenPayment::new( diff --git a/common/modules/utils/src/lib.rs b/common/modules/utils/src/lib.rs index 990b88329..9077b7203 100644 --- a/common/modules/utils/src/lib.rs +++ b/common/modules/utils/src/lib.rs @@ -57,7 +57,7 @@ pub trait UtilsModule { } fn merge_from_payments_and_burn< - T: FixedSupplyToken + Mergeable + TopDecode, + T: FixedSupplyToken + Mergeable + TopDecode + ManagedVecItem, >( &self, mut payments: PaymentsVec, @@ -68,23 +68,29 @@ pub trait UtilsModule { self.get_attributes_as_part_of_fixed_supply(&first_payment, mapper); mapper.nft_burn(first_payment.token_nonce, &first_payment.amount); + let mut other_attributes = ManagedVec::new(); + for payment in &payments { + let attr = mapper.get_token_attributes(payment.token_nonce); + other_attributes.push(attr); + } + let output_attributes = - self.merge_attributes_from_payments(base_attributes, &payments, mapper); + self.merge_attributes_from_payments(base_attributes, &other_attributes, &payments); self.send().esdt_local_burn_multi(&payments); output_attributes } fn merge_attributes_from_payments< - T: FixedSupplyToken + Mergeable + TopDecode, + T: FixedSupplyToken + Mergeable + TopDecode + ManagedVecItem, >( &self, mut base_attributes: T, + other_attributes: &ManagedVec, payments: &PaymentsVec, - mapper: &NonFungibleTokenMapper, ) -> T { - for payment in payments { - let attributes: T = self.get_attributes_as_part_of_fixed_supply(&payment, mapper); + for (attr, payment) in other_attributes.into_iter().zip(payments.iter()) { + let attributes = attr.into_part(&payment.amount); base_attributes.merge_with(attributes); } @@ -98,15 +104,17 @@ pub trait UtilsModule { + TopEncode + TopDecode + NestedEncode - + NestedDecode, + + NestedDecode + + ManagedVecItem, >( &self, base_attributes: T, + other_attributes: &ManagedVec, payments: &PaymentsVec, mapper: &NonFungibleTokenMapper, ) -> PaymentAttributesPair { let output_attributes = - self.merge_attributes_from_payments(base_attributes, payments, mapper); + self.merge_attributes_from_payments(base_attributes, other_attributes, payments); let new_token_amount = output_attributes.get_total_supply(); let new_token_payment = mapper.nft_create(new_token_amount, &output_attributes); diff --git a/dex/farm-with-locked-rewards/src/lib.rs b/dex/farm-with-locked-rewards/src/lib.rs index d704a80df..34600f80b 100644 --- a/dex/farm-with-locked-rewards/src/lib.rs +++ b/dex/farm-with-locked-rewards/src/lib.rs @@ -182,8 +182,6 @@ pub trait Farm: orig_caller.clone(), ); - self.clear_user_energy_if_needed(&orig_caller); - (exit_farm_result.farming_tokens, locked_rewards_payment).into() } diff --git a/dex/farm/src/base_functions.rs b/dex/farm/src/base_functions.rs index 48a59ac56..510887aa6 100644 --- a/dex/farm/src/base_functions.rs +++ b/dex/farm/src/base_functions.rs @@ -7,6 +7,7 @@ multiversx_sc::derive_imports!(); use core::marker::PhantomData; use common_errors::ERROR_ZERO_AMOUNT; +use common_structs::FarmToken; use common_structs::FarmTokenAttributes; use contexts::storage_cache::StorageCache; @@ -81,6 +82,10 @@ pub trait BaseFunctionsModule: &base_enter_farm_result.storage_cache.farm_token_supply, ); + self.delete_user_energy_if_needed::( + &base_enter_farm_result.context.additional_attributes, + ); + self.emit_enter_farm_event( &caller, base_enter_farm_result.context.farming_token_payment, @@ -106,6 +111,8 @@ pub trait BaseFunctionsModule: &base_claim_rewards_result.storage_cache.farm_token_supply, ); + self.delete_user_energy_if_needed::(&base_claim_rewards_result.context.all_attributes); + self.emit_claim_rewards_event( &caller, base_claim_rewards_result.context, @@ -135,6 +142,10 @@ pub trait BaseFunctionsModule: &base_compound_rewards_result.storage_cache.farm_token_supply, ); + self.delete_user_energy_if_needed::( + &base_compound_rewards_result.context.all_attributes, + ); + self.emit_compound_rewards_event( &caller, base_compound_rewards_result.context, @@ -161,6 +172,10 @@ pub trait BaseFunctionsModule: &base_exit_farm_result.storage_cache.farm_token_supply, ); + self.delete_user_energy_if_needed::(&ManagedVec::from_single_item( + base_exit_farm_result.context.farm_token.attributes.clone(), + )); + FC::apply_penalty( self, &mut farming_token_payment.amount, @@ -188,9 +203,18 @@ pub trait BaseFunctionsModule: ) -> FC::AttributesType { let payments = self.get_non_empty_payments(); let token_mapper = self.farm_token(); - token_mapper.require_all_same_token(&payments); - FC::check_and_update_user_farm_position(self, orig_caller, &payments); + let mut all_attributes = ManagedVec::new(); + for payment in &payments { + token_mapper.require_same_token(&payment.token_identifier); + + let attr = token_mapper.get_token_attributes(payment.token_nonce); + all_attributes.push(attr); + } + + self.delete_user_energy_if_needed::(&all_attributes); + + FC::check_and_update_user_farm_position(self, orig_caller, &payments, &all_attributes); self.merge_from_payments_and_burn(payments, &token_mapper) } @@ -253,6 +277,23 @@ pub trait BaseFunctionsModule: self.per_block_reward_amount().set(&per_block_amount); } + fn delete_user_energy_if_needed>( + &self, + all_attributes: &ManagedVec, + ) { + let mut processed_users = ManagedMap::new(); + for attr in all_attributes { + let original_owner = attr.get_original_owner(); + if processed_users.contains(original_owner.as_managed_buffer()) { + continue; + } + + self.clear_user_energy_if_needed(&original_owner); + + processed_users.put(original_owner.as_managed_buffer(), &ManagedBuffer::new()); + } + } + fn require_queried(&self) { let caller = self.blockchain().get_caller(); let sc_address = self.blockchain().get_sc_address(); diff --git a/dex/farm/src/lib.rs b/dex/farm/src/lib.rs index 1a35c1631..5bf5dba64 100644 --- a/dex/farm/src/lib.rs +++ b/dex/farm/src/lib.rs @@ -177,8 +177,6 @@ pub trait Farm: self.send_payment_non_zero(&caller, &exit_farm_result.farming_tokens); self.send_payment_non_zero(&caller, &exit_farm_result.rewards); - self.clear_user_energy_if_needed(&orig_caller); - (exit_farm_result.farming_tokens, exit_farm_result.rewards).into() } diff --git a/energy-integration/farm-boosted-yields/src/lib.rs b/energy-integration/farm-boosted-yields/src/lib.rs index 09bacc676..78ec0fb4e 100644 --- a/energy-integration/farm-boosted-yields/src/lib.rs +++ b/energy-integration/farm-boosted-yields/src/lib.rs @@ -123,8 +123,8 @@ pub trait FarmBoostedYieldsModule: fn clear_user_energy_if_needed(&self, original_caller: &ManagedAddress) { let opt_config = self.try_get_boosted_yields_config(); - let user_total_farm_position = self.get_user_total_farm_position(original_caller); if let Some(config) = opt_config { + let user_total_farm_position = self.get_user_total_farm_position(original_caller); let boosted_yields_factors = config.get_latest_factors(); self.clear_user_energy( original_caller, diff --git a/farm-staking/farm-staking/src/base_impl_wrapper.rs b/farm-staking/farm-staking/src/base_impl_wrapper.rs index 2b671677f..da30a1c84 100644 --- a/farm-staking/farm-staking/src/base_impl_wrapper.rs +++ b/farm-staking/farm-staking/src/base_impl_wrapper.rs @@ -5,7 +5,6 @@ use core::marker::PhantomData; use common_structs::FarmToken; use contexts::storage_cache::StorageCache; use farm_base_impl::base_traits_impl::FarmContract; -use multiversx_sc_modules::transfer_role_proxy::PaymentsVec; use crate::token_attributes::StakingFarmTokenAttributes; @@ -184,61 +183,4 @@ where original_owner: caller, } } - - fn check_and_update_user_farm_position( - sc: &Self::FarmSc, - user: &ManagedAddress<::Api>, - farm_positions: &PaymentsVec<::Api>, - ) { - let farm_token_mapper = sc.farm_token(); - for farm_position in farm_positions { - if sc.is_old_farm_position(farm_position.token_nonce) { - continue; - } - - farm_token_mapper.require_same_token(&farm_position.token_identifier); - - let token_attributes: StakingFarmTokenAttributes<::Api> = - farm_token_mapper.get_token_attributes(farm_position.token_nonce); - - if &token_attributes.original_owner != user { - Self::decrease_user_farm_position(sc, &farm_position); - Self::increase_user_farm_position(sc, user, &farm_position.amount); - } - } - } - - #[inline] - fn increase_user_farm_position( - sc: &Self::FarmSc, - user: &ManagedAddress<::Api>, - increase_farm_position_amount: &BigUint<::Api>, - ) { - let mut user_total_farm_position = sc.get_user_total_farm_position(user); - user_total_farm_position.total_farm_position += increase_farm_position_amount; - sc.user_total_farm_position(user) - .set(user_total_farm_position); - } - - fn decrease_user_farm_position( - sc: &Self::FarmSc, - farm_position: &EsdtTokenPayment<::Api>, - ) { - if sc.is_old_farm_position(farm_position.token_nonce) { - return; - } - - let farm_token_mapper = sc.farm_token(); - let token_attributes: StakingFarmTokenAttributes<::Api> = - farm_token_mapper.get_token_attributes(farm_position.token_nonce); - - sc.user_total_farm_position(&token_attributes.original_owner) - .update(|user_total_farm_position| { - if user_total_farm_position.total_farm_position > farm_position.amount { - user_total_farm_position.total_farm_position -= &farm_position.amount; - } else { - user_total_farm_position.total_farm_position = BigUint::zero(); - } - }); - } } diff --git a/farm-staking/farm-staking/src/claim_stake_farm_rewards.rs b/farm-staking/farm-staking/src/claim_stake_farm_rewards.rs index 93d4802ea..4fb4de268 100644 --- a/farm-staking/farm-staking/src/claim_stake_farm_rewards.rs +++ b/farm-staking/farm-staking/src/claim_stake_farm_rewards.rs @@ -30,6 +30,7 @@ pub trait ClaimStakeFarmRewardsModule: + weekly_rewards_splitting::locked_token_buckets::WeeklyRewardsLockedTokenBucketsModule + weekly_rewards_splitting::update_claim_progress_energy::UpdateClaimProgressEnergyModule + energy_query::EnergyQueryModule + + crate::delete_energy::DeleteEnergyModule { #[payable("*")] #[endpoint(claimRewards)] @@ -86,6 +87,10 @@ pub trait ClaimStakeFarmRewardsModule: self.set_farm_supply_for_current_week(&claim_result.storage_cache.farm_token_supply); } + self.delete_user_energy_if_needed::>( + &claim_result.context.all_attributes, + ); + self.update_energy_and_progress(&original_caller); let new_farm_token_nonce = self.send().esdt_nft_create_compact( diff --git a/farm-staking/farm-staking/src/compound_stake_farm_rewards.rs b/farm-staking/farm-staking/src/compound_stake_farm_rewards.rs index a7d83d574..bb0c2906d 100644 --- a/farm-staking/farm-staking/src/compound_stake_farm_rewards.rs +++ b/farm-staking/farm-staking/src/compound_stake_farm_rewards.rs @@ -28,6 +28,7 @@ pub trait CompoundStakeFarmRewardsModule: + weekly_rewards_splitting::locked_token_buckets::WeeklyRewardsLockedTokenBucketsModule + weekly_rewards_splitting::update_claim_progress_energy::UpdateClaimProgressEnergyModule + energy_query::EnergyQueryModule + + crate::delete_energy::DeleteEnergyModule { #[payable("*")] #[endpoint(compoundRewards)] @@ -43,6 +44,10 @@ pub trait CompoundStakeFarmRewardsModule: self.set_farm_supply_for_current_week(&compound_result.storage_cache.farm_token_supply); + self.delete_user_energy_if_needed::>( + &compound_result.context.all_attributes, + ); + self.emit_compound_rewards_event( &caller, compound_result.context, diff --git a/farm-staking/farm-staking/src/delete_energy.rs b/farm-staking/farm-staking/src/delete_energy.rs new file mode 100644 index 000000000..ddb8c9d52 --- /dev/null +++ b/farm-staking/farm-staking/src/delete_energy.rs @@ -0,0 +1,43 @@ +use common_structs::FarmToken; +use farm_base_impl::base_traits_impl::FarmContract; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait DeleteEnergyModule: + rewards::RewardsModule + + config::ConfigModule + + token_send::TokenSendModule + + farm_token::FarmTokenModule + + pausable::PausableModule + + permissions_module::PermissionsModule + + events::EventsModule + + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule + + utils::UtilsModule + + farm_boosted_yields::FarmBoostedYieldsModule + + farm_boosted_yields::boosted_yields_factors::BoostedYieldsFactorsModule + + week_timekeeping::WeekTimekeepingModule + + weekly_rewards_splitting::WeeklyRewardsSplittingModule + + weekly_rewards_splitting::events::WeeklyRewardsSplittingEventsModule + + weekly_rewards_splitting::global_info::WeeklyRewardsGlobalInfo + + weekly_rewards_splitting::locked_token_buckets::WeeklyRewardsLockedTokenBucketsModule + + weekly_rewards_splitting::update_claim_progress_energy::UpdateClaimProgressEnergyModule + + energy_query::EnergyQueryModule +{ + fn delete_user_energy_if_needed>( + &self, + all_attributes: &ManagedVec, + ) { + let mut processed_users = ManagedMap::new(); + for attr in all_attributes { + let original_owner = attr.get_original_owner(); + if processed_users.contains(original_owner.as_managed_buffer()) { + continue; + } + + self.clear_user_energy_if_needed(&original_owner); + + processed_users.put(original_owner.as_managed_buffer(), &ManagedBuffer::new()); + } + } +} diff --git a/farm-staking/farm-staking/src/lib.rs b/farm-staking/farm-staking/src/lib.rs index 5fd2b28d6..f7aa53f70 100644 --- a/farm-staking/farm-staking/src/lib.rs +++ b/farm-staking/farm-staking/src/lib.rs @@ -19,6 +19,7 @@ pub mod claim_only_boosted_staking_rewards; pub mod claim_stake_farm_rewards; pub mod compound_stake_farm_rewards; pub mod custom_rewards; +pub mod delete_energy; pub mod farm_token_roles; pub mod stake_farm; pub mod token_attributes; @@ -60,6 +61,7 @@ pub trait FarmStaking: + weekly_rewards_splitting::locked_token_buckets::WeeklyRewardsLockedTokenBucketsModule + weekly_rewards_splitting::update_claim_progress_energy::UpdateClaimProgressEnergyModule + energy_query::EnergyQueryModule + + delete_energy::DeleteEnergyModule { #[init] fn init( @@ -141,9 +143,18 @@ pub trait FarmStaking: ) -> FC::AttributesType { let payments = self.get_non_empty_payments(); let token_mapper = self.farm_token(); - token_mapper.require_all_same_token(&payments); - FC::check_and_update_user_farm_position(self, orig_caller, &payments); + let mut all_attributes = ManagedVec::new(); + for payment in &payments { + token_mapper.require_same_token(&payment.token_identifier); + + let attr = token_mapper.get_token_attributes(payment.token_nonce); + all_attributes.push(attr); + } + + self.delete_user_energy_if_needed::(&all_attributes); + + FC::check_and_update_user_farm_position(self, orig_caller, &payments, &all_attributes); self.merge_from_payments_and_burn(payments, &token_mapper) } diff --git a/farm-staking/farm-staking/src/stake_farm.rs b/farm-staking/farm-staking/src/stake_farm.rs index 7ab3dea1c..5dfa8ca53 100644 --- a/farm-staking/farm-staking/src/stake_farm.rs +++ b/farm-staking/farm-staking/src/stake_farm.rs @@ -31,6 +31,7 @@ pub trait StakeFarmModule: + weekly_rewards_splitting::locked_token_buckets::WeeklyRewardsLockedTokenBucketsModule + weekly_rewards_splitting::update_claim_progress_energy::UpdateClaimProgressEnergyModule + energy_query::EnergyQueryModule + + crate::delete_energy::DeleteEnergyModule { #[payable("*")] #[endpoint(stakeFarmThroughProxy)] @@ -86,6 +87,10 @@ pub trait StakeFarmModule: self.set_farm_supply_for_current_week(&enter_result.storage_cache.farm_token_supply); + self.delete_user_energy_if_needed::>( + &enter_result.context.additional_attributes, + ); + self.update_energy_and_progress(&original_caller); self.emit_enter_farm_event( diff --git a/farm-staking/farm-staking/src/token_attributes.rs b/farm-staking/farm-staking/src/token_attributes.rs index 59f8c6326..0fcabeba3 100644 --- a/farm-staking/farm-staking/src/token_attributes.rs +++ b/farm-staking/farm-staking/src/token_attributes.rs @@ -82,6 +82,10 @@ impl FarmToken for StakingFarmTokenAttributes { fn get_initial_farming_tokens(&self) -> BigUint { &self.current_farm_amount - &self.compounded_reward } + + fn get_original_owner(&self) -> ManagedAddress { + self.original_owner.clone() + } } impl FixedSupplyToken for StakingFarmTokenAttributes { diff --git a/farm-staking/farm-staking/src/unstake_farm.rs b/farm-staking/farm-staking/src/unstake_farm.rs index e40642b4f..6b87d9782 100644 --- a/farm-staking/farm-staking/src/unstake_farm.rs +++ b/farm-staking/farm-staking/src/unstake_farm.rs @@ -30,6 +30,7 @@ pub trait UnstakeFarmModule: + weekly_rewards_splitting::locked_token_buckets::WeeklyRewardsLockedTokenBucketsModule + weekly_rewards_splitting::update_claim_progress_energy::UpdateClaimProgressEnergyModule + energy_query::EnergyQueryModule + + crate::delete_energy::DeleteEnergyModule { #[payable("*")] #[endpoint(unstakeFarm)] @@ -89,9 +90,12 @@ pub trait UnstakeFarmModule: self.send_payment_non_zero(&caller, &exit_result.reward_payment); - self.clear_user_energy_if_needed(&original_caller); self.set_farm_supply_for_current_week(&exit_result.storage_cache.farm_token_supply); + self.delete_user_energy_if_needed::>( + &ManagedVec::from_single_item(exit_result.context.farm_token.attributes.clone()), + ); + self.emit_exit_farm_event( &caller, exit_result.context,