Skip to content

Commit

Permalink
Merge pull request #938 from multiversx/farm-supply-for-week-fix
Browse files Browse the repository at this point in the history
farm supply for week fix
  • Loading branch information
psorinionut authored Aug 5, 2024
2 parents 6cd702c + f5d2593 commit 57b3433
Show file tree
Hide file tree
Showing 10 changed files with 587 additions and 26 deletions.
31 changes: 14 additions & 17 deletions dex/farm-with-locked-rewards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,30 +127,19 @@ pub trait Farm:

self.migrate_old_farm_positions(&orig_caller);

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);
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 claim_rewards_result = self.claim_rewards::<NoMintWrapper<Self>>(orig_caller.clone());

let rewards_payment = base_claim_rewards_result.rewards;
self.send_payment_non_zero(&caller, &claim_rewards_result.new_farm_token);

let rewards_payment = claim_rewards_result.rewards;
let locked_rewards_payment = self.send_to_lock_contract_non_zero(
rewards_payment.token_identifier,
rewards_payment.amount,
caller,
orig_caller.clone(),
);

self.emit_claim_rewards_event::<_, FarmTokenAttributes<Self::Api>>(
&orig_caller,
base_claim_rewards_result.context,
base_claim_rewards_result.new_farm_token,
locked_rewards_payment.clone(),
base_claim_rewards_result.created_with_merge,
base_claim_rewards_result.storage_cache,
orig_caller,
);

(output_farm_token_payment, locked_rewards_payment).into()
(claim_rewards_result.new_farm_token, locked_rewards_payment).into()
}

#[payable("*")]
Expand Down Expand Up @@ -237,7 +226,14 @@ pub trait Farm:
);
}

let mut storage_cache = StorageCache::new(self);
self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id);
NoMintWrapper::<Self>::generate_aggregated_rewards(self, &mut storage_cache);

let boosted_rewards = self.claim_only_boosted_payment(user);

self.set_farm_supply_for_current_week(&storage_cache.farm_token_supply);

self.send_to_lock_contract_non_zero(
self.reward_token_id().get(),
boosted_rewards,
Expand Down Expand Up @@ -270,6 +266,7 @@ pub trait Farm:
require!(percentage <= MAX_PERCENT, "Invalid percentage");

let mut storage_cache = StorageCache::new(self);
self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id);
NoMintWrapper::<Self>::generate_aggregated_rewards(self, &mut storage_cache);

self.boosted_yields_rewards_percentage().set(percentage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use farm_with_locked_rewards::Farm;
use locking_module::lock_with_energy_module::LockWithEnergyModule;
use multiversx_sc_modules::pause::PauseModule;
use pausable::{PausableModule, State};
use rewards::RewardsModule;
use sc_whitelist_module::SCWhitelistModule;
use simple_lock::locked_token::LockedTokenModule;
use week_timekeeping::Epoch;
Expand Down Expand Up @@ -422,4 +423,53 @@ where
)
.assert_ok();
}

pub fn claim_boosted_rewards_for_user(
&mut self,
owner: &Address,
broker: &Address,
locked_reward_nonce: u64,
) -> u64 {
self.last_farm_token_nonce += 1;

let mut result = 0;
self.b_mock
.execute_tx(broker, &self.farm_wrapper, &rust_biguint!(0), |sc| {
let reward_payment =
sc.claim_boosted_rewards(OptionalValue::Some(managed_address!(owner)));
assert_eq!(
reward_payment.token_identifier,
managed_token_id!(LOCKED_REWARD_TOKEN_ID)
);
assert_eq!(reward_payment.token_nonce, locked_reward_nonce);

result = reward_payment.amount.to_u64().unwrap();
})
.assert_ok();

result
}

pub fn check_farm_token_supply(&mut self, expected_farm_token_supply: u64) {
let b_mock = &mut self.b_mock;
b_mock
.execute_query(&self.farm_wrapper, |sc| {
let actual_farm_supply = sc.farm_token_supply().get();
assert_eq!(
managed_biguint!(expected_farm_token_supply),
actual_farm_supply
);
})
.assert_ok();
}

pub fn check_farm_rps(&mut self, expected_amount: u64) {
let b_mock = &mut self.b_mock;
b_mock
.execute_query(&self.farm_wrapper, |sc| {
let current_rps = sc.reward_per_share().get();
assert_eq!(managed_biguint!(expected_amount), current_rps);
})
.assert_ok();
}
}
193 changes: 193 additions & 0 deletions dex/farm-with-locked-rewards/tests/farm_with_locked_rewards_test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(deprecated)]

use common_structs::FarmTokenAttributes;
use multiversx_sc::codec::Empty;
use multiversx_sc_scenario::{managed_address, managed_biguint, rust_biguint, DebugApi};
use simple_lock::locked_token::LockedTokenAttributes;

Expand Down Expand Up @@ -335,3 +336,195 @@ fn total_farm_position_claim_with_locked_rewards_test() {
None,
);
}

