Only maintain at most 1 UnlockChunk per era (#10670)

* Only maintain at most 1 `UnlockChunk` per era

* Bound `unlocking`

* Run cargo +nightly-2021-10-29 fmt

* Make benchmarks stuff compile

* Update frame/staking/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Remove DerefMut; Implement neccesary methods directly

* Doc comments for new BoundedVec methods

* Fix benchmarks

* wip bonded_vec macro

* Correct rust doc

* Apply suggestions from code review

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Update staking::Config impls

* Add MaxUnlockingChunks to more places

* Use defensive saturating add

* FMT

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Zeke Mostov
2022-03-01 15:31:13 -08:00
committed by GitHub
parent fe5a50129a
commit 3f5e0baf4a
12 changed files with 147 additions and 95 deletions
+5 -5
View File
@@ -618,7 +618,7 @@ benchmarks! {
}
rebond {
let l in 1 .. MAX_UNLOCKING_CHUNKS as u32;
let l in 1 .. MaxUnlockingChunks::get() as u32;
// clean up any existing state.
clear_validators_and_nominators::<T>();
@@ -652,7 +652,7 @@ benchmarks! {
let mut staking_ledger = Ledger::<T>::get(controller.clone()).unwrap();
for _ in 0 .. l {
staking_ledger.unlocking.push(unlock_chunk.clone())
staking_ledger.unlocking.try_push(unlock_chunk.clone()).unwrap()
}
Ledger::<T>::insert(controller.clone(), staking_ledger.clone());
let original_bonded: BalanceOf<T> = staking_ledger.active;
@@ -702,7 +702,7 @@ benchmarks! {
stash: stash.clone(),
active: T::Currency::minimum_balance() - One::one(),
total: T::Currency::minimum_balance() - One::one(),
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
};
Ledger::<T>::insert(&controller, l);
@@ -788,7 +788,7 @@ benchmarks! {
#[extra]
do_slash {
let l in 1 .. MAX_UNLOCKING_CHUNKS as u32;
let l in 1 .. MaxUnlockingChunks::get() as u32;
let (stash, controller) = create_stash_controller::<T>(0, 100, Default::default())?;
let mut staking_ledger = Ledger::<T>::get(controller.clone()).unwrap();
let unlock_chunk = UnlockChunk::<BalanceOf<T>> {
@@ -796,7 +796,7 @@ benchmarks! {
era: EraIndex::zero(),
};
for _ in 0 .. l {
staking_ledger.unlocking.push(unlock_chunk.clone())
staking_ledger.unlocking.try_push(unlock_chunk.clone()).unwrap();
}
Ledger::<T>::insert(controller, staking_ledger);
let slash_amount = T::Currency::minimum_balance() * 10u32.into();
+16 -6
View File
@@ -301,6 +301,7 @@ mod pallet;
use codec::{Decode, Encode, HasCompact};
use frame_support::{
parameter_types,
traits::{ConstU32, Currency, Get},
weights::Weight,
BoundedVec, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
@@ -347,6 +348,10 @@ type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
<T as frame_system::Config>::AccountId,
>>::NegativeImbalance;
parameter_types! {
pub MaxUnlockingChunks: u32 = 32;
}
/// Information regarding the active era (era in used in session).
#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct ActiveEraInfo {
@@ -446,9 +451,10 @@ pub struct StakingLedger<AccountId, Balance: HasCompact> {
/// rounds.
#[codec(compact)]
pub active: Balance,
/// Any balance that is becoming free, which may eventually be transferred out
/// of the stash (assuming it doesn't get slashed first).
pub unlocking: Vec<UnlockChunk<Balance>>,
/// Any balance that is becoming free, which may eventually be transferred out of the stash
/// (assuming it doesn't get slashed first). It is assumed that this will be treated as a first
/// in, first out queue where the new (higher value) eras get pushed on the back.
pub unlocking: BoundedVec<UnlockChunk<Balance>, MaxUnlockingChunks>,
/// List of eras for which the stakers behind a validator have claimed rewards. Only updated
/// for validators.
pub claimed_rewards: Vec<EraIndex>,
@@ -463,7 +469,7 @@ impl<AccountId, Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned +
stash,
total: Zero::zero(),
active: Zero::zero(),
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
}
}
@@ -472,7 +478,7 @@ impl<AccountId, Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned +
/// total by the sum of their balances.
fn consolidate_unlocked(self, current_era: EraIndex) -> Self {
let mut total = self.total;
let unlocking = self
let unlocking: BoundedVec<_, _> = self
.unlocking
.into_iter()
.filter(|chunk| {
@@ -483,7 +489,11 @@ impl<AccountId, Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned +
false
}
})
.collect();
.collect::<Vec<_>>()
.try_into()
.expect(
"filtering items from a bounded vec always leaves length less than bounds. qed",
);
Self {
stash: self.stash,
+1
View File
@@ -271,6 +271,7 @@ impl crate::pallet::pallet::Config for Test {
type GenesisElectionProvider = Self::ElectionProvider;
// NOTE: consider a macro and use `UseNominatorsMap<Self>` as well.
type SortedListProvider = BagsList;
type MaxUnlockingChunks = ConstU32<32>;
type BenchmarkingConfig = TestBenchmarkingConfig;
type WeightInfo = ();
}
+4 -4
View File
@@ -928,7 +928,7 @@ impl<T: Config> ElectionDataProvider for Pallet<T> {
stash: voter.clone(),
active: stake,
total: stake,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
},
);
@@ -946,7 +946,7 @@ impl<T: Config> ElectionDataProvider for Pallet<T> {
stash: target.clone(),
active: stake,
total: stake,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
},
);
@@ -983,7 +983,7 @@ impl<T: Config> ElectionDataProvider for Pallet<T> {
stash: v.clone(),
active: stake,
total: stake,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
},
);
@@ -1004,7 +1004,7 @@ impl<T: Config> ElectionDataProvider for Pallet<T> {
stash: v.clone(),
active: stake,
total: stake,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
},
);
+29 -11
View File
@@ -21,8 +21,8 @@ use frame_election_provider_support::SortedListProvider;
use frame_support::{
pallet_prelude::*,
traits::{
Currency, CurrencyToVote, EnsureOrigin, EstimateNextNewSession, Get, LockIdentifier,
LockableCurrency, OnUnbalanced, UnixTime,
Currency, CurrencyToVote, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get,
LockIdentifier, LockableCurrency, OnUnbalanced, UnixTime,
},
weights::Weight,
};
@@ -40,12 +40,11 @@ pub use impls::*;
use crate::{
log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints,
Exposure, Forcing, NegativeImbalanceOf, Nominations, PositiveImbalanceOf, Releases,
RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk,
Exposure, Forcing, MaxUnlockingChunks, NegativeImbalanceOf, Nominations, PositiveImbalanceOf,
Releases, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk,
ValidatorPrefs,
};
pub const MAX_UNLOCKING_CHUNKS: usize = 32;
const STAKING_ID: LockIdentifier = *b"staking ";
#[frame_support::pallet]
@@ -157,6 +156,10 @@ pub mod pallet {
/// the bags-list is not desired, [`impls::UseNominatorsMap`] is likely the desired option.
type SortedListProvider: SortedListProvider<Self::AccountId>;
/// The maximum number of `unlocking` chunks a [`StakingLedger`] can have. Effectively
/// determines how many unique eras a staker may be unbonding in.
type MaxUnlockingChunks: Get<u32>;
/// Some parameters of the benchmarking.
type BenchmarkingConfig: BenchmarkingConfig;
@@ -772,7 +775,7 @@ pub mod pallet {
stash,
total: value,
active: value,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: (last_reward_era..current_era).collect(),
};
Self::update_ledger(&controller, &item);
@@ -837,7 +840,7 @@ pub mod pallet {
/// Once the unlock period is done, you can call `withdraw_unbonded` to actually move
/// the funds out of management ready for transfer.
///
/// No more than a limited number of unlocking chunks (see `MAX_UNLOCKING_CHUNKS`)
/// No more than a limited number of unlocking chunks (see `MaxUnlockingChunks`)
/// can co-exists at the same time. In that case, [`Call::withdraw_unbonded`] need
/// to be called first to remove some of the chunks (if possible).
///
@@ -854,7 +857,10 @@ pub mod pallet {
) -> DispatchResult {
let controller = ensure_signed(origin)?;
let mut ledger = Self::ledger(&controller).ok_or(Error::<T>::NotController)?;
ensure!(ledger.unlocking.len() < MAX_UNLOCKING_CHUNKS, Error::<T>::NoMoreChunks,);
ensure!(
ledger.unlocking.len() < MaxUnlockingChunks::get() as usize,
Error::<T>::NoMoreChunks,
);
let mut value = value.min(ledger.active);
@@ -881,7 +887,19 @@ pub mod pallet {
// Note: in case there is no current era it is fine to bond one era more.
let era = Self::current_era().unwrap_or(0) + T::BondingDuration::get();
ledger.unlocking.push(UnlockChunk { value, era });
if let Some(mut chunk) =
ledger.unlocking.last_mut().filter(|chunk| chunk.era == era)
{
// To keep the chunk count down, we only keep one chunk per era. Since
// `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will
// be the last one.
chunk.value = chunk.value.defensive_saturating_add(value)
} else {
ledger
.unlocking
.try_push(UnlockChunk { value, era })
.map_err(|_| Error::<T>::NoMoreChunks)?;
};
// NOTE: ledger must be updated prior to calling `Self::weight_of`.
Self::update_ledger(&controller, &ledger);
@@ -1348,10 +1366,10 @@ pub mod pallet {
///
/// # <weight>
/// - Time complexity: O(L), where L is unlocking chunks
/// - Bounded by `MAX_UNLOCKING_CHUNKS`.
/// - Bounded by `MaxUnlockingChunks`.
/// - Storage changes: Can't increase storage, only decrease it.
/// # </weight>
#[pallet::weight(T::WeightInfo::rebond(MAX_UNLOCKING_CHUNKS as u32))]
#[pallet::weight(T::WeightInfo::rebond(MaxUnlockingChunks::get() as u32))]
pub fn rebond(
origin: OriginFor<T>,
#[pallet::compact] value: BalanceOf<T>,
+73 -68
View File
@@ -17,10 +17,10 @@
//! Tests for the module.
use super::{Event, *};
use super::{Event, MaxUnlockingChunks, *};
use frame_election_provider_support::{ElectionProvider, SortedListProvider, Support};
use frame_support::{
assert_noop, assert_ok,
assert_noop, assert_ok, bounded_vec,
dispatch::WithPostDispatchInfo,
pallet_prelude::*,
traits::{Currency, Get, ReservableCurrency},
@@ -104,7 +104,7 @@ fn basic_setup_works() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
})
);
@@ -115,7 +115,7 @@ fn basic_setup_works() {
stash: 21,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
})
);
@@ -138,7 +138,7 @@ fn basic_setup_works() {
stash: 101,
total: 500,
active: 500,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
})
);
@@ -382,7 +382,7 @@ fn staking_should_work() {
stash: 3,
total: 1500,
active: 1500,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![0],
})
);
@@ -936,7 +936,7 @@ fn reward_destination_works() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -959,7 +959,7 @@ fn reward_destination_works() {
stash: 11,
total: 1000 + total_payout_0,
active: 1000 + total_payout_0,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![0],
})
);
@@ -987,7 +987,7 @@ fn reward_destination_works() {
stash: 11,
total: 1000 + total_payout_0,
active: 1000 + total_payout_0,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![0, 1],
})
);
@@ -1016,7 +1016,7 @@ fn reward_destination_works() {
stash: 11,
total: 1000 + total_payout_0,
active: 1000 + total_payout_0,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![0, 1, 2],
})
);
@@ -1081,7 +1081,7 @@ fn bond_extra_works() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1098,7 +1098,7 @@ fn bond_extra_works() {
stash: 11,
total: 1000 + 100,
active: 1000 + 100,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1112,7 +1112,7 @@ fn bond_extra_works() {
stash: 11,
total: 1000000,
active: 1000000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1150,7 +1150,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1168,7 +1168,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
stash: 11,
total: 1000 + 100,
active: 1000 + 100,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1189,7 +1189,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
stash: 11,
total: 1000 + 100,
active: 1000 + 100,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1207,7 +1207,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
stash: 11,
total: 1000 + 100,
active: 100,
unlocking: vec![UnlockChunk { value: 1000, era: 2 + 3 }],
unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }],
claimed_rewards: vec![]
}),
);
@@ -1220,7 +1220,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
stash: 11,
total: 1000 + 100,
active: 100,
unlocking: vec![UnlockChunk { value: 1000, era: 2 + 3 }],
unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }],
claimed_rewards: vec![]
}),
);
@@ -1236,7 +1236,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
stash: 11,
total: 1000 + 100,
active: 100,
unlocking: vec![UnlockChunk { value: 1000, era: 2 + 3 }],
unlocking: bounded_vec![UnlockChunk { value: 1000, era: 2 + 3 }],
claimed_rewards: vec![]
}),
);
@@ -1252,7 +1252,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
stash: 11,
total: 100,
active: 100,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
}),
);
@@ -1262,23 +1262,35 @@ fn bond_extra_and_withdraw_unbonded_works() {
#[test]
fn too_many_unbond_calls_should_not_work() {
ExtBuilder::default().build_and_execute(|| {
// locked at era 0 until 3
for _ in 0..MAX_UNLOCKING_CHUNKS - 1 {
let mut current_era = 0;
// locked at era MaxUnlockingChunks - 1 until 3
for i in 0..MaxUnlockingChunks::get() - 1 {
// There is only 1 chunk per era, so we need to be in a new era to create a chunk.
current_era = i as u32;
mock::start_active_era(current_era);
assert_ok!(Staking::unbond(Origin::signed(10), 1));
}
mock::start_active_era(1);
current_era += 1;
mock::start_active_era(current_era);
// locked at era 1 until 4
// This chunk is locked at `current_era` through `current_era + 2` (because BondingDuration
// == 3).
assert_ok!(Staking::unbond(Origin::signed(10), 1));
assert_eq!(
Staking::ledger(&10).unwrap().unlocking.len(),
MaxUnlockingChunks::get() as usize
);
// can't do more.
assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::<Test>::NoMoreChunks);
mock::start_active_era(3);
current_era += 2;
mock::start_active_era(current_era);
assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::<Test>::NoMoreChunks);
// free up.
// free up everything except the most recently added chunk.
assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0));
assert_eq!(Staking::ledger(&10).unwrap().unlocking.len(), 1);
// Can add again.
assert_ok!(Staking::unbond(Origin::signed(10), 1));
@@ -1310,7 +1322,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1329,7 +1341,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 100,
unlocking: vec![UnlockChunk { value: 900, era: 2 + 3 }],
unlocking: bounded_vec![UnlockChunk { value: 900, era: 2 + 3 }],
claimed_rewards: vec![],
})
);
@@ -1342,7 +1354,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1355,7 +1367,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 100,
unlocking: vec![UnlockChunk { value: 900, era: 5 }],
unlocking: bounded_vec![UnlockChunk { value: 900, era: 5 }],
claimed_rewards: vec![],
})
);
@@ -1368,7 +1380,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 600,
unlocking: vec![UnlockChunk { value: 400, era: 5 }],
unlocking: bounded_vec![UnlockChunk { value: 400, era: 5 }],
claimed_rewards: vec![],
})
);
@@ -1381,7 +1393,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1396,11 +1408,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 100,
unlocking: vec![
UnlockChunk { value: 300, era: 5 },
UnlockChunk { value: 300, era: 5 },
UnlockChunk { value: 300, era: 5 },
],
unlocking: bounded_vec![UnlockChunk { value: 900, era: 5 }],
claimed_rewards: vec![],
})
);
@@ -1413,10 +1421,7 @@ fn rebond_works() {
stash: 11,
total: 1000,
active: 600,
unlocking: vec![
UnlockChunk { value: 300, era: 5 },
UnlockChunk { value: 100, era: 5 },
],
unlocking: bounded_vec![UnlockChunk { value: 400, era: 5 }],
claimed_rewards: vec![],
})
);
@@ -1443,7 +1448,7 @@ fn rebond_is_fifo() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1458,7 +1463,7 @@ fn rebond_is_fifo() {
stash: 11,
total: 1000,
active: 600,
unlocking: vec![UnlockChunk { value: 400, era: 2 + 3 },],
unlocking: bounded_vec![UnlockChunk { value: 400, era: 2 + 3 }],
claimed_rewards: vec![],
})
);
@@ -1473,9 +1478,9 @@ fn rebond_is_fifo() {
stash: 11,
total: 1000,
active: 300,
unlocking: vec![
unlocking: bounded_vec![
UnlockChunk { value: 400, era: 2 + 3 },
UnlockChunk { value: 300, era: 3 + 3 },
UnlockChunk { value: 300, era: 3 + 3 }
],
claimed_rewards: vec![],
})
@@ -1491,10 +1496,10 @@ fn rebond_is_fifo() {
stash: 11,
total: 1000,
active: 100,
unlocking: vec![
unlocking: bounded_vec![
UnlockChunk { value: 400, era: 2 + 3 },
UnlockChunk { value: 300, era: 3 + 3 },
UnlockChunk { value: 200, era: 4 + 3 },
UnlockChunk { value: 200, era: 4 + 3 }
],
claimed_rewards: vec![],
})
@@ -1508,9 +1513,9 @@ fn rebond_is_fifo() {
stash: 11,
total: 1000,
active: 500,
unlocking: vec![
unlocking: bounded_vec![
UnlockChunk { value: 400, era: 2 + 3 },
UnlockChunk { value: 100, era: 3 + 3 },
UnlockChunk { value: 100, era: 3 + 3 }
],
claimed_rewards: vec![],
})
@@ -1540,7 +1545,7 @@ fn rebond_emits_right_value_in_event() {
stash: 11,
total: 1000,
active: 100,
unlocking: vec![UnlockChunk { value: 900, era: 1 + 3 }],
unlocking: bounded_vec![UnlockChunk { value: 900, era: 1 + 3 }],
claimed_rewards: vec![],
})
);
@@ -1553,7 +1558,7 @@ fn rebond_emits_right_value_in_event() {
stash: 11,
total: 1000,
active: 200,
unlocking: vec![UnlockChunk { value: 800, era: 1 + 3 }],
unlocking: bounded_vec![UnlockChunk { value: 800, era: 1 + 3 }],
claimed_rewards: vec![],
})
);
@@ -1568,7 +1573,7 @@ fn rebond_emits_right_value_in_event() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -1604,7 +1609,7 @@ fn reward_to_stake_works() {
stash: 21,
total: 69,
active: 69,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
},
);
@@ -1665,7 +1670,7 @@ fn reap_stash_works() {
stash: 11,
total: 5,
active: 5,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
},
);
@@ -1784,7 +1789,7 @@ fn bond_with_no_staked_value() {
stash: 1,
active: 0,
total: 5,
unlocking: vec![UnlockChunk { value: 5, era: 3 }],
unlocking: bounded_vec![UnlockChunk { value: 5, era: 3 }],
claimed_rewards: vec![],
})
);
@@ -3354,7 +3359,7 @@ fn test_payout_stakers() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![1]
})
);
@@ -3376,7 +3381,7 @@ fn test_payout_stakers() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: (1..=14).collect()
})
);
@@ -3397,7 +3402,7 @@ fn test_payout_stakers() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![15, 98]
})
);
@@ -3412,7 +3417,7 @@ fn test_payout_stakers() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![15, 23, 42, 69, 98]
})
);
@@ -3607,7 +3612,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() {
stash: 9,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![],
})
);
@@ -3619,7 +3624,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() {
stash: 11,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: (0..5).collect(),
})
);
@@ -3631,7 +3636,7 @@ fn bond_during_era_correctly_populates_claimed_rewards() {
stash: 13,
total: 1000,
active: 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: (15..99).collect(),
})
);
@@ -3850,7 +3855,7 @@ fn cannot_rebond_to_lower_than_ed() {
stash: 21,
total: 10 * 1000,
active: 10 * 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
}
);
@@ -3864,7 +3869,7 @@ fn cannot_rebond_to_lower_than_ed() {
stash: 21,
total: 10 * 1000,
active: 0,
unlocking: vec![UnlockChunk { value: 10 * 1000, era: 3 }],
unlocking: bounded_vec![UnlockChunk { value: 10 * 1000, era: 3 }],
claimed_rewards: vec![]
}
);
@@ -3887,7 +3892,7 @@ fn cannot_bond_extra_to_lower_than_ed() {
stash: 21,
total: 10 * 1000,
active: 10 * 1000,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
}
);
@@ -3901,7 +3906,7 @@ fn cannot_bond_extra_to_lower_than_ed() {
stash: 21,
total: 10 * 1000,
active: 0,
unlocking: vec![UnlockChunk { value: 10 * 1000, era: 3 }],
unlocking: bounded_vec![UnlockChunk { value: 10 * 1000, era: 3 }],
claimed_rewards: vec![]
}
);
@@ -3928,7 +3933,7 @@ fn do_not_die_when_active_is_ed() {
stash: 21,
total: 1000 * ed,
active: 1000 * ed,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
}
);
@@ -3945,7 +3950,7 @@ fn do_not_die_when_active_is_ed() {
stash: 21,
total: ed,
active: ed,
unlocking: vec![],
unlocking: Default::default(),
claimed_rewards: vec![]
}
);