From 788c749caf76e047b4f8cc2992663676dd0e8c03 Mon Sep 17 00:00:00 2001 From: "Mar.io" Date: Thu, 30 Sep 2021 18:41:21 +0200 Subject: [PATCH 1/5] added counter for individual rewards --- frame/dapps-staking/src/lib.rs | 7 +--- frame/dapps-staking/src/pallet/mod.rs | 43 +++++++++++++------- frame/dapps-staking/src/testing_utils.rs | 21 +++++++++- frame/dapps-staking/src/tests.rs | 51 +++++++++++++++--------- 4 files changed, 83 insertions(+), 39 deletions(-) diff --git a/frame/dapps-staking/src/lib.rs b/frame/dapps-staking/src/lib.rs index eed5cf3c4..4cc69586b 100644 --- a/frame/dapps-staking/src/lib.rs +++ b/frame/dapps-staking/src/lib.rs @@ -86,12 +86,7 @@ pub enum SmartContract { /// The ledger of a (bonded) stash. #[derive(PartialEq, Eq, Clone, Encode, Decode, Default, RuntimeDebug)] pub struct StakingLedger { - /// The total amount of the stash's balance that we are currently accounting for. - /// It's just `active` plus all the `unlocking` balances. + /// The total amount of the staker's balance that we are currently accounting for. #[codec(compact)] pub total: Balance, - /// The total amount of the stash's balance that will be at stake in any forthcoming - /// rounds. - #[codec(compact)] - pub active: Balance, } diff --git a/frame/dapps-staking/src/pallet/mod.rs b/frame/dapps-staking/src/pallet/mod.rs index 06c676ba9..90e1b55f7 100644 --- a/frame/dapps-staking/src/pallet/mod.rs +++ b/frame/dapps-staking/src/pallet/mod.rs @@ -84,18 +84,11 @@ pub mod pallet { /// Number of eras to keep in history. /// /// Information is kept for eras in `[current_era - history_depth; current_era]`. - /// - /// Must be more than the number of eras delayed by session otherwise. I.e. active era must - /// always be in history. I.e. `active_era > current_era - history_depth` must be - /// guaranteed. #[pallet::storage] #[pallet::getter(fn history_depth)] pub(crate) type HistoryDepth = StorageValue<_, u32, ValueQuery, HistoryDepthOnEmpty>; /// The current era index. - /// - /// This is the latest planned era, depending on how the Session pallet queues the validator - /// set, it might be active or not. #[pallet::storage] #[pallet::getter(fn current_era)] pub type CurrentEra = StorageValue<_, EraIndex, ValueQuery>; @@ -132,6 +125,19 @@ pub mod pallet { pub(crate) type EraRewardsAndStakes = StorageMap<_, Twox64Concat, EraIndex, EraRewardAndStake>>; + /// Reward counter for individual stakers and the developer + #[pallet::storage] + #[pallet::getter(fn reward_counter)] + pub(crate) type IndividualRewardCounter = StorageDoubleMap< + _, + Twox64Concat, + SmartContract, + Twox64Concat, + T::AccountId, + BalanceOf, + ValueQuery, + >; + /// Stores amount staked and stakers for a contract per era #[pallet::storage] #[pallet::getter(fn contract_era_stake)] @@ -393,7 +399,6 @@ pub mod pallet { // update the ledger value by adding the newly bonded funds ledger.total += value_to_stake; - ledger.active += value_to_stake; // Get the latest era staking point info or create it if contract hasn't been staked yet so far. let era_when_contract_last_staked = Self::contract_last_staked(&contract_id); @@ -527,6 +532,8 @@ pub mod pallet { // if staked value would fall below threshold, unstake everything era_staking_points.stakers.remove(&staker); value_to_unstake = staked_value; + // remove reward counter + IndividualRewardCounter::::remove(&contract_id, &staker); } else { era_staking_points .stakers @@ -539,7 +546,6 @@ pub mod pallet { // Get the staking ledger and update it let mut ledger = Self::ledger(&staker).ok_or(Error::::UnexpectedState)?; ledger.total = ledger.total.saturating_sub(value_to_unstake); - ledger.active = ledger.active.saturating_sub(value_to_unstake); Self::update_ledger(&staker, &ledger); let current_era = Self::current_era(); @@ -672,10 +678,15 @@ pub mod pallet { // continue and process the next era interval } - // send rewards to stakers - Self::payout_stakers(&rewards_for_stakers_map); - // send rewards to developer + // send rewards to stakers and update reward counter + Self::payout_stakers(&contract_id, &rewards_for_stakers_map); + + // send rewards to developer and update reward counter T::Currency::deposit_into_existing(&developer, reward_for_developer).ok(); + IndividualRewardCounter::::mutate(&contract_id, &developer, |balance| { + *balance += reward_for_developer + }); + // if !unclaimed_rewards.is_zero() { TODO! // T::Currency::deposit_into_existing(&treasury, unclaimed_rewards).ok(); // } @@ -773,7 +784,7 @@ pub mod pallet { /// Update the ledger for a staker. This will also update the stash lock. /// This lock will lock the entire funds except paying for further transactions. fn update_ledger(staker: &T::AccountId, ledger: &StakingLedger>) { - if ledger.active.is_zero() { + if ledger.total.is_zero() { Ledger::::remove(&staker); T::Currency::remove_lock(STAKING_ID, &staker); } else { @@ -811,8 +822,12 @@ pub mod pallet { } /// Execute payout for stakers - fn payout_stakers(staker_map: &BTreeMap>) { + fn payout_stakers( + contract: &SmartContract, + staker_map: &BTreeMap>, + ) { for (s, b) in staker_map { + IndividualRewardCounter::::mutate(contract, s, |balance| *balance += *b); T::Currency::deposit_into_existing(&s, *b).ok(); } } diff --git a/frame/dapps-staking/src/testing_utils.rs b/frame/dapps-staking/src/testing_utils.rs index dbbac6393..f4baee9dc 100644 --- a/frame/dapps-staking/src/testing_utils.rs +++ b/frame/dapps-staking/src/testing_utils.rs @@ -52,7 +52,6 @@ pub(crate) fn verify_ledger(staker_id: AccountId, staked_value: Balance) { // Verify that ledger storage values are as expected. let ledger = Ledger::::get(staker_id).unwrap(); assert_eq!(staked_value, ledger.total); - assert_eq!(staked_value, ledger.active); } /// Used to verify era staking points content. @@ -159,3 +158,23 @@ pub(crate) fn calc_expected_developer_reward( let contract_reward = Perbill::from_rational(contract_stake, era_stake) * era_reward; Perbill::from_percent(DEVELOPER_REWARD_PERCENTAGE) * contract_reward } + +/// Check Balance after reward distribution and check reward counter +pub(crate) fn check_rewards_and_counter( + contract: &SmartContract, + user: &AccountId, + free_balance: mock::Balance, + eras: EraIndex, + expected_era_reward: mock::Balance, +) { + println!("check_rewards_and_counter {:?}, user={:?}", contract, &user); + let total_reward_per_era = expected_era_reward * eras as u128; + assert_eq!( + ::Currency::free_balance(user), + free_balance + total_reward_per_era + ); + assert_eq!( + mock::DappsStaking::reward_counter(contract, user), + total_reward_per_era + ); +} diff --git a/frame/dapps-staking/src/tests.rs b/frame/dapps-staking/src/tests.rs index f617575f5..0ba06668e 100644 --- a/frame/dapps-staking/src/tests.rs +++ b/frame/dapps-staking/src/tests.rs @@ -1154,13 +1154,19 @@ fn claim_one_contract_one_staker() { calc_expected_developer_reward(total_era_dapps_reward, INITIAL_STAKE, INITIAL_STAKE); // check balances to see if the rewards are paid out - assert_eq!( - ::Currency::free_balance(&staker1), - free_balance_staker1 + eras_eligible_for_reward * expected_staker1_reward - ); - assert_eq!( - ::Currency::free_balance(&developer), - free_developer_balance + eras_eligible_for_reward * expected_developer_reward as u128 + check_rewards_and_counter( + &contract, + &staker1, + free_balance_staker1, + eras_eligible_for_reward as u32, + expected_staker1_reward, + ); + check_rewards_and_counter( + &contract, + &developer, + free_developer_balance, + eras_eligible_for_reward as u32, + expected_developer_reward, ); }) } @@ -1219,17 +1225,26 @@ fn claim_one_contract_two_stakers() { // check balances to see if the rewards are paid out let eras_eligible_for_reward = (claim_era - start_era) as u128; - assert_eq!( - ::Currency::free_balance(&staker1), - free_balance_staker1 + eras_eligible_for_reward * expected_staker1_reward - ); - assert_eq!( - ::Currency::free_balance(&staker2), - free_balance_staker2 + eras_eligible_for_reward * expected_staker2_reward - ); - assert_eq!( - ::Currency::free_balance(&developer), - free_developer_balance + eras_eligible_for_reward * expected_developer_reward as u128 + check_rewards_and_counter( + &contract, + &staker1, + free_balance_staker1, + eras_eligible_for_reward as u32, + expected_staker1_reward, + ); + check_rewards_and_counter( + &contract, + &staker2, + free_balance_staker2, + eras_eligible_for_reward as u32, + expected_staker2_reward, + ); + check_rewards_and_counter( + &contract, + &developer, + free_developer_balance, + eras_eligible_for_reward as u32, + expected_developer_reward, ); }) } From 66fcc0f27c84a205c0c86660a2bb687227f4ad7c Mon Sep 17 00:00:00 2001 From: "Mar.io" Date: Fri, 1 Oct 2021 11:03:41 +0200 Subject: [PATCH 2/5] update claim UT --- frame/dapps-staking/src/pallet/mod.rs | 7 +++ frame/dapps-staking/src/tests.rs | 76 ++++++++++++++++++--------- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/frame/dapps-staking/src/pallet/mod.rs b/frame/dapps-staking/src/pallet/mod.rs index 90e1b55f7..305f9e3e3 100644 --- a/frame/dapps-staking/src/pallet/mod.rs +++ b/frame/dapps-staking/src/pallet/mod.rs @@ -829,6 +829,13 @@ pub mod pallet { for (s, b) in staker_map { IndividualRewardCounter::::mutate(contract, s, |balance| *balance += *b); T::Currency::deposit_into_existing(&s, *b).ok(); + println!( + "{:?} s:{:?} b={:?} r={:?}", + contract, + s, + *b, + Self::reward_counter(&contract, s) + ); } } diff --git a/frame/dapps-staking/src/tests.rs b/frame/dapps-staking/src/tests.rs index 0ba06668e..aa5cd4fb5 100644 --- a/frame/dapps-staking/src/tests.rs +++ b/frame/dapps-staking/src/tests.rs @@ -1362,27 +1362,37 @@ fn claim_two_contracts_three_stakers() { let expected_c1_dev1_e2_reward = calc_expected_developer_reward(expected_era_reward, ERA_STAKED2, CONTRACT1_STAKE); - assert_eq!( - ::Currency::free_balance(&staker1), - free_balance_staker1 - + eras_eligible_for_reward1 * expected_c1_staker1_e1_reward - + eras_eligible_for_reward2 * expected_c1_staker1_e2_reward + let expected_c1_staker1_reward_total = eras_eligible_for_reward1 + * expected_c1_staker1_e1_reward + + eras_eligible_for_reward2 * expected_c1_staker1_e2_reward; + check_rewards_and_counter( + &contract1, + &staker1, + free_balance_staker1, + 1 as u32, // use 1 since the multiplication with era is alreday done + expected_c1_staker1_reward_total, ); - // staker2 staked on both contracts. Memorize this reward for staker2 on contract1 - let expected_c1_staker2_reward = eras_eligible_for_reward1 * expected_c1_staker2_e1_reward + let expected_c1_staker2_reward_total = eras_eligible_for_reward1 + * expected_c1_staker2_e1_reward + eras_eligible_for_reward2 * expected_c1_staker2_e2_reward; - - // check balances to see if the rewards are paid out - assert_eq!( - ::Currency::free_balance(&staker2), - free_balance_staker2 + expected_c1_staker2_reward + check_rewards_and_counter( + &contract1, + &staker2, + free_balance_staker2, + 1 as u32, // use 1 since the multiplication with era is alreday done + expected_c1_staker2_reward_total, ); - assert_eq!( - ::Currency::free_balance(&developer1), - free_balance_developer1 - + eras_eligible_for_reward1 * expected_c1_dev1_e1_reward as u128 - + eras_eligible_for_reward2 * expected_c1_dev1_e2_reward as u128 + + let expected_c1_developer1_reward_total = eras_eligible_for_reward1 + * expected_c1_dev1_e1_reward + + eras_eligible_for_reward2 * expected_c1_dev1_e2_reward; + check_rewards_and_counter( + &contract1, + &developer1, + free_balance_developer1, + 1 as u32, // use 1 since the multiplication with era is alreday done + expected_c1_developer1_reward_total, ); // claim rewards for contract2 4 eras later @@ -1419,19 +1429,37 @@ fn claim_two_contracts_three_stakers() { let eras_eligible_for_reward = (claim_era - start_staking_era_for_c2) as u128; // all skipped eras plus era when it was last claimed // check balances to see if the rewards are paid out + let expected_c2_staker2_reward_total = + eras_eligible_for_reward * expected_c2_staker2_e2_reward; assert_eq!( ::Currency::free_balance(&staker2), free_balance_staker2 - + eras_eligible_for_reward * expected_c2_staker2_e2_reward - + expected_c1_staker2_reward + + expected_c2_staker2_reward_total + + expected_c1_staker2_reward_total ); + + // we do not use check_rewards_and_counter() here since + // this counter check is for the contract2 only. + // It does not include reward for the contract1 assert_eq!( - ::Currency::free_balance(&staker3), - free_balance_staker3 + eras_eligible_for_reward * expected_c2_staker3_e2_reward + mock::DappsStaking::reward_counter(contract2, staker2), + expected_c2_staker2_reward_total ); - assert_eq!( - ::Currency::free_balance(&developer2), - free_balance_developer2 + eras_eligible_for_reward * expected_c2_dev2_e2_reward as u128 + + check_rewards_and_counter( + &contract2, + &staker3, + free_balance_staker3, + eras_eligible_for_reward as u32, + expected_c2_staker3_e2_reward, + ); + + check_rewards_and_counter( + &contract2, + &developer2, + free_balance_developer2, + eras_eligible_for_reward as u32, + expected_c2_dev2_e2_reward, ); }) } From 3a17b6e602077c92fe55783a74f839f37048f4ef Mon Sep 17 00:00:00 2001 From: "Mar.io" Date: Fri, 1 Oct 2021 13:08:18 +0200 Subject: [PATCH 3/5] added counter for rewards paid out to contract --- frame/dapps-staking/src/lib.rs | 1 + frame/dapps-staking/src/pallet/mod.rs | 24 +++++++++++++----------- frame/dapps-staking/src/testing_utils.rs | 13 +++++++++++++ frame/dapps-staking/src/tests.rs | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/frame/dapps-staking/src/lib.rs b/frame/dapps-staking/src/lib.rs index 4cc69586b..fb8b7d573 100644 --- a/frame/dapps-staking/src/lib.rs +++ b/frame/dapps-staking/src/lib.rs @@ -72,6 +72,7 @@ pub struct EraStakingPoints { /// Era when this contract was staked last time before this one. /// In case only a single staking era exists, it will be set to that one. This indicates the final element in the chain. former_staked_era: EraIndex, + paidout_rewards: Balance, } /// Multi-VM pointer to smart contract instance. diff --git a/frame/dapps-staking/src/pallet/mod.rs b/frame/dapps-staking/src/pallet/mod.rs index 305f9e3e3..989905b13 100644 --- a/frame/dapps-staking/src/pallet/mod.rs +++ b/frame/dapps-staking/src/pallet/mod.rs @@ -412,6 +412,7 @@ pub mod pallet { total: Zero::zero(), stakers: BTreeMap::>::new(), former_staked_era: 0 as EraIndex, + paidout_rewards: BalanceOf::::default(), } }; @@ -678,15 +679,18 @@ pub mod pallet { // continue and process the next era interval } - // send rewards to stakers and update reward counter - Self::payout_stakers(&contract_id, &rewards_for_stakers_map); + // send rewards to stakers' accounts and update reward counter individual staker + let reward_for_stakers = Self::payout_stakers(&contract_id, &rewards_for_stakers_map); - // send rewards to developer and update reward counter + // send rewards to developer's account and update reward counter for developer's account T::Currency::deposit_into_existing(&developer, reward_for_developer).ok(); IndividualRewardCounter::::mutate(&contract_id, &developer, |balance| { *balance += reward_for_developer }); + // updated counter for total rewards paid to the contract + contract_staking_info.paidout_rewards += reward_for_stakers + reward_for_developer; + // if !unclaimed_rewards.is_zero() { TODO! // T::Currency::deposit_into_existing(&treasury, unclaimed_rewards).ok(); // } @@ -825,18 +829,16 @@ pub mod pallet { fn payout_stakers( contract: &SmartContract, staker_map: &BTreeMap>, - ) { + ) -> BalanceOf { + let mut reward_for_stakers = Zero::zero(); + for (s, b) in staker_map { IndividualRewardCounter::::mutate(contract, s, |balance| *balance += *b); T::Currency::deposit_into_existing(&s, *b).ok(); - println!( - "{:?} s:{:?} b={:?} r={:?}", - contract, - s, - *b, - Self::reward_counter(&contract, s) - ); + reward_for_stakers += *b; } + + reward_for_stakers } /// The block rewards are accumulated on the pallets's account during an era. diff --git a/frame/dapps-staking/src/testing_utils.rs b/frame/dapps-staking/src/testing_utils.rs index f4baee9dc..1aff41c1a 100644 --- a/frame/dapps-staking/src/testing_utils.rs +++ b/frame/dapps-staking/src/testing_utils.rs @@ -178,3 +178,16 @@ pub(crate) fn check_rewards_and_counter( total_reward_per_era ); } + +pub(crate) fn check_paidout_rewards_for_contract( + contract: &SmartContract, + expected_contract_reward: mock::Balance, +) { + let era_last_claimed = mock::DappsStaking::contract_last_claimed(contract).unwrap_or(0); + let contract_staking_info = + mock::DappsStaking::contract_era_stake(contract, era_last_claimed).unwrap_or_default(); + assert_eq!( + contract_staking_info.paidout_rewards, + expected_contract_reward + ) +} diff --git a/frame/dapps-staking/src/tests.rs b/frame/dapps-staking/src/tests.rs index aa5cd4fb5..b9a532b38 100644 --- a/frame/dapps-staking/src/tests.rs +++ b/frame/dapps-staking/src/tests.rs @@ -1168,6 +1168,9 @@ fn claim_one_contract_one_staker() { eras_eligible_for_reward as u32, expected_developer_reward, ); + let expected_contract_reward = + eras_eligible_for_reward * (expected_staker1_reward + expected_developer_reward); + check_paidout_rewards_for_contract(&contract, expected_contract_reward); }) } @@ -1246,6 +1249,9 @@ fn claim_one_contract_two_stakers() { eras_eligible_for_reward as u32, expected_developer_reward, ); + let expected_contract_reward = eras_eligible_for_reward + * (expected_staker1_reward + expected_staker2_reward + expected_developer_reward); + check_paidout_rewards_for_contract(&contract, expected_contract_reward); }) } @@ -1394,6 +1400,10 @@ fn claim_two_contracts_three_stakers() { 1 as u32, // use 1 since the multiplication with era is alreday done expected_c1_developer1_reward_total, ); + let expected_contract1_reward = expected_c1_staker1_reward_total + + expected_c1_staker2_reward_total + + expected_c1_developer1_reward_total; + check_paidout_rewards_for_contract(&contract1, expected_contract1_reward); // claim rewards for contract2 4 eras later // era=11 @@ -1461,5 +1471,9 @@ fn claim_two_contracts_three_stakers() { eras_eligible_for_reward as u32, expected_c2_dev2_e2_reward, ); + let expected_contract2_reward = eras_eligible_for_reward + * (expected_c2_staker3_e2_reward + expected_c2_dev2_e2_reward) + + expected_c2_staker2_reward_total; + check_paidout_rewards_for_contract(&contract2, expected_contract2_reward); }) } From f5f4f8c95bc418cf8f5031dc057c8053f4f8a9a7 Mon Sep 17 00:00:00 2001 From: "Mar.io" Date: Fri, 1 Oct 2021 17:28:06 +0200 Subject: [PATCH 4/5] review rework --- frame/dapps-staking/src/lib.rs | 11 ++---- frame/dapps-staking/src/pallet/mod.rs | 39 +++++++++++---------- frame/dapps-staking/src/testing_utils.rs | 13 +++---- frame/dapps-staking/src/tests.rs | 44 ++++++++++++------------ 4 files changed, 51 insertions(+), 56 deletions(-) diff --git a/frame/dapps-staking/src/lib.rs b/frame/dapps-staking/src/lib.rs index fb8b7d573..927701ee3 100644 --- a/frame/dapps-staking/src/lib.rs +++ b/frame/dapps-staking/src/lib.rs @@ -72,7 +72,8 @@ pub struct EraStakingPoints { /// Era when this contract was staked last time before this one. /// In case only a single staking era exists, it will be set to that one. This indicates the final element in the chain. former_staked_era: EraIndex, - paidout_rewards: Balance, + /// Accrued and claimed rewards on this contract both for stakers and the developer + claimed_rewards: Balance, } /// Multi-VM pointer to smart contract instance. @@ -83,11 +84,3 @@ pub enum SmartContract { /// Wasm smart contract instance. Wasm(AccountId), } - -/// The ledger of a (bonded) stash. -#[derive(PartialEq, Eq, Clone, Encode, Decode, Default, RuntimeDebug)] -pub struct StakingLedger { - /// The total amount of the staker's balance that we are currently accounting for. - #[codec(compact)] - pub total: Balance, -} diff --git a/frame/dapps-staking/src/pallet/mod.rs b/frame/dapps-staking/src/pallet/mod.rs index 989905b13..c54d932ca 100644 --- a/frame/dapps-staking/src/pallet/mod.rs +++ b/frame/dapps-staking/src/pallet/mod.rs @@ -78,8 +78,7 @@ pub mod pallet { /// Map from all (unlocked) "controller" accounts to the info regarding the staking. #[pallet::storage] #[pallet::getter(fn ledger)] - pub(crate) type Ledger = - StorageMap<_, Blake2_128Concat, T::AccountId, StakingLedger>>; + pub(crate) type Ledger = StorageMap<_, Blake2_128Concat, T::AccountId, BalanceOf>; /// Number of eras to keep in history. /// @@ -127,8 +126,8 @@ pub mod pallet { /// Reward counter for individual stakers and the developer #[pallet::storage] - #[pallet::getter(fn reward_counter)] - pub(crate) type IndividualRewardCounter = StorageDoubleMap< + #[pallet::getter(fn rewards_claimed)] + pub(crate) type RewardsClaimed = StorageDoubleMap< _, Twox64Concat, SmartContract, @@ -393,12 +392,12 @@ pub mod pallet { // Ensure that staker has enough balance to bond & stake. let free_balance = T::Currency::free_balance(&staker); // Remove already locked funds from the free balance - let available_balance = free_balance.saturating_sub(ledger.total); + let available_balance = free_balance.saturating_sub(ledger); let value_to_stake = value.min(available_balance); ensure!(!value_to_stake.is_zero(), Error::::StakingWithNoValue); // update the ledger value by adding the newly bonded funds - ledger.total += value_to_stake; + ledger += value_to_stake; // Get the latest era staking point info or create it if contract hasn't been staked yet so far. let era_when_contract_last_staked = Self::contract_last_staked(&contract_id); @@ -412,7 +411,7 @@ pub mod pallet { total: Zero::zero(), stakers: BTreeMap::>::new(), former_staked_era: 0 as EraIndex, - paidout_rewards: BalanceOf::::default(), + claimed_rewards: BalanceOf::::default(), } }; @@ -534,7 +533,7 @@ pub mod pallet { era_staking_points.stakers.remove(&staker); value_to_unstake = staked_value; // remove reward counter - IndividualRewardCounter::::remove(&contract_id, &staker); + RewardsClaimed::::remove(&contract_id, &staker); } else { era_staking_points .stakers @@ -546,7 +545,7 @@ pub mod pallet { // Get the staking ledger and update it let mut ledger = Self::ledger(&staker).ok_or(Error::::UnexpectedState)?; - ledger.total = ledger.total.saturating_sub(value_to_unstake); + ledger = ledger.saturating_sub(value_to_unstake); Self::update_ledger(&staker, &ledger); let current_era = Self::current_era(); @@ -680,16 +679,17 @@ pub mod pallet { } // send rewards to stakers' accounts and update reward counter individual staker - let reward_for_stakers = Self::payout_stakers(&contract_id, &rewards_for_stakers_map); + let reward_for_stakers = + Self::payout_stakers_and_get_total_reward(&contract_id, &rewards_for_stakers_map); // send rewards to developer's account and update reward counter for developer's account T::Currency::deposit_into_existing(&developer, reward_for_developer).ok(); - IndividualRewardCounter::::mutate(&contract_id, &developer, |balance| { + RewardsClaimed::::mutate(&contract_id, &developer, |balance| { *balance += reward_for_developer }); // updated counter for total rewards paid to the contract - contract_staking_info.paidout_rewards += reward_for_stakers + reward_for_developer; + contract_staking_info.claimed_rewards += reward_for_stakers + reward_for_developer; // if !unclaimed_rewards.is_zero() { TODO! // T::Currency::deposit_into_existing(&treasury, unclaimed_rewards).ok(); @@ -787,12 +787,12 @@ pub mod pallet { impl Pallet { /// Update the ledger for a staker. This will also update the stash lock. /// This lock will lock the entire funds except paying for further transactions. - fn update_ledger(staker: &T::AccountId, ledger: &StakingLedger>) { - if ledger.total.is_zero() { + fn update_ledger(staker: &T::AccountId, ledger: &BalanceOf) { + if ledger.is_zero() { Ledger::::remove(&staker); T::Currency::remove_lock(STAKING_ID, &staker); } else { - T::Currency::set_lock(STAKING_ID, &staker, ledger.total, WithdrawReasons::all()); + T::Currency::set_lock(STAKING_ID, &staker, ledger.clone(), WithdrawReasons::all()); Ledger::::insert(staker, ledger); } } @@ -825,15 +825,16 @@ pub mod pallet { } } - /// Execute payout for stakers - fn payout_stakers( + /// Execute payout for stakers. + /// Return total rewards claimed by stakers on this contract. + fn payout_stakers_and_get_total_reward( contract: &SmartContract, staker_map: &BTreeMap>, ) -> BalanceOf { let mut reward_for_stakers = Zero::zero(); for (s, b) in staker_map { - IndividualRewardCounter::::mutate(contract, s, |balance| *balance += *b); + RewardsClaimed::::mutate(contract, s, |balance| *balance += *b); T::Currency::deposit_into_existing(&s, *b).ok(); reward_for_stakers += *b; } @@ -842,7 +843,7 @@ pub mod pallet { } /// The block rewards are accumulated on the pallets's account during an era. - /// This function takes a snapshot of the pallet's balance accured during current era + /// This function takes a snapshot of the pallet's balance accrued during current era /// and stores it for future distribution /// /// This is called just at the beginning of an era. diff --git a/frame/dapps-staking/src/testing_utils.rs b/frame/dapps-staking/src/testing_utils.rs index 1aff41c1a..231fbd20e 100644 --- a/frame/dapps-staking/src/testing_utils.rs +++ b/frame/dapps-staking/src/testing_utils.rs @@ -51,7 +51,7 @@ pub(crate) fn unbond_unstake_and_withdraw_with_verification( pub(crate) fn verify_ledger(staker_id: AccountId, staked_value: Balance) { // Verify that ledger storage values are as expected. let ledger = Ledger::::get(staker_id).unwrap(); - assert_eq!(staked_value, ledger.total); + assert_eq!(staked_value, ledger); } /// Used to verify era staking points content. @@ -159,26 +159,27 @@ pub(crate) fn calc_expected_developer_reward( Perbill::from_percent(DEVELOPER_REWARD_PERCENTAGE) * contract_reward } -/// Check Balance after reward distribution and check reward counter -pub(crate) fn check_rewards_and_counter( +/// Check staker/dev Balance after reward distribution. +/// Check that claimed rewards for staker/dev are updated. +pub(crate) fn check_rewards_on_balance_and_storage( contract: &SmartContract, user: &AccountId, free_balance: mock::Balance, eras: EraIndex, expected_era_reward: mock::Balance, ) { - println!("check_rewards_and_counter {:?}, user={:?}", contract, &user); let total_reward_per_era = expected_era_reward * eras as u128; assert_eq!( ::Currency::free_balance(user), free_balance + total_reward_per_era ); assert_eq!( - mock::DappsStaking::reward_counter(contract, user), + mock::DappsStaking::rewards_claimed(contract, user), total_reward_per_era ); } +/// Check that claimed rewards on this contract are updated pub(crate) fn check_paidout_rewards_for_contract( contract: &SmartContract, expected_contract_reward: mock::Balance, @@ -187,7 +188,7 @@ pub(crate) fn check_paidout_rewards_for_contract( let contract_staking_info = mock::DappsStaking::contract_era_stake(contract, era_last_claimed).unwrap_or_default(); assert_eq!( - contract_staking_info.paidout_rewards, + contract_staking_info.claimed_rewards, expected_contract_reward ) } diff --git a/frame/dapps-staking/src/tests.rs b/frame/dapps-staking/src/tests.rs index b9a532b38..b64a19241 100644 --- a/frame/dapps-staking/src/tests.rs +++ b/frame/dapps-staking/src/tests.rs @@ -1154,18 +1154,18 @@ fn claim_one_contract_one_staker() { calc_expected_developer_reward(total_era_dapps_reward, INITIAL_STAKE, INITIAL_STAKE); // check balances to see if the rewards are paid out - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract, &staker1, free_balance_staker1, - eras_eligible_for_reward as u32, + eras_eligible_for_reward as EraIndex, expected_staker1_reward, ); - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract, &developer, free_developer_balance, - eras_eligible_for_reward as u32, + eras_eligible_for_reward as EraIndex, expected_developer_reward, ); let expected_contract_reward = @@ -1228,25 +1228,25 @@ fn claim_one_contract_two_stakers() { // check balances to see if the rewards are paid out let eras_eligible_for_reward = (claim_era - start_era) as u128; - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract, &staker1, free_balance_staker1, - eras_eligible_for_reward as u32, + eras_eligible_for_reward as EraIndex, expected_staker1_reward, ); - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract, &staker2, free_balance_staker2, - eras_eligible_for_reward as u32, + eras_eligible_for_reward as EraIndex, expected_staker2_reward, ); - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract, &developer, free_developer_balance, - eras_eligible_for_reward as u32, + eras_eligible_for_reward as EraIndex, expected_developer_reward, ); let expected_contract_reward = eras_eligible_for_reward @@ -1371,33 +1371,33 @@ fn claim_two_contracts_three_stakers() { let expected_c1_staker1_reward_total = eras_eligible_for_reward1 * expected_c1_staker1_e1_reward + eras_eligible_for_reward2 * expected_c1_staker1_e2_reward; - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract1, &staker1, free_balance_staker1, - 1 as u32, // use 1 since the multiplication with era is alreday done + 1 as EraIndex, // use 1 since the multiplication with era is alreday done expected_c1_staker1_reward_total, ); // staker2 staked on both contracts. Memorize this reward for staker2 on contract1 let expected_c1_staker2_reward_total = eras_eligible_for_reward1 * expected_c1_staker2_e1_reward + eras_eligible_for_reward2 * expected_c1_staker2_e2_reward; - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract1, &staker2, free_balance_staker2, - 1 as u32, // use 1 since the multiplication with era is alreday done + 1 as EraIndex, // use 1 since the multiplication with era is alreday done expected_c1_staker2_reward_total, ); let expected_c1_developer1_reward_total = eras_eligible_for_reward1 * expected_c1_dev1_e1_reward + eras_eligible_for_reward2 * expected_c1_dev1_e2_reward; - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract1, &developer1, free_balance_developer1, - 1 as u32, // use 1 since the multiplication with era is alreday done + 1 as EraIndex, // use 1 since the multiplication with era is alreday done expected_c1_developer1_reward_total, ); let expected_contract1_reward = expected_c1_staker1_reward_total @@ -1448,27 +1448,27 @@ fn claim_two_contracts_three_stakers() { + expected_c1_staker2_reward_total ); - // we do not use check_rewards_and_counter() here since + // we do not use check_rewards_on_balance_and_storage() here since // this counter check is for the contract2 only. // It does not include reward for the contract1 assert_eq!( - mock::DappsStaking::reward_counter(contract2, staker2), + mock::DappsStaking::rewards_claimed(contract2, staker2), expected_c2_staker2_reward_total ); - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract2, &staker3, free_balance_staker3, - eras_eligible_for_reward as u32, + eras_eligible_for_reward as EraIndex, expected_c2_staker3_e2_reward, ); - check_rewards_and_counter( + check_rewards_on_balance_and_storage( &contract2, &developer2, free_balance_developer2, - eras_eligible_for_reward as u32, + eras_eligible_for_reward as EraIndex, expected_c2_dev2_e2_reward, ); let expected_contract2_reward = eras_eligible_for_reward From c373a20a5845e90558758e95b3aab04db69703fc Mon Sep 17 00:00:00 2001 From: "Mar.io" Date: Fri, 1 Oct 2021 17:28:59 +0200 Subject: [PATCH 5/5] review rework2 --- frame/dapps-staking/src/pallet/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/dapps-staking/src/pallet/mod.rs b/frame/dapps-staking/src/pallet/mod.rs index c54d932ca..be970115d 100644 --- a/frame/dapps-staking/src/pallet/mod.rs +++ b/frame/dapps-staking/src/pallet/mod.rs @@ -75,10 +75,10 @@ pub mod pallet { 84u32 } - /// Map from all (unlocked) "controller" accounts to the info regarding the staking. + /// Bonded amount for the staker #[pallet::storage] #[pallet::getter(fn ledger)] - pub(crate) type Ledger = StorageMap<_, Blake2_128Concat, T::AccountId, BalanceOf>; + pub(crate) type Ledger = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf>; /// Number of eras to keep in history. ///