#[test]
fn claim_only_boosted_rewards_per_week_test() {
DebugApi::dummy();
let mut farm_setup = FarmSetup::new(
farm_with_locked_rewards::contract_obj,
energy_factory::contract_obj,
);

farm_setup.set_boosted_yields_rewards_percentage(BOOSTED_YIELDS_PERCENTAGE);
farm_setup.set_boosted_yields_factors();
farm_setup.b_mock.set_block_epoch(2);

let temp_user = farm_setup.third_user.clone();

// first user enter farm
let farm_in_amount = 100_000_000;
let first_user = farm_setup.first_user.clone();
farm_setup.set_user_energy(&first_user, 1_000, 2, 1);
farm_setup.enter_farm(&first_user, farm_in_amount);

farm_setup.check_farm_token_supply(farm_in_amount);
farm_setup.check_farm_rps(0u64);

farm_setup.b_mock.set_block_nonce(10);
farm_setup.b_mock.set_block_epoch(6);
farm_setup.set_user_energy(&first_user, 1_000, 6, 1);
farm_setup.set_user_energy(&temp_user, 1, 6, 1);
farm_setup.enter_farm(&temp_user, 1);
farm_setup.exit_farm(&temp_user, 2, 1);

farm_setup.check_farm_rps(75_000_000u64);

// advance 1 week
farm_setup.set_user_energy(&first_user, 1_000, 13, 1);
farm_setup.b_mock.set_block_nonce(20);
farm_setup.b_mock.set_block_epoch(13);

let boosted_rewards = 2_500;
let second_week_received_reward_amt =
farm_setup.claim_boosted_rewards_for_user(&first_user, &first_user, 1);

assert_eq!(second_week_received_reward_amt, boosted_rewards);
farm_setup.check_farm_rps(150_000_000u64);

// advance 1 week
farm_setup.set_user_energy(&first_user, 1_000, 15, 1);
farm_setup.b_mock.set_block_nonce(30);
farm_setup.b_mock.set_block_epoch(15);
let third_week_received_reward_amt =
farm_setup.claim_boosted_rewards_for_user(&first_user, &first_user, 1);

assert_eq!(third_week_received_reward_amt, boosted_rewards);
farm_setup.check_farm_rps(225_000_000u64);

farm_setup.b_mock.check_nft_balance::<Empty>(
&first_user,
LOCKED_REWARD_TOKEN_ID,
1,
&rust_biguint!(boosted_rewards * 2),
None,
);
}

#[test]
fn claim_rewards_per_week_test() {
DebugApi::dummy();
let mut farm_setup = FarmSetup::new(
farm_with_locked_rewards::contract_obj,
energy_factory::contract_obj,
);

farm_setup.set_boosted_yields_rewards_percentage(BOOSTED_YIELDS_PERCENTAGE);
farm_setup.set_boosted_yields_factors();
farm_setup.b_mock.set_block_epoch(2);

let temp_user = farm_setup.third_user.clone();

// first user enter farm
let farm_in_amount = 100_000_000;
let first_user = farm_setup.first_user.clone();
farm_setup.set_user_energy(&first_user, 1_000, 2, 1);
farm_setup.enter_farm(&first_user, farm_in_amount);

farm_setup.check_farm_token_supply(farm_in_amount);
farm_setup.check_farm_rps(0u64);

farm_setup.b_mock.set_block_nonce(10);
farm_setup.b_mock.set_block_epoch(6);
farm_setup.set_user_energy(&first_user, 1_000, 6, 1);
farm_setup.set_user_energy(&temp_user, 1, 6, 1);
farm_setup.enter_farm(&temp_user, 1);
farm_setup.exit_farm(&temp_user, 2, 1);

farm_setup.check_farm_rps(75_000_000u64);
let base_rewards_per_week = 7_500;
let boosted_rewards_per_week = 2_500;
let total_rewards_per_week = base_rewards_per_week + boosted_rewards_per_week;

// advance 1 week
farm_setup.set_user_energy(&first_user, 1_000, 13, 1);
farm_setup.b_mock.set_block_nonce(20);
farm_setup.b_mock.set_block_epoch(13);

let second_week_received_reward_amt = farm_setup.claim_rewards(&first_user, 1, farm_in_amount);

assert_eq!(
second_week_received_reward_amt,
total_rewards_per_week + base_rewards_per_week
);
farm_setup.check_farm_rps(150_000_000u64);

// advance 1 week
farm_setup.set_user_energy(&first_user, 1_000, 15, 1);
farm_setup.b_mock.set_block_nonce(30);
farm_setup.b_mock.set_block_epoch(15);
let third_week_received_reward_amt = farm_setup.claim_rewards(&first_user, 3, farm_in_amount);

assert_eq!(third_week_received_reward_amt, total_rewards_per_week);
farm_setup.check_farm_rps(225_000_000u64);

farm_setup.b_mock.check_nft_balance::<Empty>(
&first_user,
LOCKED_REWARD_TOKEN_ID,
1,
&rust_biguint!(total_rewards_per_week * 2 + base_rewards_per_week),
None,
);
}

