use super::*;
use frame_election_provider_support::ElectionDataProvider;
#[test]
fn set_minimum_active_stake_is_correct() {
ExtBuilder::default()
.nominate(false)
.add_staker(61, 2_000, StakerStatus::<AccountId>::Nominator(vec![21]))
.add_staker(71, 10, StakerStatus::<AccountId>::Nominator(vec![21]))
.add_staker(81, 50, StakerStatus::<AccountId>::Nominator(vec![21]))
.build_and_execute(|| {
assert_ok!(<Staking as ElectionDataProvider>::electing_voters(
DataProviderBounds::default(),
0
));
assert_eq!(MinimumActiveStake::<Test>::get(), 10);
let bounds = ElectionBoundsBuilder::default().voters_count(5.into()).build();
assert_ok!(<Staking as ElectionDataProvider>::electing_voters(bounds.voters, 0));
assert_eq!(MinimumActiveStake::<Test>::get(), 50);
});
}
#[test]
fn set_minimum_active_stake_lower_bond_works() {
ExtBuilder::default().has_stakers(true).nominate(true).build_and_execute(|| {
assert_eq!(MinNominatorBond::<Test>::get(), 1);
assert_eq!(<Test as Config>::VoterList::count(), 4);
assert_ok!(Staking::bond(RuntimeOrigin::signed(4), 5, RewardDestination::Staked,));
assert_ok!(Staking::nominate(RuntimeOrigin::signed(4), vec![11]));
assert_eq!(<Test as Config>::VoterList::count(), 5);
let voters_before =
<Staking as ElectionDataProvider>::electing_voters(DataProviderBounds::default(), 0)
.unwrap();
assert_eq!(MinimumActiveStake::<Test>::get(), 5);
MinNominatorBond::<Test>::set(10);
assert_eq!(MinNominatorBond::<Test>::get(), 10);
assert_eq!(<Test as Config>::VoterList::count(), 5);
let voters =
<Staking as ElectionDataProvider>::electing_voters(DataProviderBounds::default(), 0)
.unwrap();
assert_eq!(voters_before, voters);
assert_eq!(MinimumActiveStake::<Test>::get(), 5);
});
}
#[test]
fn set_minimum_active_bond_corrupt_state() {
ExtBuilder::default()
.has_stakers(true)
.nominate(true)
.add_staker(61, 2_000, StakerStatus::<AccountId>::Nominator(vec![21]))
.build_and_execute(|| {
assert_eq!(Staking::weight_of(&101), 500);
let voters = <Staking as ElectionDataProvider>::electing_voters(
DataProviderBounds::default(),
0,
)
.unwrap();
assert_eq!(voters.len(), 5);
assert_eq!(MinimumActiveStake::<Test>::get(), 500);
Session::roll_until_active_era(10);
assert_ok!(Staking::unbond(RuntimeOrigin::signed(101), 200));
Session::roll_until_active_era(20);
assert_ok!(Staking::unbond(RuntimeOrigin::signed(101), 100));
MaxUnlockingChunks::set(1);
let voters = <Staking as ElectionDataProvider>::electing_voters(
DataProviderBounds::default(),
0,
)
.unwrap();
assert_eq!(voters.len(), 4);
assert_eq!(MinimumActiveStake::<Test>::get(), 2_000);
assert_eq!(Staking::weight_of(&101), 0);
MaxUnlockingChunks::set(32);
})
}
#[test]
fn voters_include_self_vote() {
ExtBuilder::default().nominate(false).build_and_execute(|| {
assert!(<Validators<Test>>::iter().map(|(x, _)| x).all(|v| Staking::electing_voters(
DataProviderBounds::default(),
0
)
.unwrap()
.into_iter()
.any(|(w, _, t)| { v == w && t[0] == w })))
})
}
#[test]
#[should_panic]
#[cfg(debug_assertions)]
fn only_iterates_max_2_times_max_allowed_len() {
ExtBuilder::default()
.nominate(false)
.add_staker(61, 2_000, StakerStatus::<AccountId>::Nominator(vec![21, 22, 23, 24, 25]))
.add_staker(71, 2_000, StakerStatus::<AccountId>::Nominator(vec![21, 22, 23, 24, 25]))
.add_staker(81, 2_000, StakerStatus::<AccountId>::Nominator(vec![21, 22, 23, 24, 25]))
.build_and_execute(|| {
let bounds_builder = ElectionBoundsBuilder::default();
assert_eq!(
<Test as Config>::VoterList::iter().collect::<Vec<_>>(),
vec![61, 71, 81, 11, 21, 31]
);
AbsoluteMaxNominations::set(2);
assert_eq!(
Staking::electing_voters(bounds_builder.voters_count(2.into()).build().voters, 0)
.unwrap()
.iter()
.map(|(stash, _, _)| stash)
.copied()
.collect::<Vec<_>>(),
vec![11],
);
});
}
#[test]
fn respects_snapshot_count_limits() {
ExtBuilder::default()
.set_status(41, StakerStatus::Validator)
.build_and_execute(|| {
assert_eq!(<Test as Config>::VoterList::count(), 5);
let bounds_builder = ElectionBoundsBuilder::default();
assert_eq!(
Staking::electing_voters(bounds_builder.voters_count(1.into()).build().voters, 0)
.unwrap()
.len(),
1
);
assert_eq!(
Staking::electing_voters(bounds_builder.voters_count(5.into()).build().voters, 0)
.unwrap()
.len(),
5
);
assert_eq!(
Staking::electing_voters(bounds_builder.voters_count(55.into()).build().voters, 0)
.unwrap()
.len(),
5
);
assert_eq!(
Staking::electable_targets(
bounds_builder.targets_count(6.into()).build().targets,
0,
)
.unwrap()
.len(),
4
);
assert_eq!(
Staking::electable_targets(
bounds_builder.targets_count(4.into()).build().targets,
0,
)
.unwrap()
.len(),
4
);
assert_eq!(
Staking::electable_targets(
bounds_builder.targets_count(1.into()).build().targets,
0
)
.unwrap()
.len(),
1,
);
});
}
#[test]
fn respects_snapshot_size_limits() {
ExtBuilder::default().build_and_execute(|| {
let bounds = ElectionBoundsBuilder::default().voters_size(26.into()).build();
let elected = Staking::electing_voters(bounds.voters, 0).unwrap();
assert!(elected.encoded_size() == 26 as usize);
let prev_len = elected.len();
let bounds = ElectionBoundsBuilder::default().voters_size(100.into()).build();
let elected = Staking::electing_voters(bounds.voters, 0).unwrap();
assert!(elected.encoded_size() <= 100 as usize);
assert!(elected.len() > 1 && elected.len() > prev_len);
let bounds = ElectionBoundsBuilder::default().targets_size(10.into()).build();
let elected = Staking::electable_targets(bounds.targets, 0).unwrap();
assert!(elected.encoded_size() == 9 as usize);
let prev_len = elected.len();
let bounds = ElectionBoundsBuilder::default().targets_size(100.into()).build();
let elected = Staking::electable_targets(bounds.targets, 0).unwrap();
assert!(elected.encoded_size() <= 100 as usize);
assert!(elected.len() > 1 && elected.len() > prev_len);
});
}
#[test]
fn nomination_quota_checks_at_nominate_works() {
ExtBuilder::default().nominate(false).build_and_execute(|| {
bond(61, 222);
assert_eq!(Staking::api_nominations_quota(222), 2);
assert_ok!(Staking::nominate(RuntimeOrigin::signed(61), vec![11]));
assert_ok!(Staking::nominate(RuntimeOrigin::signed(61), vec![11, 21]));
assert_noop!(
Staking::nominate(RuntimeOrigin::signed(61), vec![11, 21, 31]),
Error::<Test>::TooManyTargets
);
});
}
#[test]
#[should_panic]
#[cfg(debug_assertions)]
fn change_of_absolute_max_nominations() {
use frame_election_provider_support::ElectionDataProvider;
ExtBuilder::default()
.add_staker(61, 10, StakerStatus::Nominator(vec![1]))
.add_staker(71, 10, StakerStatus::Nominator(vec![1, 2, 3]))
.balance_factor(10)
.build_and_execute(|| {
assert_eq!(AbsoluteMaxNominations::get(), 16);
assert_eq!(
Nominators::<Test>::iter()
.map(|(k, n)| (k, n.targets.len()))
.collect::<Vec<_>>(),
vec![(101, 2), (71, 3), (61, 1)]
);
let bounds = DataProviderBounds::default();
assert_eq!(Staking::electing_voters(bounds, 0).unwrap().len(), 3 + 3);
AbsoluteMaxNominations::set(4);
assert_eq!(
Nominators::<Test>::iter()
.map(|(k, n)| (k, n.targets.len()))
.collect::<Vec<_>>(),
vec![(101, 2), (71, 3), (61, 1)]
);
assert_eq!(Staking::electing_voters(bounds, 0).unwrap().len(), 3 + 3);
for k in Nominators::<Test>::iter_keys() {
assert_noop!(
Staking::chill_other(RuntimeOrigin::signed(1), k),
Error::<Test>::CannotChillOther
);
}
AbsoluteMaxNominations::set(3);
assert_eq!(
Nominators::<Test>::iter()
.map(|(k, n)| (k, n.targets.len()))
.collect::<Vec<_>>(),
vec![(101, 2), (71, 3), (61, 1)]
);
assert_eq!(Staking::electing_voters(bounds, 0).unwrap().len(), 3 + 3);
for k in Nominators::<Test>::iter_keys() {
assert_noop!(
Staking::chill_other(RuntimeOrigin::signed(1), k),
Error::<Test>::CannotChillOther
);
}
AbsoluteMaxNominations::set(2);
assert_eq!(
Nominators::<Test>::iter()
.map(|(k, n)| (k, n.targets.len()))
.collect::<Vec<_>>(),
vec![(101, 2), (61, 1)]
);
for k in [101, 61].iter() {
assert_noop!(
Staking::chill_other(RuntimeOrigin::signed(1), *k),
Error::<Test>::CannotChillOther
);
}
assert!(Nominators::<Test>::contains_key(71));
assert!(Nominators::<Test>::get(71).is_none());
assert_eq!(Staking::electing_voters(bounds, 0).unwrap().len(), 3 + 2);
assert!(Nominators::<Test>::contains_key(101));
AbsoluteMaxNominations::set(1);
assert_eq!(
Nominators::<Test>::iter()
.map(|(k, n)| (k, n.targets.len()))
.collect::<Vec<_>>(),
vec![(61, 1)]
);
assert_noop!(
Staking::chill_other(RuntimeOrigin::signed(1), 61),
Error::<Test>::CannotChillOther
);
assert!(Nominators::<Test>::contains_key(71));
assert!(Nominators::<Test>::contains_key(61));
assert!(Nominators::<Test>::get(71).is_none());
assert!(Nominators::<Test>::get(61).is_some());
assert_eq!(Staking::electing_voters(bounds, 0).unwrap().len(), 3 + 1);
assert_ok!(Staking::nominate(RuntimeOrigin::signed(71), vec![1]));
assert_eq!(
Nominators::<Test>::iter()
.map(|(k, n)| (k, n.targets.len()))
.collect::<Vec<_>>(),
vec![(71, 1), (61, 1)]
);
assert!(Nominators::<Test>::contains_key(101));
assert!(Nominators::<Test>::get(101).is_none());
assert_ok!(Staking::chill_other(RuntimeOrigin::signed(71), 101));
assert_eq!(*staking_events().last().unwrap(), Event::Chilled { stash: 101 });
assert!(!Nominators::<Test>::contains_key(101));
assert!(Nominators::<Test>::get(101).is_none());
})
}
#[test]
fn nomination_quota_max_changes_decoding() {
use frame_election_provider_support::ElectionDataProvider;
ExtBuilder::default()
.nominate(false)
.set_status(41, StakerStatus::Validator)
.add_staker(60, 10, StakerStatus::Nominator(vec![11]))
.add_staker(70, 10, StakerStatus::Nominator(vec![11, 21, 31]))
.add_staker(30, 10, StakerStatus::Nominator(vec![11, 21, 31, 41]))
.add_staker(50, 10, StakerStatus::Nominator(vec![11, 21, 31, 41]))
.balance_factor(11)
.build_and_execute(|| {
assert_eq!(MaxNominationsOf::<Test>::get(), 16);
let unbounded_election = DataProviderBounds::default();
assert_eq!(
Nominators::<Test>::iter()
.map(|(k, n)| (k, n.targets.len()))
.collect::<Vec<_>>(),
vec![(70, 3), (50, 4), (30, 4), (60, 1)]
);
assert_eq!(Staking::electing_voters(unbounded_election, 0).unwrap().len(), 4 + 4);
});
}
#[test]
fn api_nominations_quota_works() {
ExtBuilder::default().build_and_execute(|| {
assert_eq!(Staking::api_nominations_quota(10), MaxNominationsOf::<Test>::get());
assert_eq!(Staking::api_nominations_quota(333), MaxNominationsOf::<Test>::get());
assert_eq!(Staking::api_nominations_quota(222), 2);
assert_eq!(Staking::api_nominations_quota(111), 1);
})
}
#[test]
fn lazy_quota_npos_voters_works_above_quota() {
ExtBuilder::default()
.nominate(false)
.add_staker(22, 1000, StakerStatus::Validator)
.add_staker(23, 1000, StakerStatus::Validator)
.add_staker(24, 1000, StakerStatus::Validator)
.add_staker(25, 1000, StakerStatus::Validator)
.add_staker(
61,
300, StakerStatus::<AccountId>::Nominator(vec![21, 22, 23, 24, 25]),
)
.build_and_execute(|| {
assert_ok!(Staking::unbond(RuntimeOrigin::signed(61), 78));
assert_eq!(Staking::api_nominations_quota(300 - 78), 2);
assert_eq!(
Staking::electing_voters(DataProviderBounds::default(), 0)
.unwrap()
.iter()
.map(|(stash, _, targets)| (*stash, targets.len()))
.collect::<Vec<_>>(),
vec![(11, 1), (21, 1), (31, 1), (22, 1), (23, 1), (24, 1), (25, 1), (61, 5)],
);
});
}
#[test]
fn nominations_quota_limits_size_work() {
ExtBuilder::default()
.nominate(false)
.set_status(41, StakerStatus::Validator)
.add_staker(71, 333, StakerStatus::<AccountId>::Nominator(vec![11, 21, 31, 41]))
.build_and_execute(|| {
let bounds = ElectionBoundsBuilder::default().voters_size(101.into()).build();
assert_eq!(
Staking::electing_voters(bounds.voters, 0)
.unwrap()
.iter()
.map(|(stash, _, targets)| (*stash, targets.len()))
.collect::<Vec<_>>(),
vec![(41, 1), (11, 1), (21, 1), (31, 1)],
);
assert_eq!(
*staking_events().last().unwrap(),
Event::SnapshotVotersSizeExceeded { size: 100 }
);
let bounds = ElectionBoundsBuilder::default().voters_size(1_000.into()).build();
assert_eq!(
Staking::electing_voters(bounds.voters, 0)
.unwrap()
.iter()
.map(|(stash, _, targets)| (*stash, targets.len()))
.collect::<Vec<_>>(),
vec![(41, 1), (11, 1), (21, 1), (31, 1), (71, 4)],
);
});
}
mod sorted_list_provider {
use super::*;
use frame_election_provider_support::SortedListProvider;
#[test]
fn re_nominate_does_not_change_counters_or_list() {
ExtBuilder::default().nominate(true).build_and_execute(|| {
let pre_insert_voter_count =
(Nominators::<Test>::count() + Validators::<Test>::count()) as u32;
assert_eq!(<Test as Config>::VoterList::count(), pre_insert_voter_count);
assert_eq!(
<Test as Config>::VoterList::iter().collect::<Vec<_>>(),
vec![11, 21, 31, 101]
);
assert_ok!(Staking::nominate(RuntimeOrigin::signed(101), vec![31]));
assert_eq!(<Test as Config>::VoterList::count(), pre_insert_voter_count);
assert_eq!(
<Test as Config>::VoterList::iter().collect::<Vec<_>>(),
vec![11, 21, 31, 101]
);
});
}
#[test]
fn re_validate_does_not_change_counters_or_list() {
ExtBuilder::default().nominate(false).build_and_execute(|| {
let pre_insert_voter_count =
(Nominators::<Test>::count() + Validators::<Test>::count()) as u32;
assert_eq!(<Test as Config>::VoterList::count(), pre_insert_voter_count);
assert_eq!(<Test as Config>::VoterList::iter().collect::<Vec<_>>(), vec![11, 21, 31]);
assert_ok!(Staking::validate(RuntimeOrigin::signed(11), Default::default()));
assert_eq!(<Test as Config>::VoterList::count(), pre_insert_voter_count);
assert_eq!(<Test as Config>::VoterList::iter().collect::<Vec<_>>(), vec![11, 21, 31]);
});
}
}
mod paged_snapshot {
use super::*;
#[test]
fn target_snapshot_works() {
ExtBuilder::default()
.nominate(true)
.set_status(41, StakerStatus::Validator)
.set_status(51, StakerStatus::Validator)
.set_status(101, StakerStatus::Idle)
.build_and_execute(|| {
let all_targets = vec![51, 31, 41, 21, 11];
assert_eq_uvec!(
<Test as Config>::TargetList::iter().collect::<Vec<_>>(),
all_targets,
);
let bounds =
ElectionBoundsBuilder::default().targets_count(3.into()).build().targets;
let targets =
<Staking as ElectionDataProvider>::electable_targets(bounds, 0).unwrap();
assert_eq_uvec!(targets, all_targets.iter().take(3).cloned().collect::<Vec<_>>());
let bounds =
ElectionBoundsBuilder::default().targets_count(u32::MAX.into()).build().targets;
let single_page_targets =
<Staking as ElectionDataProvider>::electable_targets(bounds, 0).unwrap();
assert_eq_uvec!(all_targets, single_page_targets);
})
}
#[test]
fn target_snapshot_multi_page_redundant() {
ExtBuilder::default().build_and_execute(|| {
let all_targets = vec![31, 21, 11];
assert_eq_uvec!(<Test as Config>::TargetList::iter().collect::<Vec<_>>(), all_targets,);
let bounds =
ElectionBoundsBuilder::default().targets_count(u32::MAX.into()).build().targets;
let snapshot = Staking::electable_targets(bounds, 0).unwrap();
assert!(
snapshot == all_targets &&
snapshot == Staking::electable_targets(bounds, 1).unwrap() &&
snapshot == Staking::electable_targets(bounds, 2).unwrap() &&
snapshot == Staking::electable_targets(bounds, u32::MAX).unwrap(),
);
})
}
#[test]
fn voter_snapshot_works() {
ExtBuilder::default()
.nominate(true)
.set_status(51, StakerStatus::Validator)
.set_status(41, StakerStatus::Nominator(vec![51]))
.set_status(101, StakerStatus::Validator)
.build_and_execute(|| {
let bounds = ElectionBoundsBuilder::default().voters_count(3.into()).build().voters;
assert_eq!(
<Test as Config>::VoterList::iter()
.collect::<Vec<_>>()
.into_iter()
.map(|v| (v, <Test as Config>::VoterList::get_score(&v).unwrap()))
.collect::<Vec<_>>(),
vec![(51, 5000), (41, 4000), (11, 1000), (21, 1000), (31, 500), (101, 500)],
);
let mut all_voters = vec![];
let voters_page_3 = <Staking as ElectionDataProvider>::electing_voters(bounds, 3)
.unwrap()
.into_iter()
.map(|(a, _, _)| a)
.collect::<Vec<_>>();
all_voters.extend(voters_page_3.clone());
assert_eq!(voters_page_3, vec![51, 41, 11]);
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Ongoing(11));
let voters_page_2 = <Staking as ElectionDataProvider>::electing_voters(bounds, 2)
.unwrap()
.into_iter()
.map(|(a, _, _)| a)
.collect::<Vec<_>>();
all_voters.extend(voters_page_2.clone());
assert_eq!(voters_page_2, vec![21, 31, 101]);
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Consumed);
assert!(<Staking as ElectionDataProvider>::electing_voters(bounds, 1)
.unwrap()
.is_empty());
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Consumed);
assert!(<Staking as ElectionDataProvider>::electing_voters(bounds, 0)
.unwrap()
.is_empty());
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Waiting);
let bounds =
ElectionBoundsBuilder::default().voters_count(u32::MAX.into()).build().targets;
let single_page_voters =
<Staking as ElectionDataProvider>::electing_voters(bounds, 0)
.unwrap()
.into_iter()
.map(|(a, _, _)| a)
.collect::<Vec<_>>();
assert_eq!(all_voters, single_page_voters);
})
}
#[test]
fn voter_list_locked_during_multi_page_snapshot() {
ExtBuilder::default()
.nominate(true)
.set_status(51, StakerStatus::Validator)
.set_status(41, StakerStatus::Nominator(vec![51]))
.set_status(101, StakerStatus::Validator)
.build_and_execute(|| {
let bounds = ElectionBoundsBuilder::default().voters_count(2.into()).build().voters;
assert_eq!(
<Test as Config>::VoterList::iter()
.collect::<Vec<_>>()
.into_iter()
.map(|v| (v, <Test as Config>::VoterList::get_score(&v).unwrap()))
.collect::<Vec<_>>(),
vec![(51, 5000), (41, 4000), (11, 1000), (21, 1000), (31, 500), (101, 500)],
);
assert_eq!(pallet_bags_list::Lock::<T, VoterBagsListInstance>::get(), None);
let voters_page_3 = <Staking as ElectionDataProvider>::electing_voters(bounds, 3)
.unwrap()
.into_iter()
.map(|(a, _, _)| a)
.collect::<Vec<_>>();
assert_eq!(voters_page_3, vec![51, 41]);
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Ongoing(41));
assert_eq!(pallet_bags_list::Lock::<T, VoterBagsListInstance>::get(), Some(()));
hypothetically!({});
let voters_page_2 = <Staking as ElectionDataProvider>::electing_voters(bounds, 2)
.unwrap()
.into_iter()
.map(|(a, _, _)| a)
.collect::<Vec<_>>();
assert_eq!(voters_page_2, vec![11, 21]);
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Ongoing(21));
assert_eq!(pallet_bags_list::Lock::<T, VoterBagsListInstance>::get(), Some(()));
let voters_page_1 = <Staking as ElectionDataProvider>::electing_voters(bounds, 1)
.unwrap()
.into_iter()
.map(|(a, _, _)| a)
.collect::<Vec<_>>();
assert_eq_uvec!(voters_page_1, vec![31, 101]);
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Consumed);
assert_eq!(pallet_bags_list::Lock::<T, VoterBagsListInstance>::get(), None);
assert!(<Staking as ElectionDataProvider>::electing_voters(bounds, 0)
.unwrap()
.is_empty());
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Waiting);
assert_eq!(pallet_bags_list::Lock::<T, VoterBagsListInstance>::get(), None);
})
}
#[test]
fn voter_list_not_updated_when_locked() {
ExtBuilder::default()
.nominate(true)
.set_status(51, StakerStatus::Validator)
.set_status(41, StakerStatus::Nominator(vec![51]))
.set_status(101, StakerStatus::Validator)
.build_and_execute(|| {
let bounds = ElectionBoundsBuilder::default().voters_count(2.into()).build().voters;
assert_eq!(
<Test as Config>::VoterList::iter()
.collect::<Vec<_>>()
.into_iter()
.map(|v| (v, <Test as Config>::VoterList::get_score(&v).unwrap()))
.collect::<Vec<_>>(),
vec![(51, 5000), (41, 4000), (11, 1000), (21, 1000), (31, 500), (101, 500)],
);
assert_eq!(
pallet_bags_list::ListNodes::<T, VoterBagsListInstance>::get(51)
.unwrap()
.bag_upper,
10_000
);
assert_eq!(
pallet_bags_list::ListNodes::<T, VoterBagsListInstance>::get(11)
.unwrap()
.bag_upper,
1000
);
assert_eq!(pallet_bags_list::Lock::<T, VoterBagsListInstance>::get(), None);
let voters_page_3 = <Staking as ElectionDataProvider>::electing_voters(bounds, 3)
.unwrap()
.into_iter()
.map(|(a, _, _)| a)
.collect::<Vec<_>>();
assert_eq!(voters_page_3, vec![51, 41]);
assert_eq!(VoterSnapshotStatus::<Test>::get(), SnapshotStatus::Ongoing(41));
assert_eq!(pallet_bags_list::Lock::<T, VoterBagsListInstance>::get(), Some(()));
hypothetically!({
assert_ok!(Staking::unbond(RuntimeOrigin::signed(51), 500));
assert_eq!(
pallet_bags_list::ListNodes::<T, VoterBagsListInstance>::get(51)
.unwrap()
.bag_upper,
10_000
);
});
hypothetically!({
crate::asset::set_stakeable_balance::<T>(&11, 10000);
assert_ok!(Staking::bond_extra(RuntimeOrigin::signed(11), 5000));
assert_eq!(
pallet_bags_list::ListNodes::<T, VoterBagsListInstance>::get(11)
.unwrap()
.bag_upper,
1000
);
});
})
}
}
mod score_provider {
use frame_election_provider_support::ScoreProvider;
use super::*;
#[test]
fn no_score_for_chilled_stakers() {
ExtBuilder::default().build_and_execute(|| {
assert!(
Ledger::<Test>::get(41).is_some() &&
!Validators::<Test>::contains_key(41) &&
!Nominators::<Test>::contains_key(41)
);
assert!(<Staking as ScoreProvider<_>>::score(&41).is_none());
});
}
#[test]
fn no_score_for_non_stakers() {
ExtBuilder::default().build_and_execute(|| {
assert!(
!Ledger::<Test>::get(777).is_some() &&
!Validators::<Test>::contains_key(777) &&
!Nominators::<Test>::contains_key(777)
);
assert!(<Staking as ScoreProvider<_>>::score(&777).is_none());
});
}
#[test]
fn score_for_validators_nominators() {
ExtBuilder::default().nominate(true).build_and_execute(|| {
assert!(
Ledger::<Test>::get(101).unwrap().active == 500 &&
!Validators::<Test>::contains_key(101) &&
Nominators::<Test>::contains_key(101)
);
assert_eq!(<Staking as ScoreProvider<_>>::score(&101), Some(500));
assert!(
Ledger::<Test>::get(11).unwrap().active == 1000 &&
Validators::<Test>::contains_key(11) &&
!Nominators::<Test>::contains_key(11)
);
assert_eq!(<Staking as ScoreProvider<_>>::score(&11), Some(1000));
});
}
}
#[test]
fn from_most_staked_to_least_staked() {
ExtBuilder::default()
.nominate(true)
.set_status(51, StakerStatus::Validator)
.set_status(41, StakerStatus::Nominator(vec![51]))
.set_status(101, StakerStatus::Validator)
.set_stake(41, 11000)
.set_stake(51, 2500)
.set_stake(101, 35)
.build_and_execute(|| {
assert_eq!(THRESHOLDS.to_vec(), [10, 20, 30, 40, 50, 60, 1_000, 2_000, 10_000]);
assert_eq!(
<Test as Config>::VoterList::iter()
.collect::<Vec<_>>()
.into_iter()
.map(|v| (v, <Test as Config>::VoterList::get_score(&v).unwrap()))
.collect::<Vec<_>>(),
vec![(41, 11000), (51, 2500), (11, 1000), (21, 1000), (31, 500), (101, 35)],
);
});
}