Skip to content
This repository has been archived by the owner on Mar 13, 2023. It is now read-only.

Commit

Permalink
Companion of paritytech/substrate#10347, !
Browse files Browse the repository at this point in the history
  • Loading branch information
aurexav committed Sep 8, 2022
1 parent e5ba1e7 commit c731998
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 19 deletions.
37 changes: 32 additions & 5 deletions frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,8 @@ pub mod pallet {
/// There are too many validators in the system. Governance needs to adjust the staking
/// settings to keep things safe for the runtime.
TooManyValidators,
/// Commission is too low. Must be at least `MinCommission`.
CommissionTooLow,
/// Payout - INSUFFICIENT
PayoutIns,
}
Expand Down Expand Up @@ -599,6 +601,12 @@ pub mod pallet {
#[pallet::storage]
pub type MinValidatorBond<T: Config> = StorageValue<_, RingBalance<T>, ValueQuery>;

/// The minimum amount of commission that validators can set.
///
/// If set to `0`, no limit exists.
#[pallet::storage]
pub type MinCommission<T: Config> = StorageValue<_, Perbill, ValueQuery>;

/// Map from all (unlocked) "controller" accounts to the info regarding the staking.
#[pallet::storage]
#[pallet::getter(fn ledger)]
Expand Down Expand Up @@ -888,6 +896,8 @@ pub mod pallet {
pub stakers: Vec<(AccountId<T>, AccountId<T>, RingBalance<T>, StakerStatus<AccountId<T>>)>,
pub min_nominator_bond: RingBalance<T>,
pub min_validator_bond: RingBalance<T>,
pub max_validator_count: Option<u32>,
pub max_nominator_count: Option<u32>,
pub payout_fraction: Perbill,
}
#[cfg(feature = "std")]
Expand All @@ -904,6 +914,8 @@ pub mod pallet {
stakers: Default::default(),
min_nominator_bond: Default::default(),
min_validator_bond: Default::default(),
max_validator_count: None,
max_nominator_count: None,
payout_fraction: Default::default(),
}
}
Expand All @@ -921,6 +933,12 @@ pub mod pallet {
<StorageVersion<T>>::put(Releases::V7_0_0);
<MinNominatorBond<T>>::put(self.min_nominator_bond);
<MinValidatorBond<T>>::put(self.min_validator_bond);
if let Some(x) = self.max_validator_count {
MaxValidatorsCount::<T>::put(x);
}
if let Some(x) = self.max_nominator_count {
MaxNominatorsCount::<T>::put(x);
}
<PayoutFraction<T>>::put(self.payout_fraction);

for (stash, controller, ring_to_be_bonded, status) in &self.stakers {
Expand Down Expand Up @@ -1599,6 +1617,9 @@ pub mod pallet {

let stash = &ledger.stash;

// ensure their commission is correct.
ensure!(prefs.commission >= <MinCommission<T>>::get(), <Error<T>>::CommissionTooLow);

// Only check limits if they are not already a validator.
if !<Validators<T>>::contains_key(stash) {
// If this error is reached, we need to adjust the `MinValidatorBond` and start
Expand Down Expand Up @@ -2227,35 +2248,41 @@ pub mod pallet {
Ok(())
}

/// Update the various staking limits this pallet.
/// Update the various staking configurations.
///
/// * `min_nominator_bond`: The minimum active bond needed to be a nominator.
/// * `min_validator_bond`: The minimum active bond needed to be a validator.
/// * `max_nominator_count`: The max number of users who can be a nominator at once. When
/// set to `None`, no limit is enforced.
/// * `max_validator_count`: The max number of users who can be a validator at once. When
/// set to `None`, no limit is enforced.
/// * `chill_threshold`: The ratio of `max_nominator_count` or `max_validator_count` which
/// should be filled in order for the `chill_other` transaction to work.
/// * `min_commission`: The minimum amount of commission that each validators must maintain.
/// This is checked only upon calling `validate`. Existing validators are not affected.
///
/// Origin must be Root to call this function.
///
/// NOTE: Existing nominators and validators will not be affected by this update.
/// to kick people under the new limits, `chill_other` should be called.
#[pallet::weight(T::WeightInfo::set_staking_limits())]
pub fn set_staking_limits(
#[pallet::weight(T::WeightInfo::set_staking_configs())]
pub fn set_staking_configs(
origin: OriginFor<T>,
min_nominator_bond: RingBalance<T>,
min_validator_bond: RingBalance<T>,
max_nominator_count: Option<u32>,
max_validator_count: Option<u32>,
threshold: Option<Percent>,
chill_threshold: Option<Percent>,
min_commission: Perbill,
) -> DispatchResult {
ensure_root(origin)?;

<MinNominatorBond<T>>::set(min_nominator_bond);
<MinValidatorBond<T>>::set(min_validator_bond);
<MaxNominatorsCount<T>>::set(max_nominator_count);
<MaxValidatorsCount<T>>::set(max_validator_count);
<ChillThreshold<T>>::set(threshold);
ChillThreshold::<T>::set(chill_threshold);
<MinCommission<T>>::set(min_commission);

Ok(())
}
Expand Down
75 changes: 64 additions & 11 deletions frame/staking/src/substrate_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4821,13 +4821,14 @@ mod election_data_provider {
);

// Change the minimum bond... but no limits.
assert_ok!(Staking::set_staking_limits(
assert_ok!(Staking::set_staking_configs(
Origin::root(),
1_500,
2_000,
None,
None,
None
None,
Zero::zero()
));

// Still can't chill these users
Expand All @@ -4841,13 +4842,14 @@ mod election_data_provider {
);

// Add limits, but no threshold
assert_ok!(Staking::set_staking_limits(
assert_ok!(Staking::set_staking_configs(
Origin::root(),
1_500,
2_000,
Some(10),
Some(10),
None
None,
Zero::zero()
));

// Still can't chill these users
Expand All @@ -4861,13 +4863,14 @@ mod election_data_provider {
);

// Add threshold, but no limits
assert_ok!(Staking::set_staking_limits(
assert_ok!(Staking::set_staking_configs(
Origin::root(),
1_500,
2_000,
None,
None,
Some(Percent::from_percent(0))
Some(Percent::from_percent(0)),
Zero::zero()
));

// Still can't chill these users
Expand All @@ -4881,13 +4884,14 @@ mod election_data_provider {
);

// Add threshold and limits
assert_ok!(Staking::set_staking_limits(
assert_ok!(Staking::set_staking_configs(
Origin::root(),
1_500,
2_000,
Some(10),
Some(10),
Some(Percent::from_percent(75))
Some(Percent::from_percent(75)),
Zero::zero()
));

// 16 people total because tests start with 2 active one
Expand Down Expand Up @@ -4925,13 +4929,14 @@ mod election_data_provider {

// Change the maximums
let max = 10;
assert_ok!(Staking::set_staking_limits(
assert_ok!(Staking::set_staking_configs(
Origin::root(),
10,
10,
Some(max),
Some(max),
Some(Percent::from_percent(0))
Some(Percent::from_percent(0)),
Zero::zero()
));

// can create `max - validator_count` validators
Expand Down Expand Up @@ -4997,7 +5002,15 @@ mod election_data_provider {
));

// No problem when we set to `None` again
assert_ok!(Staking::set_staking_limits(Origin::root(), 10, 10, None, None, None));
assert_ok!(Staking::set_staking_configs(
Origin::root(),
10,
10,
None,
None,
None,
Zero::zero()
));
assert_ok!(Staking::nominate(Origin::signed(last_nominator), vec![1]));
assert_ok!(Staking::validate(
Origin::signed(last_validator),
Expand All @@ -5006,3 +5019,43 @@ mod election_data_provider {
})
}
}

#[test]
fn min_commission_works() {
ExtBuilder::default().build_and_execute(|| {
assert_ok!(Staking::validate(
Origin::signed(10),
ValidatorPrefs { commission: Perbill::from_percent(5), blocked: false }
));

assert_ok!(Staking::set_staking_configs(
Origin::root(),
0,
0,
None,
None,
None,
Perbill::from_percent(10),
));

// can't make it less than 10 now
assert_noop!(
Staking::validate(
Origin::signed(10),
ValidatorPrefs { commission: Perbill::from_percent(5), blocked: false }
),
<Error<Test>>::CommissionTooLow
);

// can only change to higher.
assert_ok!(Staking::validate(
Origin::signed(10),
ValidatorPrefs { commission: Perbill::from_percent(10), blocked: false }
));

assert_ok!(Staking::validate(
Origin::signed(10),
ValidatorPrefs { commission: Perbill::from_percent(15), blocked: false }
));
})
}
6 changes: 3 additions & 3 deletions frame/staking/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub trait WeightInfo {
fn new_era(v: u32, n: u32) -> Weight;
fn get_npos_voters(v: u32, n: u32, s: u32) -> Weight;
fn get_npos_targets(v: u32) -> Weight;
fn set_staking_limits() -> Weight;
fn set_staking_configs() -> Weight;
fn chill_other() -> Weight;
}

Expand Down Expand Up @@ -277,7 +277,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(v as Weight)))
}

fn set_staking_limits() -> Weight {
fn set_staking_configs() -> Weight {
(6_398_000 as Weight).saturating_add(T::DbWeight::get().writes(4 as Weight))
}

Expand Down Expand Up @@ -501,7 +501,7 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(v as Weight)))
}

fn set_staking_limits() -> Weight {
fn set_staking_configs() -> Weight {
(6_398_000 as Weight).saturating_add(RocksDbWeight::get().writes(4 as Weight))
}

Expand Down

0 comments on commit c731998

Please sign in to comment.