#[test]
fn claim_boosted_rewards_with_zero_position_test() {
DebugApi::dummy();
let mut farm_setup = FarmSetup::new(
farm_with_locked_rewards::contract_obj,
energy_factory::contract_obj,
);

farm_setup.set_boosted_yields_rewards_percentage(BOOSTED_YIELDS_PERCENTAGE);
farm_setup.set_boosted_yields_factors();
farm_setup.b_mock.set_block_epoch(2);

let temp_user = farm_setup.third_user.clone();

// first user enter farm
let farm_in_amount = 100_000_000;
let first_user = farm_setup.first_user.clone();
farm_setup.set_user_energy(&first_user, 1_000, 2, 1);
farm_setup.enter_farm(&first_user, farm_in_amount);

farm_setup.check_farm_token_supply(farm_in_amount);
farm_setup.check_farm_rps(0u64);

farm_setup.b_mock.set_block_nonce(10);
farm_setup.b_mock.set_block_epoch(6);
farm_setup.set_user_energy(&first_user, 1_000, 6, 1);
farm_setup.set_user_energy(&temp_user, 1, 6, 1);
farm_setup.enter_farm(&temp_user, 1);
farm_setup.exit_farm(&temp_user, 2, 1);

farm_setup.check_farm_rps(75_000_000u64);

// advance 1 week
farm_setup.set_user_energy(&first_user, 1_000, 13, 1);
farm_setup.b_mock.set_block_nonce(20);
farm_setup.b_mock.set_block_epoch(13);

let second_week_received_reward_amt =
farm_setup.claim_boosted_rewards_for_user(&temp_user, &temp_user, 0);

assert_eq!(second_week_received_reward_amt, 0);
farm_setup.check_farm_rps(150_000_000u64);

// advance 1 week
let boosted_rewards = 2_500;
farm_setup.set_user_energy(&first_user, 1_000, 15, 1);
farm_setup.b_mock.set_block_nonce(30);
farm_setup.b_mock.set_block_epoch(15);
let third_week_received_reward_amt =
farm_setup.claim_boosted_rewards_for_user(&first_user, &first_user, 1);

assert_eq!(third_week_received_reward_amt, boosted_rewards * 2); // user receives rewards for weeks 1 and 2)
farm_setup.check_farm_rps(225_000_000u64);

farm_setup.b_mock.check_nft_balance::<Empty>(
&first_user,
LOCKED_REWARD_TOKEN_ID,
1,
&rust_biguint!(boosted_rewards * 2),
None,
);
}
7 changes: 7 additions & 0 deletions dex/farm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,16 @@ pub trait Farm:
);
}

let mut storage_cache = StorageCache::new(self);
self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id);
Wrapper::<Self>::generate_aggregated_rewards(self, &mut storage_cache);

let boosted_rewards = self.claim_only_boosted_payment(user);
let boosted_rewards_payment =
EsdtTokenPayment::new(self.reward_token_id().get(), 0, boosted_rewards);

self.set_farm_supply_for_current_week(&storage_cache.farm_token_supply);

self.send_payment_non_zero(user, &boosted_rewards_payment);

boosted_rewards_payment
Expand Down Expand Up @@ -261,6 +267,7 @@ pub trait Farm:
require!(percentage <= MAX_PERCENT, "Invalid percentage");

let mut storage_cache = StorageCache::new(self);
self.validate_contract_state(storage_cache.contract_state, &storage_cache.farm_token_id);
Wrapper::<Self>::generate_aggregated_rewards(self, &mut storage_cache);

self.boosted_yields_rewards_percentage().set(percentage);
Expand Down
7 changes: 1 addition & 6 deletions farm-staking/farm-staking/src/base_impl_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,8 @@ where
caller: &ManagedAddress<<<Self as FarmContract>::FarmSc as ContractBase>::Api>,
) -> BigUint<<<Self as FarmContract>::FarmSc as ContractBase>::Api> {
let user_total_farm_position = sc.user_total_farm_position(caller).get();
let mut boosted_rewards = BigUint::zero();

if user_total_farm_position > 0 {
boosted_rewards = sc.claim_boosted_yields_rewards(caller, user_total_farm_position);
}

boosted_rewards
sc.claim_boosted_yields_rewards(caller, user_total_farm_position)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use contexts::storage_cache::StorageCache;
use farm_base_impl::base_traits_impl::FarmContract;

use crate::base_impl_wrapper::FarmStakingWrapper;

multiversx_sc::imports!();
Expand Down Expand Up @@ -38,10 +41,15 @@ pub trait ClaimOnlyBoostedStakingRewardsModule:
);
}

let mut storage_cache = StorageCache::new(self);
FarmStakingWrapper::<Self>::generate_aggregated_rewards(self, &mut storage_cache);

let boosted_rewards = self.claim_only_boosted_payment(user);
let boosted_rewards_payment =
EsdtTokenPayment::new(self.reward_token_id().get(), 0, boosted_rewards);

self.set_farm_supply_for_current_week(&storage_cache.farm_token_supply);

self.send_payment_non_zero(user, &boosted_rewards_payment);

boosted_rewards_payment
Expand Down
Loading

0 comments on commit 57b3433

Please sign in to comment.