Skip to content

Commit

Permalink
Merge pull request #852 from multiversx/farm-accumulate-boosted-rewards
Browse files Browse the repository at this point in the history
accumulate boosted rewards
  • Loading branch information
dorin-iancu authored Mar 15, 2024
2 parents b4910e7 + 4b5bca0 commit a6c8d4d
Show file tree
Hide file tree
Showing 44 changed files with 324 additions and 487 deletions.
30 changes: 27 additions & 3 deletions common/modules/farm/farm_base_impl/src/base_traits_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@ use mergeable::Mergeable;
use multiversx_sc_modules::transfer_role_proxy::PaymentsVec;
use rewards::RewardsModule;

pub struct RewardPair<M: ManagedTypeApi> {
pub base: BigUint<M>,
pub boosted: BigUint<M>,
}

impl<M: ManagedTypeApi> RewardPair<M> {
#[inline]
pub fn new(base: BigUint<M>, boosted: BigUint<M>) -> Self {
Self { base, boosted }
}

#[inline]
pub fn new_zero() -> Self {
Self::new(BigUint::zero(), BigUint::zero())
}

#[inline]
pub fn total_rewards(&self) -> BigUint<M> {
&self.base + &self.boosted
}
}

pub trait AllBaseFarmImplTraits =
rewards::RewardsModule
+ config::ConfigModule
Expand Down Expand Up @@ -101,14 +123,16 @@ pub trait FarmContract {
farm_token_amount: &BigUint<<Self::FarmSc as ContractBase>::Api>,
token_attributes: &Self::AttributesType,
storage_cache: &StorageCache<Self::FarmSc>,
) -> BigUint<<Self::FarmSc as ContractBase>::Api> {
) -> RewardPair<<Self::FarmSc as ContractBase>::Api> {
let token_rps = token_attributes.get_reward_per_share();
if storage_cache.reward_per_share <= token_rps {
return BigUint::zero();
return RewardPair::new_zero();
}

let rps_diff = &storage_cache.reward_per_share - &token_rps;
farm_token_amount * &rps_diff / &storage_cache.division_safety_constant
let base_rewards = farm_token_amount * &rps_diff / &storage_cache.division_safety_constant;

RewardPair::new(base_rewards, BigUint::zero())
}

