Skip to content

Commit

Permalink
Fix: fix cumulative rewards calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszaaa committed Dec 4, 2023
1 parent 227ffc8 commit 1ef50f5
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 18 deletions.
31 changes: 13 additions & 18 deletions pallets/proof-of-stake/src/schedule_rewards_calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,36 +70,33 @@ pub struct ScheduleRewards<Balance: AtLeast32BitUnsigned> {

impl<Balance: AtLeast32BitUnsigned> ScheduleRewards<Balance> {
pub fn provide_rewards(&mut self, now: SessionId, amount: Balance) {
if now <= self.pending_session_id {
self.pending += amount;
} else {
if now > self.pending_session_id {
self.total += self.pending.clone();
self.pending = amount;
self.pending_session_id = now;
} else {
self.pending += amount;
}
}

pub fn total_rewards(&self, now: SessionId) -> Balance {
if now <= self.pending_session_id {
self.total.clone()
} else {
if now > self.pending_session_id {
self.total.clone() + self.pending.clone()
} else {
self.total.clone()
}
}

pub fn transfer_pending(&mut self, now: SessionId) {
pub fn clear(&mut self, now: SessionId) {
if now > self.pending_session_id {
self.total += self.pending.clone();
self.total = Balance::zero();
self.pending = Balance::zero();
self.pending_session_id = now;
} else {
self.total = Balance::zero();
self.pending_session_id = now;
}
}

pub fn clear(&mut self, now: SessionId) {
self.total = Balance::zero();
self.pending = Balance::zero();
self.pending_session_id = now;
}
}

pub struct ScheduleRewardsCalculator<T> {
Expand All @@ -119,8 +116,7 @@ impl<T: Config> ScheduleRewardsCalculator<T> {

let (cumulative, idx) =
ScheduleRewardsPerLiquidity::<T>::get((liquidity_asset_id, liquidity_assets_reward));
if idx == (Pallet::<T>::session_index() as u64) {
} else {
if (idx + 1) < (Pallet::<T>::session_index() as u64) {
let total_activated_liquidity =
Self::total_activated_liquidity(liquidity_asset_id, liquidity_assets_reward);
let total_schedule_rewards =
Expand All @@ -129,7 +125,6 @@ impl<T: Config> ScheduleRewardsCalculator<T> {
ScheduleRewardsTotal::<T>::mutate(
(liquidity_asset_id, liquidity_assets_reward),
|schedule| {
schedule.transfer_pending(session_id);
schedule.clear(session_id);
},
);
Expand All @@ -138,7 +133,7 @@ impl<T: Config> ScheduleRewardsCalculator<T> {
.unwrap_or_default();
ScheduleRewardsPerLiquidity::<T>::insert(
(liquidity_asset_id, liquidity_assets_reward),
(cumulative + pending, (Pallet::<T>::session_index() as u64)),
(cumulative + pending, ((Pallet::<T>::session_index() - 1) as u64)),
);
}
}
Expand Down
179 changes: 179 additions & 0 deletions pallets/proof-of-stake/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4313,3 +4313,182 @@ fn test_NotEnoughAssets_is_triggered_when_user_wants_to_deactive_more_tokens_tha
);
});
}

#[test]
#[serial]
fn test_cumulative_rewards_per_liquidity_over_multiple_sessions() {
ExtBuilder::new()
.issue(ALICE, LIQUIDITY_TOKEN, 100_000_000_000u128)
.issue(BOB, REWARD_TOKEN, 100_000_000_000_000_000_000_000_000u128)
.issue(BOB, LIQUIDITY_TOKEN, 500_000_000_000u128)
.execute_with_default_mocks(|| {
forward_to_block::<Test>(5);
ProofOfStake::reward_pool(
RuntimeOrigin::signed(BOB),
REWARDED_PAIR,
REWARD_TOKEN,
10000u128,
10u32.into(),
)
.unwrap();

assert_eq!(
ScheduleRewardsPerLiquidity::<Test>::get((LIQUIDITY_TOKEN, REWARD_TOKEN)),
(U256::from(0), 0)
);

ProofOfStake::activate_liquidity_for_3rdparty_rewards(
RuntimeOrigin::signed(BOB),
LIQUIDITY_TOKEN,
100u128,
REWARD_TOKEN,
None,
)
.unwrap();

assert_eq!(
ScheduleRewardsPerLiquidity::<Test>::get((LIQUIDITY_TOKEN, REWARD_TOKEN)),
(U256::from(0), 0)
);

ScheduleRewardsCalculator::<Test>::update_cumulative_rewards(
LIQUIDITY_TOKEN,
REWARD_TOKEN,
);

assert_eq!(
ScheduleRewardsPerLiquidity::<Test>::get((LIQUIDITY_TOKEN, REWARD_TOKEN)),
(U256::from(0), 0)
);

forward_to_block::<Test>(9);

ScheduleRewardsCalculator::<Test>::update_cumulative_rewards(
LIQUIDITY_TOKEN,
REWARD_TOKEN,
);
assert_eq!(
ScheduleRewardsPerLiquidity::<Test>::get((LIQUIDITY_TOKEN, REWARD_TOKEN)),
(U256::from(0), 0)
);

forward_to_block::<Test>(18);

ScheduleRewardsCalculator::<Test>::update_cumulative_rewards(
LIQUIDITY_TOKEN,
REWARD_TOKEN,
);
assert_eq!(
ScheduleRewardsPerLiquidity::<Test>::get((LIQUIDITY_TOKEN, REWARD_TOKEN)),
(U256::from(0), 0)
);
assert_eq!(
ProofOfStake::calculate_3rdparty_rewards_amount(BOB, LIQUIDITY_TOKEN, REWARD_TOKEN)
.unwrap(),
0
);

forward_to_block::<Test>(25);

ScheduleRewardsCalculator::<Test>::update_cumulative_rewards(
LIQUIDITY_TOKEN,
REWARD_TOKEN,
);
assert_eq!(
ScheduleRewardsPerLiquidity::<Test>::get((LIQUIDITY_TOKEN, REWARD_TOKEN)),
(U256::from(u128::MAX) * 1000 / 100, 1)
);

forward_to_block::<Test>(30);
ScheduleRewardsCalculator::<Test>::update_cumulative_rewards(
LIQUIDITY_TOKEN,
REWARD_TOKEN,
);

assert_eq!(
ScheduleRewardsPerLiquidity::<Test>::get((LIQUIDITY_TOKEN, REWARD_TOKEN)),
(U256::from(2) * (U256::from(u128::MAX) * 1000 / 100), 2)
);

assert_eq!(
ProofOfStake::calculate_3rdparty_rewards_amount(BOB, LIQUIDITY_TOKEN, REWARD_TOKEN)
.unwrap(),
2000
);

ScheduleRewardsCalculator::<Test>::update_cumulative_rewards(
LIQUIDITY_TOKEN,
REWARD_TOKEN,
);
});
}

#[test]
#[serial]
fn test_amount_of_rewards_when_activation_happens_after_schedule_was_processed_in_current_session()
{
ExtBuilder::new()
.issue(ALICE, LIQUIDITY_TOKEN, 100_000_000_000u128)
.issue(BOB, REWARD_TOKEN, 100_000_000_000_000_000_000_000_000u128)
.issue(BOB, LIQUIDITY_TOKEN, 500_000_000_000u128)
.execute_with_default_mocks(|| {
forward_to_block::<Test>(36);
ProofOfStake::reward_pool(
RuntimeOrigin::signed(BOB),
REWARDED_PAIR,
REWARD_TOKEN,
100_000_000_000_000_000_000_000_000u128,
7u32.into(),
)
.unwrap();

forward_to_block::<Test>(40);
ProofOfStake::activate_liquidity_for_3rdparty_rewards(
RuntimeOrigin::signed(BOB),
LIQUIDITY_TOKEN,
100_000_000_000u128,
REWARD_TOKEN,
None,
)
.unwrap();

forward_to_block::<Test>(50);
ProofOfStake::activate_liquidity_for_3rdparty_rewards(
RuntimeOrigin::signed(ALICE),
LIQUIDITY_TOKEN,
100_000_000_000u128,
REWARD_TOKEN,
None,
)
.unwrap();

forward_to_block::<Test>(64);
ProofOfStake::activate_liquidity_for_3rdparty_rewards(
RuntimeOrigin::signed(BOB),
LIQUIDITY_TOKEN,
100_000_000_000u128,
REWARD_TOKEN,
None,
)
.unwrap();

roll_to_next_session::<Test>();
roll_to_next_session::<Test>();
roll_to_next_session::<Test>();
roll_to_next_session::<Test>();
roll_to_next_session::<Test>();

let alice_rewards = ProofOfStake::calculate_3rdparty_rewards_amount(
ALICE,
LIQUIDITY_TOKEN,
REWARD_TOKEN,
)
.unwrap();
let bob_rewards =
ProofOfStake::calculate_3rdparty_rewards_amount(BOB, LIQUIDITY_TOKEN, REWARD_TOKEN)
.unwrap();

// + 1 because of rounding
assert_eq!((alice_rewards + bob_rewards + 1), 100_000_000_000_000_000_000_000_000);
});
}

0 comments on commit 1ef50f5

Please sign in to comment.