Newer
Older
// errors
assert_noop!(
Staking::scale_validator_count(RuntimeOrigin::root(), Percent::from_percent(126)),
Error::<Test>::TooManyValidators,
);
})
}
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
#[test]
fn set_min_commission_works_with_admin_origin() {
ExtBuilder::default().build_and_execute(|| {
// no minimum commission set initially
assert_eq!(MinCommission::<Test>::get(), Zero::zero());
// root can set min commission
assert_ok!(Staking::set_min_commission(RuntimeOrigin::root(), Perbill::from_percent(10)));
assert_eq!(MinCommission::<Test>::get(), Perbill::from_percent(10));
// Non privileged origin can not set min_commission
assert_noop!(
Staking::set_min_commission(RuntimeOrigin::signed(2), Perbill::from_percent(15)),
BadOrigin
);
// Admin Origin can set min commission
assert_ok!(Staking::set_min_commission(
RuntimeOrigin::signed(1),
Perbill::from_percent(15),
));
// setting commission below min_commission fails
assert_noop!(
Staking::validate(
RuntimeOrigin::signed(11),
ValidatorPrefs { commission: Perbill::from_percent(14), blocked: false }
),
Error::<Test>::CommissionTooLow
);
// setting commission >= min_commission works
assert_ok!(Staking::validate(
RuntimeOrigin::signed(11),
ValidatorPrefs { commission: Perbill::from_percent(15), blocked: false }
));
})
}
mod staking_interface {
use frame_support::storage::with_storage_layer;
use sp_staking::StakingInterface;
use super::*;
#[test]
fn force_unstake_with_slash_works() {
ExtBuilder::default().build_and_execute(|| {
// without slash
let _ = with_storage_layer::<(), _, _>(|| {
// bond an account, can unstake
assert_eq!(Staking::bonded(&11), Some(11));
assert_ok!(<Staking as StakingInterface>::force_unstake(11));
Err(DispatchError::from("revert"))
});
// bond again and add a slash, still can unstake.
assert_eq!(Staking::bonded(&11), Some(11));
add_slash(&11);
assert_ok!(<Staking as StakingInterface>::force_unstake(11));
});
}
#[test]
fn do_withdraw_unbonded_with_wrong_slash_spans_works_as_expected() {
ExtBuilder::default().build_and_execute(|| {
on_offence_now(
&[OffenceDetails {
offender: (11, Staking::eras_stakers(active_era(), 11)),
reporters: vec![],
}],
&[Perbill::from_percent(100)],
);
assert_eq!(Staking::bonded(&11), Some(11));
Staking::withdraw_unbonded(RuntimeOrigin::signed(11), 0),
Error::<Test>::IncorrectSlashingSpans
);
let num_slashing_spans = Staking::slashing_spans(&11).map_or(0, |s| s.iter().count());
assert_ok!(Staking::withdraw_unbonded(
RuntimeOrigin::signed(11),
num_slashing_spans as u32
));
});
}
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
#[test]
fn status() {
ExtBuilder::default().build_and_execute(|| {
// stash of a validator is identified as a validator
assert_eq!(Staking::status(&11).unwrap(), StakerStatus::Validator);
// .. but not the controller.
assert!(Staking::status(&10).is_err());
// stash of nominator is identified as a nominator
assert_eq!(Staking::status(&101).unwrap(), StakerStatus::Nominator(vec![11, 21]));
// .. but not the controller.
assert!(Staking::status(&100).is_err());
// stash of chilled is identified as a chilled
assert_eq!(Staking::status(&41).unwrap(), StakerStatus::Idle);
// .. but not the controller.
assert!(Staking::status(&40).is_err());
// random other account.
assert!(Staking::status(&42).is_err());
})
}
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
mod ledger {
use super::*;
#[test]
fn paired_account_works() {
ExtBuilder::default().build_and_execute(|| {
assert_ok!(Staking::bond(
RuntimeOrigin::signed(10),
100,
RewardDestination::Controller
));
assert_eq!(<Bonded<Test>>::get(&10), Some(10));
assert_eq!(
StakingLedger::<Test>::paired_account(StakingAccount::Controller(10)),
Some(10)
);
assert_eq!(StakingLedger::<Test>::paired_account(StakingAccount::Stash(10)), Some(10));
assert_eq!(<Bonded<Test>>::get(&42), None);
assert_eq!(StakingLedger::<Test>::paired_account(StakingAccount::Controller(42)), None);
assert_eq!(StakingLedger::<Test>::paired_account(StakingAccount::Stash(42)), None);
// bond manually stash with different controller. This is deprecated but the migration
// has not been complete yet (controller: 100, stash: 200)
assert_ok!(bond_controller_stash(100, 200));
assert_eq!(<Bonded<Test>>::get(&200), Some(100));
assert_eq!(
StakingLedger::<Test>::paired_account(StakingAccount::Controller(100)),
Some(200)
);
assert_eq!(
StakingLedger::<Test>::paired_account(StakingAccount::Stash(200)),
Some(100)
);
})
}
#[test]
fn get_ledger_works() {
ExtBuilder::default().build_and_execute(|| {
// stash does not exist
assert!(StakingLedger::<Test>::get(StakingAccount::Stash(42)).is_err());
// bonded and paired
assert_eq!(<Bonded<Test>>::get(&11), Some(11));
match StakingLedger::<Test>::get(StakingAccount::Stash(11)) {
Ok(ledger) => {
assert_eq!(ledger.controller(), Some(11));
assert_eq!(ledger.stash, 11);
},
Err(_) => panic!("staking ledger must exist"),
};
// bond manually stash with different controller. This is deprecated but the migration
// has not been complete yet (controller: 100, stash: 200)
assert_ok!(bond_controller_stash(100, 200));
assert_eq!(<Bonded<Test>>::get(&200), Some(100));
match StakingLedger::<Test>::get(StakingAccount::Stash(200)) {
Ok(ledger) => {
assert_eq!(ledger.controller(), Some(100));
assert_eq!(ledger.stash, 200);
},
Err(_) => panic!("staking ledger must exist"),
};
match StakingLedger::<Test>::get(StakingAccount::Controller(100)) {
Ok(ledger) => {
assert_eq!(ledger.controller(), Some(100));
assert_eq!(ledger.stash, 200);
},
Err(_) => panic!("staking ledger must exist"),
};
})
}
#[test]
fn bond_works() {
ExtBuilder::default().build_and_execute(|| {
assert!(!StakingLedger::<Test>::is_bonded(StakingAccount::Stash(42)));
assert!(<Bonded<Test>>::get(&42).is_none());
let mut ledger: StakingLedger<Test> = StakingLedger::default_from(42);
let reward_dest = RewardDestination::Account(10);
assert_ok!(ledger.clone().bond(reward_dest));
assert!(StakingLedger::<Test>::is_bonded(StakingAccount::Stash(42)));
assert!(<Bonded<Test>>::get(&42).is_some());
assert_eq!(<Payee<Test>>::get(&42), reward_dest);
// cannot bond again.
assert!(ledger.clone().bond(reward_dest).is_err());
// once bonded, update works as expected.
ledger.claimed_rewards = bounded_vec![1];
assert_ok!(ledger.update());
})
}
#[test]
fn is_bonded_works() {
ExtBuilder::default().build_and_execute(|| {
assert!(!StakingLedger::<Test>::is_bonded(StakingAccount::Stash(42)));
assert!(!StakingLedger::<Test>::is_bonded(StakingAccount::Controller(42)));
// adds entry to Bonded without Ledger pair (should not happen).
<Bonded<Test>>::insert(42, 42);
assert!(!StakingLedger::<Test>::is_bonded(StakingAccount::Controller(42)));
assert_eq!(<Bonded<Test>>::get(&11), Some(11));
assert!(StakingLedger::<Test>::is_bonded(StakingAccount::Stash(11)));
assert!(StakingLedger::<Test>::is_bonded(StakingAccount::Controller(11)));
<Bonded<Test>>::remove(42); // ensures try-state checks pass.
})
}
}