mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 11:07:56 +00:00
Remove pre-simple-payout code from staking (#6253)
* Remove some dead code * fix * Kill warnings
This commit is contained in:
@@ -928,19 +928,20 @@ impl Default for Forcing {
|
||||
fn default() -> Self { Forcing::NotForcing }
|
||||
}
|
||||
|
||||
// A value placed in storage that represents the current version of the Staking storage.
|
||||
// This value is used by the `on_runtime_upgrade` logic to determine whether we run
|
||||
// storage migration logic. This should match directly with the semantic versions of the Rust crate.
|
||||
// A value placed in storage that represents the current version of the Staking storage. This value
|
||||
// is used by the `on_runtime_upgrade` logic to determine whether we run storage migration logic.
|
||||
// This should match directly with the semantic versions of the Rust crate.
|
||||
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)]
|
||||
enum Releases {
|
||||
V1_0_0Ancient,
|
||||
V2_0_0,
|
||||
V3_0_0,
|
||||
V4_0_0,
|
||||
}
|
||||
|
||||
impl Default for Releases {
|
||||
fn default() -> Self {
|
||||
Releases::V3_0_0
|
||||
Releases::V4_0_0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1126,10 +1127,7 @@ decl_storage! {
|
||||
/// Storage version of the pallet.
|
||||
///
|
||||
/// This is set to v3.0.0 for new networks.
|
||||
StorageVersion build(|_: &GenesisConfig<T>| Releases::V3_0_0): Releases;
|
||||
|
||||
/// The era where we migrated from Lazy Payouts to Simple Payouts
|
||||
MigrateEra: Option<EraIndex>;
|
||||
StorageVersion build(|_: &GenesisConfig<T>| Releases::V4_0_0): Releases;
|
||||
}
|
||||
add_extra_genesis {
|
||||
config(stakers):
|
||||
@@ -1277,6 +1275,28 @@ decl_module! {
|
||||
|
||||
fn deposit_event() = default;
|
||||
|
||||
fn on_runtime_upgrade() -> Weight {
|
||||
#[allow(dead_code)]
|
||||
mod inner {
|
||||
pub struct Module<T>(sp_std::marker::PhantomData<T>);
|
||||
frame_support::decl_storage! {
|
||||
trait Store for Module<T: super::Trait> as Staking {
|
||||
pub MigrateEra: Option<super::EraIndex>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Releases::V3_0_0 = StorageVersion::get() {
|
||||
StorageVersion::put(Releases::V4_0_0);
|
||||
inner::MigrateEra::kill();
|
||||
|
||||
T::DbWeight::get().reads_writes(1, 1)
|
||||
} else {
|
||||
T::DbWeight::get().reads(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// sets `ElectionStatus` to `Open(now)` where `now` is the block number at which the
|
||||
/// election window has opened, if we are at the last session and less blocks than
|
||||
/// `T::ElectionLookahead` is remaining until the next new session schedule. The offchain
|
||||
@@ -1901,69 +1921,6 @@ decl_module! {
|
||||
<Self as Store>::UnappliedSlashes::insert(&era, &unapplied);
|
||||
}
|
||||
|
||||
/// **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving
|
||||
/// opportunity for users to claim all rewards before moving to Simple Payouts. After this
|
||||
/// time, you should use `payout_stakers` instead.**
|
||||
///
|
||||
/// Make one nominator's payout for one era.
|
||||
///
|
||||
/// - `who` is the controller account of the nominator to pay out.
|
||||
/// - `era` may not be lower than one following the most recently paid era. If it is higher,
|
||||
/// then it indicates an instruction to skip the payout of all previous eras.
|
||||
/// - `validators` is the list of all validators that `who` had exposure to during `era`,
|
||||
/// alongside the index of `who` in the clipped exposure of the validator.
|
||||
/// I.e. each element is a tuple of
|
||||
/// `(validator, index of `who` in clipped exposure of validator)`.
|
||||
/// If it is incomplete, then less than the full reward will be paid out.
|
||||
/// It must not exceed `MAX_NOMINATIONS`.
|
||||
///
|
||||
/// WARNING: once an era is payed for a validator such validator can't claim the payout of
|
||||
/// previous era.
|
||||
///
|
||||
/// WARNING: Incorrect arguments here can result in loss of payout. Be very careful.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Number of storage read of `O(validators)`; `validators` is the argument of the call,
|
||||
/// and is bounded by `MAX_NOMINATIONS`.
|
||||
/// - Each storage read is `O(N)` size and decode complexity; `N` is the maximum
|
||||
/// nominations that can be given to a single validator.
|
||||
/// - Computation complexity: `O(MAX_NOMINATIONS * logN)`; `MAX_NOMINATIONS` is the
|
||||
/// maximum number of validators that may be nominated by a single nominator, it is
|
||||
/// bounded only economically (all nominators are required to place a minimum stake).
|
||||
/// # </weight>
|
||||
#[weight = 500_000_000]
|
||||
fn payout_nominator(origin, era: EraIndex, validators: Vec<(T::AccountId, u32)>)
|
||||
-> DispatchResult
|
||||
{
|
||||
let ctrl = ensure_signed(origin)?;
|
||||
Self::do_payout_nominator(ctrl, era, validators)
|
||||
}
|
||||
|
||||
/// **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving
|
||||
/// opportunity for users to claim all rewards before moving to Simple Payouts. After this
|
||||
/// time, you should use `payout_stakers` instead.**
|
||||
///
|
||||
/// Make one validator's payout for one era.
|
||||
///
|
||||
/// - `who` is the controller account of the validator to pay out.
|
||||
/// - `era` may not be lower than one following the most recently paid era. If it is higher,
|
||||
/// then it indicates an instruction to skip the payout of all previous eras.
|
||||
///
|
||||
/// WARNING: once an era is payed for a validator such validator can't claim the payout of
|
||||
/// previous era.
|
||||
///
|
||||
/// WARNING: Incorrect arguments here can result in loss of payout. Be very careful.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Time complexity: O(1).
|
||||
/// - Contains a limited number of reads and writes.
|
||||
/// # </weight>
|
||||
#[weight = 500_000_000]
|
||||
fn payout_validator(origin, era: EraIndex) -> DispatchResult {
|
||||
let ctrl = ensure_signed(origin)?;
|
||||
Self::do_payout_validator(ctrl, era)
|
||||
}
|
||||
|
||||
/// Pay out all the stakers behind a single validator for a single era.
|
||||
///
|
||||
/// - `validator_stash` is the stash account of the validator. Their nominators, up to
|
||||
@@ -1982,16 +1939,15 @@ decl_module! {
|
||||
/// N is the Number of payouts for the validator (including the validator)
|
||||
/// Base Weight: 110 + 54.2 * N µs (Median Slopes)
|
||||
/// DB Weight:
|
||||
/// - Read: EraElectionStatus, CurrentEra, HistoryDepth, MigrateEra, ErasValidatorReward,
|
||||
/// - Read: EraElectionStatus, CurrentEra, HistoryDepth, ErasValidatorReward,
|
||||
/// ErasStakersClipped, ErasRewardPoints, ErasValidatorPrefs (8 items)
|
||||
/// - Read Each: Bonded, Ledger, Payee, Locks, System Account (5 items)
|
||||
/// - Write Each: System Account, Locks, Ledger (3 items)
|
||||
// TODO: Remove read on Migrate Era
|
||||
/// # </weight>
|
||||
#[weight =
|
||||
110 * WEIGHT_PER_MICROS
|
||||
+ 54 * WEIGHT_PER_MICROS * Weight::from(T::MaxNominatorRewardedPerValidator::get())
|
||||
+ T::DbWeight::get().reads(8)
|
||||
+ T::DbWeight::get().reads(7)
|
||||
+ T::DbWeight::get().reads(5) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1)
|
||||
+ T::DbWeight::get().writes(3) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1)
|
||||
]
|
||||
@@ -2273,143 +2229,6 @@ impl<T: Trait> Module<T> {
|
||||
<SnapshotNominators<T>>::kill();
|
||||
}
|
||||
|
||||
fn do_payout_nominator(ctrl: T::AccountId, era: EraIndex, validators: Vec<(T::AccountId, u32)>)
|
||||
-> DispatchResult
|
||||
{
|
||||
// validators len must not exceed `MAX_NOMINATIONS` to avoid querying more validator
|
||||
// exposure than necessary.
|
||||
if validators.len() > MAX_NOMINATIONS {
|
||||
return Err(Error::<T>::InvalidNumberOfNominations.into());
|
||||
}
|
||||
// If migrate_era is not populated, then you should use `payout_stakers`
|
||||
let migrate_era = MigrateEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
|
||||
// This payout mechanism will only work for eras before the migration.
|
||||
// Subsequent payouts should use `payout_stakers`.
|
||||
ensure!(era < migrate_era, Error::<T>::InvalidEraToReward);
|
||||
let current_era = CurrentEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
|
||||
ensure!(era <= current_era, Error::<T>::InvalidEraToReward);
|
||||
let history_depth = Self::history_depth();
|
||||
ensure!(era >= current_era.saturating_sub(history_depth), Error::<T>::InvalidEraToReward);
|
||||
|
||||
// Note: if era has no reward to be claimed, era may be future. better not to update
|
||||
// `nominator_ledger.last_reward` in this case.
|
||||
let era_payout = <ErasValidatorReward<T>>::get(&era)
|
||||
.ok_or_else(|| Error::<T>::InvalidEraToReward)?;
|
||||
|
||||
let mut nominator_ledger = <Ledger<T>>::get(&ctrl).ok_or_else(|| Error::<T>::NotController)?;
|
||||
|
||||
ensure!(
|
||||
Self::era_election_status().is_closed() || Self::payee(&nominator_ledger.stash) != RewardDestination::Staked,
|
||||
Error::<T>::CallNotAllowed,
|
||||
);
|
||||
|
||||
nominator_ledger.claimed_rewards.retain(|&x| x >= current_era.saturating_sub(history_depth));
|
||||
match nominator_ledger.claimed_rewards.binary_search(&era) {
|
||||
Ok(_) => Err(Error::<T>::AlreadyClaimed)?,
|
||||
Err(pos) => nominator_ledger.claimed_rewards.insert(pos, era),
|
||||
}
|
||||
|
||||
<Ledger<T>>::insert(&ctrl, &nominator_ledger);
|
||||
|
||||
let mut reward = Perbill::zero();
|
||||
let era_reward_points = <ErasRewardPoints<T>>::get(&era);
|
||||
|
||||
for (validator, nominator_index) in validators.into_iter() {
|
||||
let commission = Self::eras_validator_prefs(&era, &validator).commission;
|
||||
let validator_exposure = <ErasStakersClipped<T>>::get(&era, &validator);
|
||||
|
||||
if let Some(nominator_exposure) = validator_exposure.others
|
||||
.get(nominator_index as usize)
|
||||
{
|
||||
if nominator_exposure.who != nominator_ledger.stash {
|
||||
continue;
|
||||
}
|
||||
|
||||
let nominator_exposure_part = Perbill::from_rational_approximation(
|
||||
nominator_exposure.value,
|
||||
validator_exposure.total,
|
||||
);
|
||||
let validator_point = era_reward_points.individual.get(&validator)
|
||||
.map(|points| *points)
|
||||
.unwrap_or_else(|| Zero::zero());
|
||||
let validator_point_part = Perbill::from_rational_approximation(
|
||||
validator_point,
|
||||
era_reward_points.total,
|
||||
);
|
||||
reward = reward.saturating_add(
|
||||
validator_point_part
|
||||
.saturating_mul(Perbill::one().saturating_sub(commission))
|
||||
.saturating_mul(nominator_exposure_part)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(imbalance) = Self::make_payout(&nominator_ledger.stash, reward * era_payout) {
|
||||
Self::deposit_event(RawEvent::Reward(ctrl, imbalance.peek()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_payout_validator(ctrl: T::AccountId, era: EraIndex) -> DispatchResult {
|
||||
// If migrate_era is not populated, then you should use `payout_stakers`
|
||||
let migrate_era = MigrateEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
|
||||
// This payout mechanism will only work for eras before the migration.
|
||||
// Subsequent payouts should use `payout_stakers`.
|
||||
ensure!(era < migrate_era, Error::<T>::InvalidEraToReward);
|
||||
let current_era = CurrentEra::get().ok_or(Error::<T>::InvalidEraToReward)?;
|
||||
ensure!(era <= current_era, Error::<T>::InvalidEraToReward);
|
||||
let history_depth = Self::history_depth();
|
||||
ensure!(era >= current_era.saturating_sub(history_depth), Error::<T>::InvalidEraToReward);
|
||||
|
||||
// Note: if era has no reward to be claimed, era may be future. better not to update
|
||||
// `ledger.last_reward` in this case.
|
||||
let era_payout = <ErasValidatorReward<T>>::get(&era)
|
||||
.ok_or_else(|| Error::<T>::InvalidEraToReward)?;
|
||||
|
||||
let mut ledger = <Ledger<T>>::get(&ctrl).ok_or_else(|| Error::<T>::NotController)?;
|
||||
|
||||
ensure!(
|
||||
Self::era_election_status().is_closed() || Self::payee(&ledger.stash) != RewardDestination::Staked,
|
||||
Error::<T>::CallNotAllowed,
|
||||
);
|
||||
|
||||
ledger.claimed_rewards.retain(|&x| x >= current_era.saturating_sub(history_depth));
|
||||
match ledger.claimed_rewards.binary_search(&era) {
|
||||
Ok(_) => Err(Error::<T>::AlreadyClaimed)?,
|
||||
Err(pos) => ledger.claimed_rewards.insert(pos, era),
|
||||
}
|
||||
|
||||
<Ledger<T>>::insert(&ctrl, &ledger);
|
||||
|
||||
let era_reward_points = <ErasRewardPoints<T>>::get(&era);
|
||||
let commission = Self::eras_validator_prefs(&era, &ledger.stash).commission;
|
||||
let exposure = <ErasStakersClipped<T>>::get(&era, &ledger.stash);
|
||||
|
||||
let exposure_part = Perbill::from_rational_approximation(
|
||||
exposure.own,
|
||||
exposure.total,
|
||||
);
|
||||
let validator_point = era_reward_points.individual.get(&ledger.stash)
|
||||
.map(|points| *points)
|
||||
.unwrap_or_else(|| Zero::zero());
|
||||
let validator_point_part = Perbill::from_rational_approximation(
|
||||
validator_point,
|
||||
era_reward_points.total,
|
||||
);
|
||||
let reward = validator_point_part.saturating_mul(
|
||||
commission.saturating_add(
|
||||
Perbill::one().saturating_sub(commission).saturating_mul(exposure_part)
|
||||
)
|
||||
);
|
||||
|
||||
if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) {
|
||||
Self::deposit_event(RawEvent::Reward(ctrl, imbalance.peek()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_payout_stakers(
|
||||
validator_stash: T::AccountId,
|
||||
era: EraIndex,
|
||||
@@ -2420,13 +2239,6 @@ impl<T: Trait> Module<T> {
|
||||
let history_depth = Self::history_depth();
|
||||
ensure!(era >= current_era.saturating_sub(history_depth), Error::<T>::InvalidEraToReward);
|
||||
|
||||
// If there was no migration, then this function is always valid.
|
||||
if let Some(migrate_era) = MigrateEra::get() {
|
||||
// This payout mechanism will only work for eras on and after the migration.
|
||||
// Payouts before then should use `payout_nominator`/`payout_validator`.
|
||||
ensure!(migrate_era <= era, Error::<T>::InvalidEraToReward);
|
||||
}
|
||||
|
||||
// Note: if era has no reward to be claimed, era may be future. better not to update
|
||||
// `ledger.claimed_rewards` in this case.
|
||||
let era_payout = <ErasValidatorReward<T>>::get(&era)
|
||||
@@ -3148,11 +2960,11 @@ impl<T: Trait> Module<T> {
|
||||
/// - after a `withdraw_unbond()` call that frees all of a stash's bonded balance.
|
||||
/// - through `reap_stash()` if the balance has fallen to zero (through slashing).
|
||||
fn kill_stash(stash: &T::AccountId, num_slashing_spans: u32) -> DispatchResult {
|
||||
let controller = Bonded::<T>::get(stash).ok_or(Error::<T>::NotStash)?;
|
||||
let controller = <Bonded<T>>::get(stash).ok_or(Error::<T>::NotStash)?;
|
||||
|
||||
slashing::clear_stash_metadata::<T>(stash, num_slashing_spans)?;
|
||||
|
||||
Bonded::<T>::remove(stash);
|
||||
<Bonded<T>>::remove(stash);
|
||||
<Ledger<T>>::remove(&controller);
|
||||
|
||||
<Payee<T>>::remove(stash);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
//! Test utilities
|
||||
|
||||
use std::{collections::{HashSet, HashMap}, cell::RefCell};
|
||||
use std::{collections::HashSet, cell::RefCell};
|
||||
use sp_runtime::Perbill;
|
||||
use sp_runtime::curve::PiecewiseLinear;
|
||||
use sp_runtime::traits::{IdentityLookup, Convert, SaturatedConversion, Zero};
|
||||
@@ -980,38 +980,6 @@ pub(crate) fn prepare_submission_with(
|
||||
(compact, winners, score)
|
||||
}
|
||||
|
||||
/// Make all validator and nominator request their payment
|
||||
pub(crate) fn make_all_reward_payment_before_migration(era: EraIndex) {
|
||||
let validators_with_reward = ErasRewardPoints::<Test>::get(era).individual.keys()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// reward nominators
|
||||
let mut nominator_controllers = HashMap::new();
|
||||
for validator in Staking::eras_reward_points(era).individual.keys() {
|
||||
let validator_exposure = Staking::eras_stakers_clipped(era, validator);
|
||||
for (nom_index, nom) in validator_exposure.others.iter().enumerate() {
|
||||
if let Some(nom_ctrl) = Staking::bonded(nom.who) {
|
||||
nominator_controllers.entry(nom_ctrl)
|
||||
.or_insert(vec![])
|
||||
.push((validator.clone(), nom_index as u32));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (nominator_controller, validators_with_nom_index) in nominator_controllers {
|
||||
assert_ok!(Staking::payout_nominator(
|
||||
Origin::signed(nominator_controller),
|
||||
era,
|
||||
validators_with_nom_index,
|
||||
));
|
||||
}
|
||||
|
||||
// reward validators
|
||||
for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) {
|
||||
assert_ok!(Staking::payout_validator(Origin::signed(validator_controller), era));
|
||||
}
|
||||
}
|
||||
|
||||
/// Make all validator and nominator request their payment
|
||||
pub(crate) fn make_all_reward_payment(era: EraIndex) {
|
||||
let validators_with_reward = ErasRewardPoints::<Test>::get(era).individual.keys()
|
||||
|
||||
@@ -4461,330 +4461,6 @@ fn bond_during_era_correctly_populates_claimed_rewards() {
|
||||
});
|
||||
}
|
||||
|
||||
/* These migration tests below can be removed once migration code is removed */
|
||||
|
||||
#[test]
|
||||
fn rewards_should_work_before_migration() {
|
||||
// should check that before migration:
|
||||
// * rewards get recorded per session
|
||||
// * rewards get paid per Era
|
||||
// * Check that nominators are also rewarded
|
||||
ExtBuilder::default().nominate(true).build_and_execute(|| {
|
||||
MigrateEra::put(10);
|
||||
let init_balance_10 = Balances::total_balance(&10);
|
||||
let init_balance_11 = Balances::total_balance(&11);
|
||||
let init_balance_20 = Balances::total_balance(&20);
|
||||
let init_balance_21 = Balances::total_balance(&21);
|
||||
let init_balance_100 = Balances::total_balance(&100);
|
||||
let init_balance_101 = Balances::total_balance(&101);
|
||||
|
||||
// Check state
|
||||
Payee::<Test>::insert(11, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(21, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(101, RewardDestination::Controller);
|
||||
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
// This is the second validator of the current elected set.
|
||||
<Module<Test>>::reward_by_ids(vec![(21, 50)]);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_0 = current_total_payout_for_duration(3 * 1000);
|
||||
assert!(total_payout_0 > 10); // Test is meaningful if reward something
|
||||
|
||||
start_session(1);
|
||||
|
||||
assert_eq!(Balances::total_balance(&10), init_balance_10);
|
||||
assert_eq!(Balances::total_balance(&11), init_balance_11);
|
||||
assert_eq!(Balances::total_balance(&20), init_balance_20);
|
||||
assert_eq!(Balances::total_balance(&21), init_balance_21);
|
||||
assert_eq!(Balances::total_balance(&100), init_balance_100);
|
||||
assert_eq!(Balances::total_balance(&101), init_balance_101);
|
||||
assert_eq_uvec!(Session::validators(), vec![11, 21]);
|
||||
assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints {
|
||||
total: 50*3,
|
||||
individual: vec![(11, 100), (21, 50)].into_iter().collect(),
|
||||
});
|
||||
let part_for_10 = Perbill::from_rational_approximation::<u32>(1000, 1125);
|
||||
let part_for_20 = Perbill::from_rational_approximation::<u32>(1000, 1375);
|
||||
let part_for_100_from_10 = Perbill::from_rational_approximation::<u32>(125, 1125);
|
||||
let part_for_100_from_20 = Perbill::from_rational_approximation::<u32>(375, 1375);
|
||||
|
||||
start_session(2);
|
||||
start_session(3);
|
||||
|
||||
assert_eq!(Staking::active_era().unwrap().index, 1);
|
||||
mock::make_all_reward_payment_before_migration(0);
|
||||
|
||||
assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0*1/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2);
|
||||
assert_eq_error_rate!(
|
||||
Balances::total_balance(&100),
|
||||
init_balance_100
|
||||
+ part_for_100_from_10 * total_payout_0 * 2/3
|
||||
+ part_for_100_from_20 * total_payout_0 * 1/3,
|
||||
2
|
||||
);
|
||||
assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![11, 21]);
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 1)]);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_1 = current_total_payout_for_duration(3 * 1000);
|
||||
assert!(total_payout_1 > 10); // Test is meaningful if reward something
|
||||
|
||||
mock::start_era(2);
|
||||
mock::make_all_reward_payment_before_migration(1);
|
||||
|
||||
assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0 * 1/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2);
|
||||
assert_eq_error_rate!(
|
||||
Balances::total_balance(&100),
|
||||
init_balance_100
|
||||
+ part_for_100_from_10 * (total_payout_0 * 2/3 + total_payout_1)
|
||||
+ part_for_100_from_20 * total_payout_0 * 1/3,
|
||||
2
|
||||
);
|
||||
assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn migrate_era_should_work() {
|
||||
// should check that before and after migration:
|
||||
// * rewards get recorded per session
|
||||
// * rewards get paid per Era
|
||||
// * Check that nominators are also rewarded
|
||||
ExtBuilder::default().nominate(true).build_and_execute(|| {
|
||||
MigrateEra::put(1);
|
||||
let init_balance_10 = Balances::total_balance(&10);
|
||||
let init_balance_11 = Balances::total_balance(&11);
|
||||
let init_balance_20 = Balances::total_balance(&20);
|
||||
let init_balance_21 = Balances::total_balance(&21);
|
||||
let init_balance_100 = Balances::total_balance(&100);
|
||||
let init_balance_101 = Balances::total_balance(&101);
|
||||
|
||||
// Check state
|
||||
Payee::<Test>::insert(11, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(21, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(101, RewardDestination::Controller);
|
||||
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
// This is the second validator of the current elected set.
|
||||
<Module<Test>>::reward_by_ids(vec![(21, 50)]);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_0 = current_total_payout_for_duration(3 * 1000);
|
||||
assert!(total_payout_0 > 10); // Test is meaningful if reward something
|
||||
|
||||
start_session(1);
|
||||
|
||||
assert_eq!(Balances::total_balance(&10), init_balance_10);
|
||||
assert_eq!(Balances::total_balance(&11), init_balance_11);
|
||||
assert_eq!(Balances::total_balance(&20), init_balance_20);
|
||||
assert_eq!(Balances::total_balance(&21), init_balance_21);
|
||||
assert_eq!(Balances::total_balance(&100), init_balance_100);
|
||||
assert_eq!(Balances::total_balance(&101), init_balance_101);
|
||||
assert_eq_uvec!(Session::validators(), vec![11, 21]);
|
||||
assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints {
|
||||
total: 50*3,
|
||||
individual: vec![(11, 100), (21, 50)].into_iter().collect(),
|
||||
});
|
||||
let part_for_10 = Perbill::from_rational_approximation::<u32>(1000, 1125);
|
||||
let part_for_20 = Perbill::from_rational_approximation::<u32>(1000, 1375);
|
||||
let part_for_100_from_10 = Perbill::from_rational_approximation::<u32>(125, 1125);
|
||||
let part_for_100_from_20 = Perbill::from_rational_approximation::<u32>(375, 1375);
|
||||
|
||||
start_session(2);
|
||||
start_session(3);
|
||||
|
||||
assert_eq!(Staking::active_era().unwrap().index, 1);
|
||||
mock::make_all_reward_payment_before_migration(0);
|
||||
|
||||
assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0*1/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2);
|
||||
assert_eq_error_rate!(
|
||||
Balances::total_balance(&100),
|
||||
init_balance_100
|
||||
+ part_for_100_from_10 * total_payout_0 * 2/3
|
||||
+ part_for_100_from_20 * total_payout_0 * 1/3,
|
||||
2
|
||||
);
|
||||
assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![11, 21]);
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 1)]);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_1 = current_total_payout_for_duration(3 * 1000);
|
||||
assert!(total_payout_1 > 10); // Test is meaningful if reward something
|
||||
|
||||
mock::start_era(2);
|
||||
mock::make_all_reward_payment(1);
|
||||
|
||||
assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0 * 1/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2);
|
||||
assert_eq_error_rate!(
|
||||
Balances::total_balance(&100),
|
||||
init_balance_100
|
||||
+ part_for_100_from_10 * (total_payout_0 * 2/3 + total_payout_1)
|
||||
+ part_for_100_from_20 * total_payout_0 * 1/3,
|
||||
2
|
||||
);
|
||||
assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn migrate_era_should_handle_error() {
|
||||
ExtBuilder::default().nominate(true).build_and_execute(|| {
|
||||
MigrateEra::put(1);
|
||||
let init_balance_10 = Balances::total_balance(&10);
|
||||
let init_balance_11 = Balances::total_balance(&11);
|
||||
let init_balance_20 = Balances::total_balance(&20);
|
||||
let init_balance_21 = Balances::total_balance(&21);
|
||||
let init_balance_100 = Balances::total_balance(&100);
|
||||
let init_balance_101 = Balances::total_balance(&101);
|
||||
|
||||
// Check state
|
||||
Payee::<Test>::insert(11, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(21, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(101, RewardDestination::Controller);
|
||||
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
// This is the second validator of the current elected set.
|
||||
<Module<Test>>::reward_by_ids(vec![(21, 50)]);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_0 = current_total_payout_for_duration(3 * 1000);
|
||||
assert!(total_payout_0 > 10); // Test is meaningful if reward something
|
||||
|
||||
start_session(1);
|
||||
|
||||
assert_eq!(Balances::total_balance(&10), init_balance_10);
|
||||
assert_eq!(Balances::total_balance(&11), init_balance_11);
|
||||
assert_eq!(Balances::total_balance(&20), init_balance_20);
|
||||
assert_eq!(Balances::total_balance(&21), init_balance_21);
|
||||
assert_eq!(Balances::total_balance(&100), init_balance_100);
|
||||
assert_eq!(Balances::total_balance(&101), init_balance_101);
|
||||
assert_eq_uvec!(Session::validators(), vec![11, 21]);
|
||||
assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints {
|
||||
total: 50*3,
|
||||
individual: vec![(11, 100), (21, 50)].into_iter().collect(),
|
||||
});
|
||||
|
||||
start_session(2);
|
||||
start_session(3);
|
||||
|
||||
assert_eq!(Staking::active_era().unwrap().index, 1);
|
||||
mock::make_all_reward_payment(0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn migrate_era_should_handle_errors_2() {
|
||||
// should check that before and after migration:
|
||||
// * rewards get recorded per session
|
||||
// * rewards get paid per Era
|
||||
// * Check that nominators are also rewarded
|
||||
ExtBuilder::default().nominate(true).build_and_execute(|| {
|
||||
MigrateEra::put(1);
|
||||
let init_balance_10 = Balances::total_balance(&10);
|
||||
let init_balance_11 = Balances::total_balance(&11);
|
||||
let init_balance_20 = Balances::total_balance(&20);
|
||||
let init_balance_21 = Balances::total_balance(&21);
|
||||
let init_balance_100 = Balances::total_balance(&100);
|
||||
let init_balance_101 = Balances::total_balance(&101);
|
||||
|
||||
// Check state
|
||||
Payee::<Test>::insert(11, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(21, RewardDestination::Controller);
|
||||
Payee::<Test>::insert(101, RewardDestination::Controller);
|
||||
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 50)]);
|
||||
// This is the second validator of the current elected set.
|
||||
<Module<Test>>::reward_by_ids(vec![(21, 50)]);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_0 = current_total_payout_for_duration(3 * 1000);
|
||||
assert!(total_payout_0 > 10); // Test is meaningful if reward something
|
||||
|
||||
start_session(1);
|
||||
|
||||
assert_eq!(Balances::total_balance(&10), init_balance_10);
|
||||
assert_eq!(Balances::total_balance(&11), init_balance_11);
|
||||
assert_eq!(Balances::total_balance(&20), init_balance_20);
|
||||
assert_eq!(Balances::total_balance(&21), init_balance_21);
|
||||
assert_eq!(Balances::total_balance(&100), init_balance_100);
|
||||
assert_eq!(Balances::total_balance(&101), init_balance_101);
|
||||
assert_eq_uvec!(Session::validators(), vec![11, 21]);
|
||||
assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints {
|
||||
total: 50*3,
|
||||
individual: vec![(11, 100), (21, 50)].into_iter().collect(),
|
||||
});
|
||||
let part_for_10 = Perbill::from_rational_approximation::<u32>(1000, 1125);
|
||||
let part_for_20 = Perbill::from_rational_approximation::<u32>(1000, 1375);
|
||||
let part_for_100_from_10 = Perbill::from_rational_approximation::<u32>(125, 1125);
|
||||
let part_for_100_from_20 = Perbill::from_rational_approximation::<u32>(375, 1375);
|
||||
|
||||
start_session(2);
|
||||
start_session(3);
|
||||
|
||||
assert_eq!(Staking::active_era().unwrap().index, 1);
|
||||
mock::make_all_reward_payment_before_migration(0);
|
||||
|
||||
assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0*1/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2);
|
||||
assert_eq_error_rate!(
|
||||
Balances::total_balance(&100),
|
||||
init_balance_100
|
||||
+ part_for_100_from_10 * total_payout_0 * 2/3
|
||||
+ part_for_100_from_20 * total_payout_0 * 1/3,
|
||||
2
|
||||
);
|
||||
assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2);
|
||||
|
||||
assert_eq_uvec!(Session::validators(), vec![11, 21]);
|
||||
<Module<Test>>::reward_by_ids(vec![(11, 1)]);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_1 = current_total_payout_for_duration(3 * 1000);
|
||||
assert!(total_payout_1 > 10); // Test is meaningful if reward something
|
||||
|
||||
mock::start_era(2);
|
||||
mock::make_all_reward_payment_before_migration(1);
|
||||
|
||||
assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0 * 1/3, 2);
|
||||
assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2);
|
||||
assert_eq_error_rate!(
|
||||
Balances::total_balance(&100),
|
||||
init_balance_100
|
||||
+ part_for_100_from_10 * (total_payout_0 * 2/3 + total_payout_1)
|
||||
+ part_for_100_from_20 * total_payout_0 * 1/3,
|
||||
2
|
||||
);
|
||||
assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offences_weight_calculated_correctly() {
|
||||
ExtBuilder::default().nominate(true).build_and_execute(|| {
|
||||
|
||||
Reference in New Issue
Block a user