diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index ff793a49b5ce6..0816fedff0347 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1842,7 +1842,7 @@ impl_runtime_apis! { impl pallet_nomination_pools_runtime_api::NominationPoolsApi for Runtime { fn pending_rewards(member_account: AccountId) -> Balance { - NominationPools::pending_rewards(member_account) + NominationPools::pending_rewards(member_account).unwrap_or_default() } } diff --git a/frame/nomination-pools/src/lib.rs b/frame/nomination-pools/src/lib.rs index 62d0b3ddd55cb..40db4ac64851a 100644 --- a/frame/nomination-pools/src/lib.rs +++ b/frame/nomination-pools/src/lib.rs @@ -2156,16 +2156,20 @@ pub mod pallet { impl Pallet { /// Returns the pending rewards for the specified `member_account`. /// - /// In the case of error the function returns balance of zero. - pub fn pending_rewards(member_account: T::AccountId) -> BalanceOf { + /// In the case of error, `None` is returned. + pub fn pending_rewards(member_account: T::AccountId) -> Option> { if let Some(pool_member) = PoolMembers::::get(member_account) { - if let Some(reward_pool) = RewardPools::::get(pool_member.pool_id) { - return pool_member - .pending_rewards(reward_pool.last_recorded_reward_counter()) - .unwrap_or_default() + if let Some((reward_pool, bonded_pool)) = RewardPools::::get(pool_member.pool_id) + .zip(BondedPools::::get(pool_member.pool_id)) + { + let current_reward_counter = reward_pool + .current_reward_counter(pool_member.pool_id, bonded_pool.points) + .ok()?; + return pool_member.pending_rewards(current_reward_counter).ok() } } - BalanceOf::::default() + + None } /// The amount of bond that MUST REMAIN IN BONDED in ALL POOLS. diff --git a/frame/nomination-pools/src/tests.rs b/frame/nomination-pools/src/tests.rs index 5aa8e97266e0d..705f8ce3a6449 100644 --- a/frame/nomination-pools/src/tests.rs +++ b/frame/nomination-pools/src/tests.rs @@ -1285,6 +1285,59 @@ mod claim_payout { }); } + #[test] + fn pending_rewards_per_member_works() { + ExtBuilder::default().build_and_execute(|| { + let ed = Balances::minimum_balance(); + + assert_eq!(Pools::pending_rewards(10), Some(0)); + Balances::mutate_account(&default_reward_account(), |f| f.free += 30).unwrap(); + assert_eq!(Pools::pending_rewards(10), Some(30)); + assert_eq!(Pools::pending_rewards(20), None); + + Balances::make_free_balance_be(&20, ed + 10); + assert_ok!(Pools::join(Origin::signed(20), 10, 1)); + + assert_eq!(Pools::pending_rewards(10), Some(30)); + assert_eq!(Pools::pending_rewards(20), Some(0)); + + Balances::mutate_account(&default_reward_account(), |f| f.free += 100).unwrap(); + + assert_eq!(Pools::pending_rewards(10), Some(30 + 50)); + assert_eq!(Pools::pending_rewards(20), Some(50)); + assert_eq!(Pools::pending_rewards(30), None); + + Balances::make_free_balance_be(&30, ed + 10); + assert_ok!(Pools::join(Origin::signed(30), 10, 1)); + + assert_eq!(Pools::pending_rewards(10), Some(30 + 50)); + assert_eq!(Pools::pending_rewards(20), Some(50)); + assert_eq!(Pools::pending_rewards(30), Some(0)); + + Balances::mutate_account(&default_reward_account(), |f| f.free += 60).unwrap(); + + assert_eq!(Pools::pending_rewards(10), Some(30 + 50 + 20)); + assert_eq!(Pools::pending_rewards(20), Some(50 + 20)); + assert_eq!(Pools::pending_rewards(30), Some(20)); + + // 10 should claim 10, 20 should claim nothing. + assert_ok!(Pools::claim_payout(Origin::signed(10))); + assert_eq!(Pools::pending_rewards(10), Some(0)); + assert_eq!(Pools::pending_rewards(20), Some(50 + 20)); + assert_eq!(Pools::pending_rewards(30), Some(20)); + + assert_ok!(Pools::claim_payout(Origin::signed(20))); + assert_eq!(Pools::pending_rewards(10), Some(0)); + assert_eq!(Pools::pending_rewards(20), Some(0)); + assert_eq!(Pools::pending_rewards(30), Some(20)); + + assert_ok!(Pools::claim_payout(Origin::signed(30))); + assert_eq!(Pools::pending_rewards(10), Some(0)); + assert_eq!(Pools::pending_rewards(20), Some(0)); + assert_eq!(Pools::pending_rewards(30), Some(0)); + }); + } + #[test] fn rewards_distribution_is_fair_bond_extra() { ExtBuilder::default().build_and_execute(|| {