|
| 1 | +multiversx_sc::imports!(); |
| 2 | + |
| 3 | +use common_structs::FarmTokenAttributes; |
| 4 | +use farm::{ |
| 5 | + base_functions::{self, ClaimRewardsResultType}, |
| 6 | + EnterFarmResultType, |
| 7 | +}; |
| 8 | + |
| 9 | +use crate::NoMintWrapper; |
| 10 | + |
| 11 | +#[multiversx_sc::module] |
| 12 | +pub trait ExternalInteractionsModule: |
| 13 | + rewards::RewardsModule |
| 14 | + + config::ConfigModule |
| 15 | + + token_send::TokenSendModule |
| 16 | + + farm_token::FarmTokenModule |
| 17 | + + pausable::PausableModule |
| 18 | + + permissions_module::PermissionsModule |
| 19 | + + sc_whitelist_module::SCWhitelistModule |
| 20 | + + events::EventsModule |
| 21 | + + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule |
| 22 | + + base_functions::BaseFunctionsModule |
| 23 | + + locking_module::lock_with_energy_module::LockWithEnergyModule |
| 24 | + + farm_base_impl::base_farm_init::BaseFarmInitModule |
| 25 | + + farm_base_impl::base_farm_validation::BaseFarmValidationModule |
| 26 | + + farm_base_impl::enter_farm::BaseEnterFarmModule |
| 27 | + + farm_base_impl::claim_rewards::BaseClaimRewardsModule |
| 28 | + + farm_base_impl::compound_rewards::BaseCompoundRewardsModule |
| 29 | + + farm_base_impl::exit_farm::BaseExitFarmModule |
| 30 | + + farm_boosted_yields::FarmBoostedYieldsModule |
| 31 | + + farm_boosted_yields::boosted_yields_factors::BoostedYieldsFactorsModule |
| 32 | + + farm_boosted_yields::custom_reward_logic::CustomRewardLogicModule |
| 33 | + + week_timekeeping::WeekTimekeepingModule |
| 34 | + + weekly_rewards_splitting::WeeklyRewardsSplittingModule |
| 35 | + + weekly_rewards_splitting::events::WeeklyRewardsSplittingEventsModule |
| 36 | + + weekly_rewards_splitting::global_info::WeeklyRewardsGlobalInfo |
| 37 | + + weekly_rewards_splitting::locked_token_buckets::WeeklyRewardsLockedTokenBucketsModule |
| 38 | + + weekly_rewards_splitting::update_claim_progress_energy::UpdateClaimProgressEnergyModule |
| 39 | + + energy_query::EnergyQueryModule |
| 40 | + + utils::UtilsModule |
| 41 | +{ |
| 42 | + #[payable("*")] |
| 43 | + #[endpoint(enterFarmOnBehalf)] |
| 44 | + fn enter_farm_on_behalf(&self, user: ManagedAddress) -> EnterFarmResultType<Self::Api> { |
| 45 | + let caller = self.blockchain().get_caller(); |
| 46 | + self.require_user_whitelisted(&user, &caller); |
| 47 | + |
| 48 | + self.check_additional_payments_original_owner(&user); |
| 49 | + |
| 50 | + let boosted_rewards = self.claim_only_boosted_payment(&user); |
| 51 | + let new_farm_token = self.enter_farm::<NoMintWrapper<Self>>(user.clone()); |
| 52 | + self.send_payment_non_zero(&caller, &new_farm_token); |
| 53 | + |
| 54 | + let locked_rewards_payment = if boosted_rewards == 0 { |
| 55 | + let locked_token_id = self.get_locked_token_id(); |
| 56 | + EsdtTokenPayment::new(locked_token_id, 0, boosted_rewards) |
| 57 | + } else { |
| 58 | + self.lock_virtual( |
| 59 | + self.reward_token_id().get(), |
| 60 | + boosted_rewards, |
| 61 | + user.clone(), |
| 62 | + user.clone(), |
| 63 | + ) |
| 64 | + }; |
| 65 | + |
| 66 | + self.update_energy_and_progress(&user); |
| 67 | + |
| 68 | + (new_farm_token, locked_rewards_payment).into() |
| 69 | + } |
| 70 | + |
| 71 | + #[payable("*")] |
| 72 | + #[endpoint(claimRewardsOnBehalf)] |
| 73 | + fn claim_rewards_on_behalf(&self) -> ClaimRewardsResultType<Self::Api> { |
| 74 | + let user = self.check_and_return_original_owner(); |
| 75 | + let caller = self.blockchain().get_caller(); |
| 76 | + self.require_user_whitelisted(&user, &caller); |
| 77 | + |
| 78 | + let claim_rewards_result = self.claim_rewards::<NoMintWrapper<Self>>(user.clone()); |
| 79 | + |
| 80 | + self.send_payment_non_zero(&caller, &claim_rewards_result.new_farm_token); |
| 81 | + |
| 82 | + let rewards_payment = claim_rewards_result.rewards; |
| 83 | + let locked_rewards_payment = if rewards_payment.amount == 0 { |
| 84 | + let locked_token_id = self.get_locked_token_id(); |
| 85 | + EsdtTokenPayment::new(locked_token_id, 0, rewards_payment.amount) |
| 86 | + } else { |
| 87 | + self.lock_virtual( |
| 88 | + rewards_payment.token_identifier, |
| 89 | + rewards_payment.amount, |
| 90 | + user.clone(), |
| 91 | + user, |
| 92 | + ) |
| 93 | + }; |
| 94 | + |
| 95 | + (claim_rewards_result.new_farm_token, locked_rewards_payment).into() |
| 96 | + } |
| 97 | + |
| 98 | + fn check_and_return_original_owner(&self) -> ManagedAddress { |
| 99 | + let payments = self.call_value().all_esdt_transfers().clone_value(); |
| 100 | + let farm_token_mapper = self.farm_token(); |
| 101 | + let mut original_owner = ManagedAddress::zero(); |
| 102 | + for payment in payments.into_iter() { |
| 103 | + let attributes: FarmTokenAttributes<Self::Api> = |
| 104 | + farm_token_mapper.get_token_attributes(payment.token_nonce); |
| 105 | + |
| 106 | + if original_owner.is_zero() { |
| 107 | + original_owner = attributes.original_owner; |
| 108 | + } else { |
| 109 | + require!( |
| 110 | + original_owner == attributes.original_owner, |
| 111 | + "All position must have the same original owner" |
| 112 | + ); |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + require!( |
| 117 | + !original_owner.is_zero(), |
| 118 | + "Original owner could not be identified" |
| 119 | + ); |
| 120 | + |
| 121 | + original_owner |
| 122 | + } |
| 123 | + |
| 124 | + fn check_additional_payments_original_owner(&self, user: &ManagedAddress) { |
| 125 | + let payments = self.call_value().all_esdt_transfers().clone_value(); |
| 126 | + if payments.len() == 1 { |
| 127 | + return; |
| 128 | + } |
| 129 | + |
| 130 | + let farm_token_mapper = self.farm_token(); |
| 131 | + let farm_token_id = farm_token_mapper.get_token_id(); |
| 132 | + for payment in payments.into_iter() { |
| 133 | + if payment.token_identifier != farm_token_id { |
| 134 | + continue; |
| 135 | + } |
| 136 | + |
| 137 | + let attributes: FarmTokenAttributes<Self::Api> = |
| 138 | + farm_token_mapper.get_token_attributes(payment.token_nonce); |
| 139 | + |
| 140 | + require!( |
| 141 | + user == &attributes.original_owner, |
| 142 | + "Provided address is not the same as the original owner" |
| 143 | + ); |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + fn require_user_whitelisted(&self, user: &ManagedAddress, authorized_address: &ManagedAddress) { |
| 148 | + let permissions_hub_address = self.permissions_hub_address().get(); |
| 149 | + let is_whitelisted: bool = self |
| 150 | + .permissions_hub_proxy(permissions_hub_address) |
| 151 | + .is_whitelisted(user, authorized_address) |
| 152 | + .execute_on_dest_context(); |
| 153 | + |
| 154 | + require!(is_whitelisted, "Caller is not whitelisted by the user"); |
| 155 | + } |
| 156 | + |
| 157 | + #[only_owner] |
| 158 | + #[endpoint(setPermissionsHubAddress)] |
| 159 | + fn set_permissions_hub_address(&self, address: ManagedAddress) { |
| 160 | + self.permissions_hub_address().set(&address); |
| 161 | + } |
| 162 | + |
| 163 | + #[proxy] |
| 164 | + fn permissions_hub_proxy( |
| 165 | + &self, |
| 166 | + sc_address: ManagedAddress, |
| 167 | + ) -> permissions_hub::Proxy<Self::Api>; |
| 168 | + |
| 169 | + #[storage_mapper("permissionsHubAddress")] |
| 170 | + fn permissions_hub_address(&self) -> SingleValueMapper<ManagedAddress>; |
| 171 | +} |
0 commit comments