mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 23:51:05 +00:00
Tvl pool staking (#1322)
What does this PR do? - Introduced the TotalValueLocked storage for nomination-pools. - introduced a slashing api in mock.rs - additional test for tracking a slashing event towards a pool without sub-pools - migration for the nomination-pools (V6 to V7) with `VersionedMigration` Why are these changes needed? this is the continuation of the work by @kianenigma in this [PR](https://github.com/paritytech/substrate/pull/13319) How were these changes implemented and what do they affect? - It's an extra StorageValue that's modified whenever funds flow in or out of staking for any of the `bonded_account` of `BondedPools` - The `PoolSlashed`event is now emitted even when no `SubPools` are found Closes https://github.com/paritytech/polkadot-sdk/issues/155 KSM: HHEEgVzcqL3kCXgsxSfJMbsTy8dxoTctuXtpY94n4s8F4pS --------- Co-authored-by: Liam Aharon <liam.aharon@hotmail.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com> Co-authored-by: Ankan <ankan.anurag@gmail.com> Co-authored-by: command-bot <>
This commit is contained in:
@@ -59,6 +59,9 @@ fn test_setup_works() {
|
||||
assert_eq!(StakingMock::bonding_duration(), 3);
|
||||
assert!(Metadata::<T>::contains_key(1));
|
||||
|
||||
// initial member.
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 10);
|
||||
|
||||
let last_pool = LastPoolId::<Runtime>::get();
|
||||
assert_eq!(
|
||||
BondedPool::<Runtime>::get(last_pool).unwrap(),
|
||||
@@ -218,10 +221,7 @@ mod bonded_pool {
|
||||
|
||||
// slash half of the pool's balance. expected result of `fn api_points_to_balance`
|
||||
// to be 1/2 of the pool's balance.
|
||||
StakingMock::set_bonded_balance(
|
||||
default_bonded_account(),
|
||||
Pools::depositor_min_bond() / 2,
|
||||
);
|
||||
StakingMock::slash_by(1, Pools::depositor_min_bond() / 2);
|
||||
assert_eq!(Pallet::<Runtime>::api_points_to_balance(1, 10), 5);
|
||||
|
||||
// if pool does not exist, points to balance ratio is 0.
|
||||
@@ -238,10 +238,7 @@ mod bonded_pool {
|
||||
|
||||
// slash half of the pool's balance. expect result of `fn api_balance_to_points`
|
||||
// to be 2 * of the balance to add to the pool.
|
||||
StakingMock::set_bonded_balance(
|
||||
default_bonded_account(),
|
||||
Pools::depositor_min_bond() / 2,
|
||||
);
|
||||
StakingMock::slash_by(1, Pools::depositor_min_bond() / 2);
|
||||
assert_eq!(Pallet::<Runtime>::api_balance_to_points(1, 10), 20);
|
||||
|
||||
// if pool does not exist, balance to points ratio is 0.
|
||||
@@ -637,12 +634,12 @@ mod join {
|
||||
// Given
|
||||
Currency::set_balance(&11, ExistentialDeposit::get() + 2);
|
||||
assert!(!PoolMembers::<Runtime>::contains_key(11));
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 10);
|
||||
|
||||
// When
|
||||
assert_ok!(Pools::join(RuntimeOrigin::signed(11), 2, 1));
|
||||
|
||||
// Then
|
||||
|
||||
assert_eq!(
|
||||
pool_events_since_last_call(),
|
||||
vec![
|
||||
@@ -651,6 +648,7 @@ mod join {
|
||||
Event::Bonded { member: 11, pool_id: 1, bonded: 2, joined: true },
|
||||
]
|
||||
);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 12);
|
||||
|
||||
assert_eq!(
|
||||
PoolMembers::<Runtime>::get(11).unwrap(),
|
||||
@@ -660,7 +658,7 @@ mod join {
|
||||
|
||||
// Given
|
||||
// The bonded balance is slashed in half
|
||||
StakingMock::set_bonded_balance(Pools::create_bonded_account(1), 6);
|
||||
StakingMock::slash_by(1, 6);
|
||||
|
||||
// And
|
||||
Currency::set_balance(&12, ExistentialDeposit::get() + 12);
|
||||
@@ -672,8 +670,12 @@ mod join {
|
||||
// Then
|
||||
assert_eq!(
|
||||
pool_events_since_last_call(),
|
||||
vec![Event::Bonded { member: 12, pool_id: 1, bonded: 12, joined: true }]
|
||||
vec![
|
||||
Event::PoolSlashed { pool_id: 1, balance: 6 },
|
||||
Event::Bonded { member: 12, pool_id: 1, bonded: 12, joined: true }
|
||||
]
|
||||
);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 18);
|
||||
|
||||
assert_eq!(
|
||||
PoolMembers::<Runtime>::get(12).unwrap(),
|
||||
@@ -2359,11 +2361,15 @@ mod unbond {
|
||||
.min_join_bond(10)
|
||||
.add_members(vec![(20, 20)])
|
||||
.build_and_execute(|| {
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 30);
|
||||
// can unbond to above limit
|
||||
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 5));
|
||||
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().active_points(), 15);
|
||||
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().unbonding_points(), 5);
|
||||
|
||||
// tvl remains unchanged.
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 30);
|
||||
|
||||
// cannot go to below 10:
|
||||
assert_noop!(
|
||||
Pools::unbond(RuntimeOrigin::signed(20), 20, 10),
|
||||
@@ -2669,8 +2675,9 @@ mod unbond {
|
||||
.add_members(vec![(40, 40), (550, 550)])
|
||||
.build_and_execute(|| {
|
||||
let ed = Currency::minimum_balance();
|
||||
// Given a slash from 600 -> 100
|
||||
StakingMock::set_bonded_balance(default_bonded_account(), 100);
|
||||
// Given a slash from 600 -> 500
|
||||
StakingMock::slash_by(1, 500);
|
||||
|
||||
// and unclaimed rewards of 600.
|
||||
Currency::set_balance(&default_reward_account(), ed + 600);
|
||||
|
||||
@@ -2702,8 +2709,9 @@ mod unbond {
|
||||
Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true },
|
||||
Event::Bonded { member: 40, pool_id: 1, bonded: 40, joined: true },
|
||||
Event::Bonded { member: 550, pool_id: 1, bonded: 550, joined: true },
|
||||
Event::PoolSlashed { pool_id: 1, balance: 100 },
|
||||
Event::PaidOut { member: 40, pool_id: 1, payout: 40 },
|
||||
Event::Unbonded { member: 40, pool_id: 1, points: 6, balance: 6, era: 3 }
|
||||
Event::Unbonded { member: 40, pool_id: 1, balance: 6, points: 6, era: 3 }
|
||||
]
|
||||
);
|
||||
|
||||
@@ -2863,6 +2871,7 @@ mod unbond {
|
||||
);
|
||||
|
||||
// When the root kicks then its ok
|
||||
// Account with ID 100 is kicked.
|
||||
assert_ok!(Pools::fully_unbond(RuntimeOrigin::signed(900), 100));
|
||||
|
||||
assert_eq!(
|
||||
@@ -2883,6 +2892,7 @@ mod unbond {
|
||||
);
|
||||
|
||||
// When the bouncer kicks then its ok
|
||||
// Account with ID 200 is kicked.
|
||||
assert_ok!(Pools::fully_unbond(RuntimeOrigin::signed(902), 200));
|
||||
|
||||
assert_eq!(
|
||||
@@ -2921,7 +2931,7 @@ mod unbond {
|
||||
);
|
||||
assert_eq!(
|
||||
*UnbondingBalanceMap::get().get(&default_bonded_account()).unwrap(),
|
||||
100 + 200
|
||||
vec![(3, 100), (3, 200)],
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -3020,7 +3030,10 @@ mod unbond {
|
||||
}
|
||||
);
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()).unwrap(), 0);
|
||||
assert_eq!(*UnbondingBalanceMap::get().get(&default_bonded_account()).unwrap(), 10);
|
||||
assert_eq!(
|
||||
*UnbondingBalanceMap::get().get(&default_bonded_account()).unwrap(),
|
||||
vec![(6, 10)]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3298,7 +3311,7 @@ mod unbond {
|
||||
assert_eq!(PoolMembers::<Runtime>::get(10).unwrap().unbonding_points(), 0);
|
||||
|
||||
// slash the default pool
|
||||
StakingMock::set_bonded_balance(Pools::create_bonded_account(1), 5);
|
||||
StakingMock::slash_by(1, 5);
|
||||
|
||||
// cannot unbond even 7, because the value of shares is now less.
|
||||
assert_noop!(
|
||||
@@ -3368,21 +3381,58 @@ mod pool_withdraw_unbonded {
|
||||
|
||||
#[test]
|
||||
fn pool_withdraw_unbonded_works() {
|
||||
ExtBuilder::default().build_and_execute(|| {
|
||||
// Given 10 unbonded directly against the pool account
|
||||
assert_ok!(StakingMock::unbond(&default_bonded_account(), 5));
|
||||
// and the pool account only has 10 balance
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(5));
|
||||
assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(10));
|
||||
assert_eq!(Currency::free_balance(&default_bonded_account()), 10);
|
||||
ExtBuilder::default().add_members(vec![(20, 10)]).build_and_execute(|| {
|
||||
// Given 10 unbond'ed directly against the pool account
|
||||
|
||||
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 5));
|
||||
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(15));
|
||||
assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(20));
|
||||
assert_eq!(Balances::free_balance(&default_bonded_account()), 20);
|
||||
|
||||
// When
|
||||
CurrentEra::set(StakingMock::current_era() + StakingMock::bonding_duration() + 1);
|
||||
assert_ok!(Pools::pool_withdraw_unbonded(RuntimeOrigin::signed(10), 1, 0));
|
||||
|
||||
// Then there unbonding balance is no longer locked
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(5));
|
||||
assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(5));
|
||||
assert_eq!(Currency::free_balance(&default_bonded_account()), 10);
|
||||
// Then their unbonding balance is no longer locked
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(15));
|
||||
assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(15));
|
||||
assert_eq!(Balances::free_balance(&default_bonded_account()), 20);
|
||||
});
|
||||
}
|
||||
#[test]
|
||||
fn pool_withdraw_unbonded_creates_tvl_diff() {
|
||||
ExtBuilder::default().add_members(vec![(20, 10)]).build_and_execute(|| {
|
||||
// Given 10 unbond'ed directly against the pool account
|
||||
assert_ok!(Pools::unbond(RuntimeOrigin::signed(20), 20, 5));
|
||||
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(15));
|
||||
assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(20));
|
||||
assert_eq!(Balances::free_balance(&default_bonded_account()), 20);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 20);
|
||||
|
||||
// When
|
||||
CurrentEra::set(StakingMock::current_era() + StakingMock::bonding_duration() + 1);
|
||||
assert_ok!(Pools::pool_withdraw_unbonded(RuntimeOrigin::signed(10), 1, 0));
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 15);
|
||||
|
||||
let member_balance = PoolMembers::<T>::iter()
|
||||
.map(|(_, member)| member.total_balance())
|
||||
.reduce(|acc, total_balance| acc + total_balance)
|
||||
.unwrap_or_default();
|
||||
|
||||
// Then their unbonding balance is no longer locked
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()), Ok(15));
|
||||
assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(15));
|
||||
assert_eq!(Currency::free_balance(&default_bonded_account()), 20);
|
||||
|
||||
// The difference between TVL and member_balance is exactly the difference between
|
||||
// `total_stake` and the `free_balance`.
|
||||
// This relation is not guaranteed in the wild as arbitrary transfers towards
|
||||
// `free_balance` can be made to the pool that are not accounted for.
|
||||
let non_locked_balance = Balances::free_balance(&default_bonded_account()) -
|
||||
StakingMock::total_stake(&default_bonded_account()).unwrap();
|
||||
assert_eq!(member_balance, TotalValueLocked::<T>::get() + non_locked_balance);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3412,24 +3462,33 @@ mod withdraw_unbonded {
|
||||
let unbond_pool = sub_pools.with_era.get_mut(&3).unwrap();
|
||||
// Sanity check
|
||||
assert_eq!(*unbond_pool, UnbondPool { points: 550 + 40, balance: 550 + 40 });
|
||||
assert_eq!(TotalValueLocked::<Runtime>::get(), 600);
|
||||
|
||||
// Simulate a slash to the pool with_era(current_era), decreasing the balance by
|
||||
// half
|
||||
{
|
||||
unbond_pool.balance /= 2; // 295
|
||||
SubPoolsStorage::<Runtime>::insert(1, sub_pools);
|
||||
|
||||
// Adjust the TVL for this non-api usage (direct sub-pool modification)
|
||||
TotalValueLocked::<Runtime>::mutate(|x| *x -= 295);
|
||||
|
||||
// Update the equivalent of the unbonding chunks for the `StakingMock`
|
||||
let mut x = UnbondingBalanceMap::get();
|
||||
*x.get_mut(&default_bonded_account()).unwrap() /= 5;
|
||||
x.get_mut(&default_bonded_account())
|
||||
.unwrap()
|
||||
.get_mut(current_era as usize)
|
||||
.unwrap()
|
||||
.1 /= 2;
|
||||
UnbondingBalanceMap::set(&x);
|
||||
|
||||
Currency::set_balance(
|
||||
&default_bonded_account(),
|
||||
Currency::free_balance(&default_bonded_account()) / 2, // 300
|
||||
);
|
||||
StakingMock::set_bonded_balance(
|
||||
default_bonded_account(),
|
||||
StakingMock::active_stake(&default_bonded_account()).unwrap() / 2,
|
||||
);
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()).unwrap(), 10);
|
||||
StakingMock::slash_by(1, 5);
|
||||
assert_eq!(StakingMock::active_stake(&default_bonded_account()).unwrap(), 5);
|
||||
};
|
||||
|
||||
// Advance the current_era to ensure all `with_era` pools will be merged into
|
||||
@@ -3465,6 +3524,7 @@ mod withdraw_unbonded {
|
||||
era: 3
|
||||
},
|
||||
Event::Unbonded { member: 40, pool_id: 1, points: 40, balance: 40, era: 3 },
|
||||
Event::PoolSlashed { pool_id: 1, balance: 5 }
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -3552,7 +3612,7 @@ mod withdraw_unbonded {
|
||||
|
||||
// Given
|
||||
// current bond is 600, we slash it all to 300.
|
||||
StakingMock::set_bonded_balance(default_bonded_account(), 300);
|
||||
StakingMock::slash_by(1, 300);
|
||||
Currency::set_balance(&default_bonded_account(), 300);
|
||||
assert_eq!(StakingMock::total_stake(&default_bonded_account()), Ok(300));
|
||||
|
||||
@@ -3572,6 +3632,7 @@ mod withdraw_unbonded {
|
||||
Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true },
|
||||
Event::Bonded { member: 40, pool_id: 1, bonded: 40, joined: true },
|
||||
Event::Bonded { member: 550, pool_id: 1, bonded: 550, joined: true },
|
||||
Event::PoolSlashed { pool_id: 1, balance: 300 },
|
||||
Event::Unbonded { member: 40, pool_id: 1, balance: 20, points: 20, era: 3 },
|
||||
Event::Unbonded {
|
||||
member: 550,
|
||||
@@ -4051,6 +4112,7 @@ mod withdraw_unbonded {
|
||||
#[test]
|
||||
fn full_multi_step_withdrawing_non_depositor() {
|
||||
ExtBuilder::default().add_members(vec![(100, 100)]).build_and_execute(|| {
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 110);
|
||||
// given
|
||||
assert_ok!(Pools::unbond(RuntimeOrigin::signed(100), 100, 75));
|
||||
assert_eq!(
|
||||
@@ -4058,6 +4120,9 @@ mod withdraw_unbonded {
|
||||
member_unbonding_eras!(3 => 75)
|
||||
);
|
||||
|
||||
// tvl unchanged.
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 110);
|
||||
|
||||
// progress one era and unbond the leftover.
|
||||
CurrentEra::set(1);
|
||||
assert_ok!(Pools::unbond(RuntimeOrigin::signed(100), 100, 25));
|
||||
@@ -4070,6 +4135,8 @@ mod withdraw_unbonded {
|
||||
Pools::withdraw_unbonded(RuntimeOrigin::signed(100), 100, 0),
|
||||
Error::<Runtime>::CannotWithdrawAny
|
||||
);
|
||||
// tvl unchanged.
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 110);
|
||||
|
||||
// now the 75 should be free.
|
||||
CurrentEra::set(3);
|
||||
@@ -4089,6 +4156,8 @@ mod withdraw_unbonded {
|
||||
PoolMembers::<Runtime>::get(100).unwrap().unbonding_eras,
|
||||
member_unbonding_eras!(4 => 25)
|
||||
);
|
||||
// tvl updated
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 35);
|
||||
|
||||
// the 25 should be free now, and the member removed.
|
||||
CurrentEra::set(4);
|
||||
@@ -4398,6 +4467,7 @@ mod create {
|
||||
let next_pool_stash = Pools::create_bonded_account(2);
|
||||
let ed = Currency::minimum_balance();
|
||||
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 10);
|
||||
assert!(!BondedPools::<Runtime>::contains_key(2));
|
||||
assert!(!RewardPools::<Runtime>::contains_key(2));
|
||||
assert!(!PoolMembers::<Runtime>::contains_key(11));
|
||||
@@ -4411,6 +4481,7 @@ mod create {
|
||||
456,
|
||||
789
|
||||
));
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 10 + StakingMock::minimum_nominator_bond());
|
||||
|
||||
assert_eq!(Currency::free_balance(&11), 0);
|
||||
assert_eq!(
|
||||
@@ -4701,9 +4772,10 @@ mod set_state {
|
||||
|
||||
// Given
|
||||
unsafe_set_state(1, PoolState::Open);
|
||||
let mut bonded_pool = BondedPool::<Runtime>::get(1).unwrap();
|
||||
bonded_pool.points = 100;
|
||||
bonded_pool.put();
|
||||
// slash the pool to the point that `max_points_to_balance` ratio is
|
||||
// surpassed. Making this pool destroyable by anyone.
|
||||
StakingMock::slash_by(1, 10);
|
||||
|
||||
// When
|
||||
assert_ok!(Pools::set_state(RuntimeOrigin::signed(11), 1, PoolState::Destroying));
|
||||
// Then
|
||||
@@ -4729,6 +4801,7 @@ mod set_state {
|
||||
pool_events_since_last_call(),
|
||||
vec![
|
||||
Event::StateChanged { pool_id: 1, new_state: PoolState::Destroying },
|
||||
Event::PoolSlashed { pool_id: 1, balance: 0 },
|
||||
Event::StateChanged { pool_id: 1, new_state: PoolState::Destroying },
|
||||
Event::StateChanged { pool_id: 1, new_state: PoolState::Destroying }
|
||||
]
|
||||
@@ -4927,8 +5000,10 @@ mod bond_extra {
|
||||
assert_eq!(PoolMembers::<Runtime>::get(10).unwrap().points, 10);
|
||||
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().points, 20);
|
||||
assert_eq!(BondedPools::<Runtime>::get(1).unwrap().points, 30);
|
||||
|
||||
assert_eq!(Currency::free_balance(&10), 35);
|
||||
assert_eq!(Currency::free_balance(&20), 20);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 30);
|
||||
|
||||
// when
|
||||
assert_ok!(Pools::bond_extra(RuntimeOrigin::signed(10), BondExtra::Rewards));
|
||||
@@ -4936,6 +5011,8 @@ mod bond_extra {
|
||||
|
||||
// then
|
||||
assert_eq!(Currency::free_balance(&10), 35);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 31);
|
||||
|
||||
// 10's share of the reward is 1/3, since they gave 10/30 of the total shares.
|
||||
assert_eq!(PoolMembers::<Runtime>::get(10).unwrap().points, 10 + 1);
|
||||
assert_eq!(BondedPools::<Runtime>::get(1).unwrap().points, 30 + 1);
|
||||
@@ -4945,6 +5022,8 @@ mod bond_extra {
|
||||
|
||||
// then
|
||||
assert_eq!(Currency::free_balance(&20), 20);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 33);
|
||||
|
||||
// 20's share of the rewards is the other 2/3 of the rewards, since they have 20/30 of
|
||||
// the shares
|
||||
assert_eq!(PoolMembers::<Runtime>::get(20).unwrap().points, 20 + 2);
|
||||
@@ -5354,7 +5433,7 @@ mod reward_counter_precision {
|
||||
);
|
||||
|
||||
// slash this pool by 99% of that.
|
||||
StakingMock::set_bonded_balance(default_bonded_account(), DOT + pool_bond / 100);
|
||||
StakingMock::slash_by(1, pool_bond * 99 / 100);
|
||||
|
||||
// some whale now joins with the other half ot the total issuance. This will trigger an
|
||||
// overflow. This test is actually a bit too lenient because all the reward counters are
|
||||
@@ -6868,3 +6947,73 @@ mod commission {
|
||||
})
|
||||
}
|
||||
}
|
||||
mod slash {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn slash_no_subpool_is_tracked() {
|
||||
let bonded = |points, member_counter| BondedPool::<Runtime> {
|
||||
id: 1,
|
||||
inner: BondedPoolInner {
|
||||
commission: Commission::default(),
|
||||
member_counter,
|
||||
points,
|
||||
roles: DEFAULT_ROLES,
|
||||
state: PoolState::Open,
|
||||
},
|
||||
};
|
||||
ExtBuilder::default().with_check(0).build_and_execute(|| {
|
||||
// Given
|
||||
Currency::set_balance(&11, ExistentialDeposit::get() + 2);
|
||||
assert!(!PoolMembers::<Runtime>::contains_key(11));
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 10);
|
||||
|
||||
// When
|
||||
assert_ok!(Pools::join(RuntimeOrigin::signed(11), 2, 1));
|
||||
|
||||
// Then
|
||||
assert_eq!(
|
||||
pool_events_since_last_call(),
|
||||
vec![
|
||||
Event::Created { depositor: 10, pool_id: 1 },
|
||||
Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true },
|
||||
Event::Bonded { member: 11, pool_id: 1, bonded: 2, joined: true },
|
||||
]
|
||||
);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 12);
|
||||
|
||||
assert_eq!(
|
||||
PoolMembers::<Runtime>::get(11).unwrap(),
|
||||
PoolMember::<Runtime> { pool_id: 1, points: 2, ..Default::default() }
|
||||
);
|
||||
assert_eq!(BondedPool::<Runtime>::get(1).unwrap(), bonded(12, 2));
|
||||
|
||||
// Given
|
||||
// The bonded balance is slashed in half
|
||||
StakingMock::slash_by(1, 6);
|
||||
|
||||
// And
|
||||
Currency::set_balance(&12, ExistentialDeposit::get() + 12);
|
||||
assert!(!PoolMembers::<Runtime>::contains_key(12));
|
||||
|
||||
// When
|
||||
assert_ok!(Pools::join(RuntimeOrigin::signed(12), 12, 1));
|
||||
|
||||
// Then
|
||||
assert_eq!(
|
||||
pool_events_since_last_call(),
|
||||
vec![
|
||||
Event::PoolSlashed { pool_id: 1, balance: 6 },
|
||||
Event::Bonded { member: 12, pool_id: 1, bonded: 12, joined: true }
|
||||
]
|
||||
);
|
||||
assert_eq!(TotalValueLocked::<T>::get(), 18);
|
||||
|
||||
assert_eq!(
|
||||
PoolMembers::<Runtime>::get(12).unwrap(),
|
||||
PoolMember::<Runtime> { pool_id: 1, points: 24, ..Default::default() }
|
||||
);
|
||||
assert_eq!(BondedPool::<Runtime>::get(1).unwrap(), bonded(12 + 24, 3));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user