fn create_enter_farm_initial_attributes(
Expand Down
10 changes: 5 additions & 5 deletions common/modules/farm/farm_base_impl/src/claim_rewards.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
multiversx_sc::imports!();

use crate::base_traits_impl::FarmContract;
use crate::base_traits_impl::{FarmContract, RewardPair};
use common_structs::{PaymentAttributesPair, PaymentsVec};
use contexts::{
claim_rewards_context::ClaimRewardsContext,
Expand All @@ -15,7 +15,7 @@ where
{
pub context: ClaimRewardsContext<C::Api, T>,
pub storage_cache: StorageCache<'a, C>,
pub rewards: EsdtTokenPayment<C::Api>,
pub rewards: RewardPair<C::Api>,
pub new_farm_token: PaymentAttributesPair<C::Api, T>,
pub created_with_merge: bool,
}
Expand Down Expand Up @@ -72,14 +72,14 @@ pub trait BaseClaimRewardsModule:
.clone()
.into_part(farm_token_amount);

let reward = FC::calculate_rewards(
let rewards = FC::calculate_rewards(
self,
&caller,
farm_token_amount,
&token_attributes,
&storage_cache,
);
storage_cache.reward_reserve -= &reward;
storage_cache.reward_reserve -= rewards.total_rewards();

FC::check_and_update_user_farm_position(self, &caller, &payments);

Expand Down Expand Up @@ -112,7 +112,7 @@ pub trait BaseClaimRewardsModule:
InternalClaimRewardsResult {
created_with_merge: !claim_rewards_context.additional_payments.is_empty(),
context: claim_rewards_context,
rewards: EsdtTokenPayment::new(storage_cache.reward_token_id.clone(), 0, reward),
rewards,
new_farm_token,
storage_cache,
}
Expand Down
13 changes: 7 additions & 6 deletions common/modules/farm/farm_base_impl/src/compound_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,16 @@ pub trait BaseCompoundRewardsModule:
.clone()
.into_part(farm_token_amount);

let reward = FC::calculate_rewards(
let rewards = FC::calculate_rewards(
self,
&caller,
farm_token_amount,
&token_attributes,
&storage_cache,
);
storage_cache.reward_reserve -= &reward;
storage_cache.farm_token_supply += &reward;
let total_rewards = rewards.total_rewards();
storage_cache.reward_reserve -= &total_rewards;
storage_cache.farm_token_supply += &total_rewards;

FC::check_and_update_user_farm_position(self, &caller, &payments);

Expand All @@ -78,15 +79,15 @@ pub trait BaseCompoundRewardsModule:
caller.clone(),
token_attributes,
storage_cache.reward_per_share.clone(),
&reward,
&total_rewards,
);
let new_farm_token = self.merge_and_create_token(
base_attributes,
&compound_rewards_context.additional_payments,
&farm_token_mapper,
);

FC::increase_user_farm_position(self, &caller, &reward);
FC::increase_user_farm_position(self, &caller, &total_rewards);

let first_farm_token = &compound_rewards_context.first_farm_token.payment;
farm_token_mapper.nft_burn(first_farm_token.token_nonce, &first_farm_token.amount);
Expand All @@ -97,7 +98,7 @@ pub trait BaseCompoundRewardsModule:
created_with_merge: !compound_rewards_context.additional_payments.is_empty(),
context: compound_rewards_context,
new_farm_token,
compounded_rewards: reward,
compounded_rewards: total_rewards,
storage_cache,
}
}
Expand Down
12 changes: 5 additions & 7 deletions common/modules/farm/farm_base_impl/src/exit_farm.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
multiversx_sc::imports!();

use crate::base_traits_impl::FarmContract;
use crate::base_traits_impl::{FarmContract, RewardPair};
use contexts::{
exit_farm_context::ExitFarmContext,
storage_cache::{FarmContracTraitBounds, StorageCache},
Expand All @@ -15,7 +15,7 @@ where
pub context: ExitFarmContext<C::Api, T>,
pub storage_cache: StorageCache<'a, C>,
pub farming_token_payment: EsdtTokenPayment<C::Api>,
pub reward_payment: EsdtTokenPayment<C::Api>,
pub rewards: RewardPair<C::Api>,
}

#[multiversx_sc::module]
Expand Down Expand Up @@ -53,14 +53,14 @@ pub trait BaseExitFarmModule:
.clone()
.into_part(farm_token_amount);

let reward = FC::calculate_rewards(
let rewards = FC::calculate_rewards(
self,
&caller,
farm_token_amount,
&token_attributes,
&storage_cache,
);
storage_cache.reward_reserve -= &reward;
storage_cache.reward_reserve -= rewards.total_rewards();

FC::decrease_user_farm_position(self, &payment);

Expand All @@ -70,8 +70,6 @@ pub trait BaseExitFarmModule:
0,
farming_token_amount,
);
let reward_payment =
EsdtTokenPayment::new(storage_cache.reward_token_id.clone(), 0, reward);

let farm_token_payment = &exit_farm_context.farm_token.payment;
self.send().esdt_local_burn(
Expand All @@ -85,7 +83,7 @@ pub trait BaseExitFarmModule:
InternalExitFarmResult {
context: exit_farm_context,
farming_token_payment,
reward_payment,
rewards,
storage_cache,
}
}
Expand Down
1 change: 1 addition & 0 deletions common/modules/token_send/src/token_send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub trait TokenSendModule {
self.send().direct_esdt(to, token_id, token_nonce, amount);
}

#[inline]
fn send_payment_non_zero(&self, to: &ManagedAddress, payment: &EsdtTokenPayment<Self::Api>) {
self.send_tokens_non_zero(
to,
Expand Down
74 changes: 29 additions & 45 deletions dex/farm-with-locked-rewards/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#![no_std]
#![allow(clippy::too_many_arguments)]
#![feature(exact_size_is_empty)]

multiversx_sc::imports!();
multiversx_sc::derive_imports!();
Expand All @@ -11,13 +9,13 @@ use core::marker::PhantomData;
use week_timekeeping::Epoch;

use farm::{
base_functions::{BaseFunctionsModule, ClaimRewardsResultType, DoubleMultiPayment, Wrapper},
base_functions::{BaseFunctionsModule, ClaimRewardsResultType, Wrapper},
exit_penalty::{
DEFAULT_BURN_GAS_LIMIT, DEFAULT_MINUMUM_FARMING_EPOCHS, DEFAULT_PENALTY_PERCENT,
},
EnterFarmResultType, ExitFarmWithPartialPosResultType,
ExitFarmWithPartialPosResultType,
};
use farm_base_impl::base_traits_impl::FarmContract;
use farm_base_impl::base_traits_impl::{FarmContract, RewardPair};

#[multiversx_sc::contract]
pub trait Farm:
Expand Down Expand Up @@ -95,25 +93,21 @@ pub trait Farm:
fn enter_farm_endpoint(
&self,
opt_orig_caller: OptionalValue<ManagedAddress>,
) -> EnterFarmResultType<Self::Api> {
) -> EsdtTokenPayment {
let caller = self.blockchain().get_caller();
let orig_caller = self.get_orig_caller_from_opt(&caller, opt_orig_caller);

self.migrate_old_farm_positions(&orig_caller);

let boosted_rewards = self.claim_only_boosted_payment(&orig_caller);
let boosted_rewards_payment = self.send_to_lock_contract_non_zero(
self.reward_token_id().get(),
boosted_rewards,
caller.clone(),
orig_caller.clone(),
);
self.add_boosted_rewards(&orig_caller, &boosted_rewards);

let new_farm_token = self.enter_farm::<NoMintWrapper<Self>>(orig_caller.clone());
self.send_payment_non_zero(&caller, &new_farm_token);

self.update_energy_and_progress(&orig_caller);

(new_farm_token, boosted_rewards_payment).into()
new_farm_token
}

#[payable("*")]
Expand All @@ -122,12 +116,7 @@ pub trait Farm:
&self,
opt_orig_caller: OptionalValue<ManagedAddress>,
) -> ClaimRewardsResultType<Self::Api> {
let current_epoch = self.blockchain().get_block_epoch();
let first_week_start_epoch = self.first_week_start_epoch().get();
require!(
first_week_start_epoch <= current_epoch,
"Cannot claim rewards yet"
);
self.require_first_epoch_passed();

let caller = self.blockchain().get_caller();
let orig_caller = self.get_orig_caller_from_opt(&caller, opt_orig_caller);
Expand All @@ -137,13 +126,15 @@ pub trait Farm:
let payments = self.call_value().all_esdt_transfers().clone_value();
let base_claim_rewards_result =
self.claim_rewards_base::<NoMintWrapper<Self>>(orig_caller.clone(), payments);
self.add_boosted_rewards(&orig_caller, &base_claim_rewards_result.rewards.boosted);

let output_farm_token_payment = base_claim_rewards_result.new_farm_token.payment.clone();
self.send_payment_non_zero(&caller, &output_farm_token_payment);

let rewards_payment = base_claim_rewards_result.rewards;
let reward_token_id = self.reward_token_id().get();
let locked_rewards_payment = self.send_to_lock_contract_non_zero(
rewards_payment.token_identifier,
rewards_payment.amount,
reward_token_id,
base_claim_rewards_result.rewards.base,
caller,
orig_caller.clone(),
);
Expand All @@ -170,19 +161,18 @@ pub trait Farm:
let orig_caller = self.get_orig_caller_from_opt(&caller, opt_orig_caller);

let payment = self.call_value().single_esdt();

let migrated_amount = self.migrate_old_farm_positions(&orig_caller);

let exit_farm_result = self.exit_farm::<NoMintWrapper<Self>>(orig_caller.clone(), payment);
self.add_boosted_rewards(&orig_caller, &exit_farm_result.rewards.boosted);

self.decrease_old_farm_positions(migrated_amount, &orig_caller);

let rewards = exit_farm_result.rewards;
self.send_payment_non_zero(&caller, &exit_farm_result.farming_tokens);

let reward_token_id = self.reward_token_id().get();
let locked_rewards_payment = self.send_to_lock_contract_non_zero(
rewards.token_identifier.clone(),
rewards.amount,
reward_token_id,
exit_farm_result.rewards.base,
caller,
orig_caller.clone(),
);
Expand All @@ -197,34 +187,25 @@ pub trait Farm:
fn merge_farm_tokens_endpoint(
&self,
opt_orig_caller: OptionalValue<ManagedAddress>,
) -> DoubleMultiPayment<Self::Api> {
) -> EsdtTokenPayment {
let caller = self.blockchain().get_caller();
let orig_caller = self.get_orig_caller_from_opt(&caller, opt_orig_caller);

self.migrate_old_farm_positions(&orig_caller);

let boosted_rewards = self.claim_only_boosted_payment(&orig_caller);
self.add_boosted_rewards(&orig_caller, &boosted_rewards);

let merged_farm_token = self.merge_farm_tokens::<NoMintWrapper<Self>>();

self.send_payment_non_zero(&caller, &merged_farm_token);
let locked_rewards_payment = self.send_to_lock_contract_non_zero(
self.reward_token_id().get(),
boosted_rewards,
caller,
orig_caller,
);

(merged_farm_token, locked_rewards_payment).into()
merged_farm_token
}

#[endpoint(claimBoostedRewards)]
fn claim_boosted_rewards(&self, opt_user: OptionalValue<ManagedAddress>) -> EsdtTokenPayment {
let current_epoch = self.blockchain().get_block_epoch();
let first_week_start_epoch = self.first_week_start_epoch().get();
require!(
first_week_start_epoch <= current_epoch,
"Cannot claim rewards yet"
);
self.require_first_epoch_passed();

let caller = self.blockchain().get_caller();
let user = match &opt_user {
Expand All @@ -239,10 +220,11 @@ pub trait Farm:
);
}

let accumulated_boosted_rewards = self.accumulated_rewards_per_user(user).take();
let boosted_rewards = self.claim_only_boosted_payment(user);
self.send_to_lock_contract_non_zero(
self.reward_token_id().get(),
boosted_rewards,
accumulated_boosted_rewards + boosted_rewards,
user.clone(),
user.clone(),
)
Expand Down Expand Up @@ -278,13 +260,15 @@ pub trait Farm:
let mut storage_cache = StorageCache::new(self);
NoMintWrapper::<Self>::generate_aggregated_rewards(self, &mut storage_cache);

NoMintWrapper::<Self>::calculate_rewards(
let rewards = NoMintWrapper::<Self>::calculate_rewards(
self,
&user,
&farm_token_amount,
&attributes,
&storage_cache,
)
);

rewards.base
}

fn send_to_lock_contract_non_zero(
Expand Down Expand Up @@ -346,7 +330,7 @@ where
farm_token_amount: &BigUint<<Self::FarmSc as ContractBase>::Api>,
token_attributes: &Self::AttributesType,
storage_cache: &StorageCache<Self::FarmSc>,
) -> BigUint<<Self::FarmSc as ContractBase>::Api> {
) -> RewardPair<<Self::FarmSc as ContractBase>::Api> {
Wrapper::<T>::calculate_rewards(
sc,
caller,
Expand Down
Loading

0 comments on commit a6c8d4d

Please sign in to comment.