#![cfg(test)]
mod mock;
use frame_support::{assert_noop, assert_ok, traits::Currency};
use mock::*;
use pallet_nomination_pools::{
BondExtra, BondedPools, Error as PoolsError, Event as PoolsEvent, LastPoolId, PoolMember,
PoolMembers, PoolState,
};
use pallet_staking::{
CurrentEra, Error as StakingError, Event as StakingEvent, Payee, RewardDestination,
};
use sp_runtime::{bounded_btree_map, traits::Zero};
#[test]
fn pool_lifecycle_e2e() {
new_test_ext().execute_with(|| {
assert_eq!(Balances::minimum_balance(), 5);
assert_eq!(CurrentEra::<T>::get(), None);
assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10));
assert_eq!(LastPoolId::<Runtime>::get(), 1);
assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true },
]
);
assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1));
assert_ok!(Pools::join(RuntimeOrigin::signed(21), 10, 1));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 },
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true },
PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 10, joined: true },
]
);
assert_ok!(Pools::set_state(RuntimeOrigin::signed(10), 1, PoolState::Destroying));
assert_noop!(
Pools::unbond(RuntimeOrigin::signed(10), 10, 50),
PoolsError::<Runtime>::MinimumBondNotMet,
);
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10));
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().unbonding_eras.len(), 1);
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().points, 0);
assert_eq!(PoolMembers::<Runtime>::get(21).unwrap().unbonding_eras.len(), 1);
assert_eq!(PoolMembers::<Runtime>::get(21).unwrap().points, 0);
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::StateChanged { pool_id: 1, new_state: PoolState::Destroying },
PoolsEvent::Unbonded { member: 20, pool_id: 1, points: 10, balance: 10, era: 3 },
PoolsEvent::Unbonded { member: 21, pool_id: 1, points: 10, balance: 10, era: 3 },
]
);
assert_noop!(
Pools::unbond(RuntimeOrigin::signed(10), 10, 50),
PoolsError::<Runtime>::MinimumBondNotMet,
);
for e in 1..BondingDuration::get() {
CurrentEra::<Runtime>::set(Some(e));
assert_noop!(
Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0),
PoolsError::<Runtime>::CannotWithdrawAny
);
}
CurrentEra::<Runtime>::set(Some(BondingDuration::get()));
assert_noop!(
Pools::unbond(RuntimeOrigin::signed(10), 10, 50),
PoolsError::<Runtime>::MinimumBondNotMet,
);
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0));
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 0));
assert!(PoolMembers::<Runtime>::get(20).is_none());
assert!(PoolMembers::<Runtime>::get(21).is_none());
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 20 },]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Withdrawn { member: 20, pool_id: 1, points: 10, balance: 10 },
PoolsEvent::MemberRemoved { pool_id: 1, member: 20, released_balance: 0 },
PoolsEvent::Withdrawn { member: 21, pool_id: 1, points: 10, balance: 10 },
PoolsEvent::MemberRemoved { pool_id: 1, member: 21, released_balance: 0 },
]
);
assert_noop!(
Pools::unbond(RuntimeOrigin::signed(10), 10, 50),
pallet_staking::Error::<Runtime>::InsufficientBond
);
assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 50));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Chilled { stash: POOL1_BONDED },
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 50 },
]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 }]
);
CurrentEra::<Runtime>::set(Some(BondingDuration::get() * 2));
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 1));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 50 },]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Withdrawn { member: 10, pool_id: 1, points: 50, balance: 50 },
PoolsEvent::MemberRemoved { pool_id: 1, member: 10, released_balance: 0 },
PoolsEvent::Destroyed { pool_id: 1 }
]
);
})
}
#[test]
fn destroy_pool_with_erroneous_consumer() {
new_test_ext().execute_with(|| {
assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10));
assert_eq!(LastPoolId::<Runtime>::get(), 1);
assert_eq!(frame_system::Pallet::<T>::consumers(&POOL1_BONDED), 2);
assert_ok!(frame_system::Pallet::<T>::inc_consumers(&POOL1_BONDED));
assert_eq!(frame_system::Pallet::<T>::consumers(&POOL1_BONDED), 3);
assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true },
]
);
assert_ok!(Pools::set_state(RuntimeOrigin::signed(10), 1, PoolState::Destroying));
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::StateChanged { pool_id: 1, new_state: PoolState::Destroying },]
);
CurrentEra::<Runtime>::set(Some(1));
assert_noop!(
Pools::unbond(RuntimeOrigin::signed(10), 10, 50),
pallet_staking::Error::<Runtime>::InsufficientBond
);
assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 50));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Chilled { stash: POOL1_BONDED },
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 50 },
]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded {
member: 10,
pool_id: 1,
points: 50,
balance: 50,
era: 1 + 3
}]
);
CurrentEra::<Runtime>::set(Some(1 + 3));
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 1));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 50 },]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Withdrawn { member: 10, pool_id: 1, points: 50, balance: 50 },
PoolsEvent::MemberRemoved { pool_id: 1, member: 10, released_balance: 0 },
PoolsEvent::Destroyed { pool_id: 1 }
]
);
})
}
#[test]
fn pool_chill_e2e() {
new_test_ext().execute_with(|| {
assert_eq!(Balances::minimum_balance(), 5);
assert_eq!(CurrentEra::<T>::get(), None);
assert_ok!(Pools::create(RuntimeOrigin::signed(10), 50, 10, 10, 10));
assert_eq!(LastPoolId::<Runtime>::get(), 1);
assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 50 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true },
]
);
assert_ok!(Pools::join(RuntimeOrigin::signed(20), 10, 1));
assert_ok!(Pools::join(RuntimeOrigin::signed(21), 10, 1));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 },
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true },
PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 10, joined: true },
]
);
assert_ok!(Staking::set_staking_configs(
RuntimeOrigin::root(),
pallet_staking::ConfigOp::Set(55), pallet_staking::ConfigOp::Noop,
pallet_staking::ConfigOp::Noop,
pallet_staking::ConfigOp::Noop,
pallet_staking::ConfigOp::Noop,
pallet_staking::ConfigOp::Noop,
pallet_staking::ConfigOp::Noop,
));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10),);
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().unbonding_eras.len(), 1);
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().points, 0);
assert_noop!(
Pools::unbond(RuntimeOrigin::signed(21), 21, 10),
StakingError::<Runtime>::InsufficientBond,
);
assert_ok!(Pools::chill(RuntimeOrigin::signed(20), 1));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10));
assert_eq!(PoolMembers::<Runtime>::get(21).unwrap().unbonding_eras.len(), 1);
assert_eq!(PoolMembers::<Runtime>::get(21).unwrap().points, 0);
assert_noop!(
Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]),
PoolsError::<Runtime>::MinimumBondNotMet,
);
assert_ok!(Pools::join(RuntimeOrigin::signed(22), 10, 1));
assert_noop!(
Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]),
PoolsError::<Runtime>::MinimumBondNotMet,
);
assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::FreeBalance(10)));
assert_noop!(
Pools::chill(RuntimeOrigin::signed(20), 1),
PoolsError::<Runtime>::NotNominator,
);
assert_ok!(Pools::nominate(RuntimeOrigin::signed(10), 1, vec![1, 2, 3]));
CurrentEra::<Runtime>::set(Some(BondingDuration::get()));
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0));
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 0));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Chilled { stash: POOL1_BONDED },
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, StakingEvent::Bonded { stash: POOL1_BONDED, amount: 10 }, StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 20 },
]
);
})
}
#[test]
fn pool_slash_e2e() {
new_test_ext().execute_with(|| {
ExistentialDeposit::set(1);
assert_eq!(Balances::minimum_balance(), 1);
assert_eq!(CurrentEra::<T>::get(), None);
assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10));
assert_eq!(LastPoolId::<Runtime>::get(), 1);
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true },
]
);
assert_eq!(
Payee::<Runtime>::get(POOL1_BONDED),
Some(RewardDestination::Account(POOL1_REWARD))
);
assert_ok!(Pools::join(RuntimeOrigin::signed(20), 20, 1));
assert_ok!(Pools::join(RuntimeOrigin::signed(21), 20, 1));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Bonded { stash: POOL1_BONDED, amount: 20 },
StakingEvent::Bonded { stash: POOL1_BONDED, amount: 20 }
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true },
PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: 20, joined: true },
]
);
CurrentEra::<Runtime>::set(Some(1));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 10));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 4 },
PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: 10, points: 10, era: 4 }
]
);
CurrentEra::<Runtime>::set(Some(2));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 10));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 10));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 },
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 5 },
PoolsEvent::Unbonded { member: 20, pool_id: 1, balance: 10, points: 10, era: 5 },
PoolsEvent::Unbonded { member: 21, pool_id: 1, balance: 10, points: 10, era: 5 },
]
);
pallet_staking::slashing::do_slash::<Runtime>(
&POOL1_BONDED,
30,
&mut Default::default(),
&mut Default::default(),
2, );
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 30 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 5, balance: 15 },
PoolsEvent::PoolSlashed { pool_id: 1, balance: 15 }
]
);
CurrentEra::<Runtime>::set(Some(3));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, 10));
assert_eq!(
PoolMembers::<Runtime>::get(21).unwrap(),
PoolMember {
pool_id: 1,
points: 0,
last_recorded_reward_counter: Zero::zero(),
unbonding_eras: bounded_btree_map!(5 => 10, 6 => 5)
}
);
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 5 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded { member: 21, pool_id: 1, balance: 5, points: 5, era: 6 }]
);
CurrentEra::<Runtime>::set(Some(6));
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(20), 20, 0));
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(21), 21, 0));
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Withdrawn { member: 20, pool_id: 1, balance: 10 + 5, points: 20 },
PoolsEvent::MemberRemoved { pool_id: 1, member: 20, released_balance: 0 },
PoolsEvent::Withdrawn { member: 21, pool_id: 1, balance: 5 + 5, points: 15 },
PoolsEvent::MemberRemoved { pool_id: 1, member: 21, released_balance: 0 }
]
);
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 15 + 10 + 15 }]
);
assert_ok!(Pools::set_state(RuntimeOrigin::signed(10), 1, PoolState::Destroying));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 20));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: 10 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::StateChanged { pool_id: 1, new_state: PoolState::Destroying },
PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 10, balance: 10, era: 9 }
]
);
CurrentEra::<Runtime>::set(Some(9));
assert_eq!(
PoolMembers::<Runtime>::get(10).unwrap(),
PoolMember {
pool_id: 1,
points: 0,
last_recorded_reward_counter: Zero::zero(),
unbonding_eras: bounded_btree_map!(4 => 10, 5 => 10, 9 => 10)
}
);
assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(10), 10, 0));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Withdrawn { stash: POOL1_BONDED, amount: 10 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Withdrawn { member: 10, pool_id: 1, balance: 10 + 15, points: 30 },
PoolsEvent::MemberRemoved { pool_id: 1, member: 10, released_balance: 0 },
PoolsEvent::Destroyed { pool_id: 1 }
]
);
});
}
#[test]
fn pool_slash_proportional() {
new_test_ext().execute_with(|| {
ExistentialDeposit::set(1);
BondingDuration::set(28);
assert_eq!(Balances::minimum_balance(), 1);
assert_eq!(CurrentEra::<T>::get(), None);
assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10));
assert_eq!(LastPoolId::<T>::get(), 1);
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true },
]
);
let bond = 20;
assert_ok!(Pools::join(RuntimeOrigin::signed(20), bond, 1));
assert_ok!(Pools::join(RuntimeOrigin::signed(21), bond, 1));
assert_ok!(Pools::join(RuntimeOrigin::signed(22), bond, 1));
assert_eq!(
staking_events_since_last_call(),
vec![
StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond },
StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond },
StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond },
]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true },
PoolsEvent::Bonded { member: 21, pool_id: 1, bonded: bond, joined: true },
PoolsEvent::Bonded { member: 22, pool_id: 1, bonded: bond, joined: true },
]
);
CurrentEra::<T>::set(Some(99));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond },]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded {
member: 20,
pool_id: 1,
balance: bond,
points: bond,
era: 127
}]
);
CurrentEra::<T>::set(Some(100));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(21), 21, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond },]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded {
member: 21,
pool_id: 1,
balance: bond,
points: bond,
era: 128
}]
);
CurrentEra::<T>::set(Some(101));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(22), 22, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond },]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded {
member: 22,
pool_id: 1,
balance: bond,
points: bond,
era: 129
}]
);
assert_eq!(BondedPools::<T>::get(1).unwrap().points, 40);
pallet_staking::slashing::do_slash::<Runtime>(
&POOL1_BONDED,
50,
&mut Default::default(),
&mut Default::default(),
100,
);
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 50 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 128, balance: 7 },
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 129, balance: 8 },
PoolsEvent::PoolSlashed { pool_id: 1, balance: 15 }
]
);
});
}
#[test]
fn pool_slash_non_proportional_only_bonded_pool() {
new_test_ext().execute_with(|| {
ExistentialDeposit::set(1);
BondingDuration::set(28);
assert_eq!(Balances::minimum_balance(), 1);
assert_eq!(CurrentEra::<T>::get(), None);
assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true },
]
);
let bond = 20;
assert_ok!(Pools::join(RuntimeOrigin::signed(20), bond, 1));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond }]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true }]
);
CurrentEra::<T>::set(Some(99));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond }]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded {
member: 20,
pool_id: 1,
balance: bond,
points: bond,
era: 127
}]
);
CurrentEra::<T>::set(Some(100));
assert_eq!(BondedPools::<T>::get(1).unwrap().points, 40);
pallet_staking::slashing::do_slash::<Runtime>(
&POOL1_BONDED,
30,
&mut Default::default(),
&mut Default::default(),
100,
);
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 30 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::PoolSlashed { pool_id: 1, balance: 10 }]
);
});
}
#[test]
fn pool_slash_non_proportional_bonded_pool_and_chunks() {
new_test_ext().execute_with(|| {
ExistentialDeposit::set(1);
BondingDuration::set(28);
assert_eq!(Balances::minimum_balance(), 1);
assert_eq!(CurrentEra::<T>::get(), None);
assert_ok!(Pools::create(RuntimeOrigin::signed(10), 40, 10, 10, 10));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: 40 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::Created { depositor: 10, pool_id: 1 },
PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 40, joined: true },
]
);
let bond = 20;
assert_ok!(Pools::join(RuntimeOrigin::signed(20), bond, 1));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Bonded { stash: POOL1_BONDED, amount: bond }]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Bonded { member: 20, pool_id: 1, bonded: bond, joined: true }]
);
CurrentEra::<T>::set(Some(99));
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, bond));
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Unbonded { stash: POOL1_BONDED, amount: bond }]
);
assert_eq!(
pool_events_since_last_call(),
vec![PoolsEvent::Unbonded {
member: 20,
pool_id: 1,
balance: bond,
points: bond,
era: 127
}]
);
CurrentEra::<T>::set(Some(100));
assert_eq!(BondedPools::<T>::get(1).unwrap().points, 40);
pallet_staking::slashing::do_slash::<Runtime>(
&POOL1_BONDED,
50,
&mut Default::default(),
&mut Default::default(),
100,
);
assert_eq!(
staking_events_since_last_call(),
vec![StakingEvent::Slashed { staker: POOL1_BONDED, amount: 50 }]
);
assert_eq!(
pool_events_since_last_call(),
vec![
PoolsEvent::UnbondingPoolSlashed { pool_id: 1, era: 127, balance: 10 },
PoolsEvent::PoolSlashed { pool_id: 1, balance: 0 }
]
);
});
}