Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion node/src/parachain/dev_chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{sr25519, Pair, Public};
use sp_runtime::{
traits::{IdentifyAccount, Verify},
Perbill,
Perbill, Permill,
};

/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
Expand Down Expand Up @@ -133,6 +133,8 @@ fn configure_genesis(
parachain_staking: ParachainStakingConfig {
stakers,
max_candidate_stake: staking::MAX_COLLATOR_STAKE,
max_commission_change: Permill::from_percent(100),
min_commission_change_interval: 0,
},
inflation_manager: Default::default(),
block_reward: BlockRewardConfig {
Expand Down
4 changes: 3 additions & 1 deletion node/src/parachain/krest_chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use peaq_primitives_xcm::{AccountId, Balance};
use runtime_common::TOKEN_DECIMALS;
use sc_service::{ChainType, Properties};
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_runtime::Perbill;
use sp_runtime::{Perbill, Permill};

use crate::parachain::dev_chain_spec::{authority_keys_from_seed, get_account_id_from_seed};

Expand Down Expand Up @@ -118,6 +118,8 @@ fn configure_genesis(
parachain_staking: ParachainStakingConfig {
stakers,
max_candidate_stake: staking::MAX_COLLATOR_STAKE,
max_commission_change: Permill::from_percent(100),
min_commission_change_interval: 0,
},
inflation_manager: Default::default(),
block_reward: BlockRewardConfig {
Expand Down
4 changes: 3 additions & 1 deletion node/src/parachain/peaq_chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use peaq_runtime::{
use runtime_common::TOKEN_DECIMALS;
use sc_service::{ChainType, Properties};
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_runtime::Perbill;
use sp_runtime::{Perbill, Permill};

use crate::parachain::dev_chain_spec::{authority_keys_from_seed, get_account_id_from_seed};

Expand Down Expand Up @@ -122,6 +122,8 @@ fn configure_genesis(
parachain_staking: ParachainStakingConfig {
stakers,
max_candidate_stake: staking::MAX_COLLATOR_STAKE,
max_commission_change: Permill::from_percent(100),
min_commission_change_interval: 0,
},
inflation_manager: Default::default(),
block_reward: BlockRewardConfig {
Expand Down
107 changes: 94 additions & 13 deletions pallets/parachain-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ pub mod pallet {
CommissionTooHigh,
/// Sudo cannot force new round if payouts are ongoing
PayoutsOngoing,
/// The commission change is too high.
CommissionChangeTooHigh,
/// The commission change is too frequent.
CommissionChangeTooEarly,
}

#[pallet::event]
Expand Down Expand Up @@ -519,6 +523,12 @@ pub mod pallet {
/// The commission for a collator has been changed.
/// \[collator's account, new commission\]
CollatorCommissionChanged(T::AccountId, Permill),
/// The commission maximum change has been changed.
/// \[new value\]
MaxCommissionChangeUpdated(Permill),
/// The delay between two commission changes has been changed.
/// \[new value\]
CommissionChangeIntervalUpdated(BlockNumberFor<T>),
}

#[pallet::hooks]
Expand Down Expand Up @@ -677,15 +687,36 @@ pub mod pallet {
pub(crate) type DelayedPayoutInfo<T: Config> =
StorageValue<_, DelayedPayoutInfoT<SessionIndex, BalanceOf<T>>, OptionQuery>;

#[pallet::storage]
#[pallet::getter(fn last_commission_change)]
pub type LastCommissionChange<T: Config> =
StorageMap<_, Blake2_128Concat, T::AccountId, BlockNumberFor<T>, ValueQuery>;

#[pallet::storage]
#[pallet::getter(fn max_commission_change)]
pub type MaxCommissionChange<T> = StorageValue<_, Permill, ValueQuery>;

#[pallet::storage]
#[pallet::getter(fn min_commission_change_interval)]
pub type MinCommissionChangeInterval<T: Config> =
StorageValue<_, BlockNumberFor<T>, ValueQuery>;

#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub stakers: GenesisStaker<T>,
pub max_candidate_stake: BalanceOf<T>,
pub max_commission_change: Permill,
pub min_commission_change_interval: BlockNumberFor<T>,
}

impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
Self { stakers: Default::default(), max_candidate_stake: Default::default() }
Self {
stakers: Default::default(),
max_candidate_stake: Default::default(),
max_commission_change: Permill::from_percent(100),
min_commission_change_interval: 0u32.into(),
}
}
}

Expand Down Expand Up @@ -722,6 +753,9 @@ pub mod pallet {
let round: RoundInfo<BlockNumberFor<T>> =
RoundInfo::new(0u32, 0u32.into(), T::DefaultBlocksPerRound::get());
<Round<T>>::put(round);

MaxCommissionChange::<T>::put(self.max_commission_change);
MinCommissionChangeInterval::<T>::put(self.min_commission_change_interval);
}
}

Expand Down Expand Up @@ -1969,20 +2003,67 @@ pub mod pallet {
))]
pub fn set_commission(origin: OriginFor<T>, commission: Permill) -> DispatchResult {
let collator = ensure_signed(origin)?;
CandidatePool::<T>::get(&collator).ok_or(Error::<T>::CandidateNotFound)?;
if commission > Permill::from_percent(100) {
return Err(Error::<T>::CommissionTooHigh.into())
}
let current_block = <frame_system::Pallet<T>>::block_number();

<crate::pallet::CandidatePool<T>>::mutate(&collator, |maybe_candidate| {
if let Some(candidate) = maybe_candidate {
candidate.set_commission(commission);
}
});
// Check if the collator exists
let mut candidate =
CandidatePool::<T>::get(&collator).ok_or(Error::<T>::CandidateNotFound)?;

// Check the time since the last commission change
let last_change = LastCommissionChange::<T>::get(&collator);
ensure!(
current_block >= last_change + MinCommissionChangeInterval::<T>::get(),
Error::<T>::CommissionChangeTooEarly
);

// Check the maximum change commission
let max_change = MaxCommissionChange::<T>::get();
let current_commission = candidate.commission;
let change = if commission > current_commission {
commission - current_commission
} else {
current_commission - commission
};
ensure!(change <= max_change, Error::<T>::CommissionChangeTooHigh);

// Update the commission and the last change time
candidate.set_commission(commission);
CandidatePool::<T>::insert(&collator, candidate);
LastCommissionChange::<T>::insert(&collator, current_block);

// Emit an event that the commission was updated
Self::deposit_event(Event::CollatorCommissionChanged(collator, commission));
Ok(())
}

#[pallet::call_index(20)]
#[pallet::weight(<T as crate::pallet::Config>::WeightInfo::set_max_commission_change(
Permill::from_percent(100).deconstruct()
))]
pub fn set_max_commission_change(
Comment thread
DocteurPing marked this conversation as resolved.
origin: OriginFor<T>,
new_max_commission_change: Permill,
) -> DispatchResult {
ensure_root(origin)?;

MaxCommissionChange::<T>::put(new_max_commission_change);

Self::deposit_event(Event::MaxCommissionChangeUpdated(new_max_commission_change));
Ok(())
}

#[pallet::call_index(21)]
#[pallet::weight(<T as crate::pallet::Config>::WeightInfo::set_min_commission_change_interval())]
pub fn set_min_commission_change_interval(
origin: OriginFor<T>,
new_min_commission_change_interval: BlockNumberFor<T>,
) -> DispatchResult {
ensure_root(origin)?;

MinCommissionChangeInterval::<T>::put(new_min_commission_change_interval);

// Emit an event that the commission was updated.
Self::deposit_event(crate::pallet::Event::CollatorCommissionChanged(
collator, commission,
Self::deposit_event(Event::CommissionChangeIntervalUpdated(
new_min_commission_change_interval,
));
Ok(())
}
Expand Down
12 changes: 10 additions & 2 deletions pallets/parachain-staking/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
use crate::{
pallet::{Config, Pallet, OLD_STAKING_ID, STAKING_ID},
types::{Candidate, OldCandidate},
CandidatePool, ForceNewRound, Round,
CandidatePool, ForceNewRound, MaxCommissionChange, MinCommissionChangeInterval, Round,
};
use frame_support::{
pallet_prelude::{GetStorageVersion, StorageVersion},
traits::{Get, LockableCurrency, WithdrawReasons},
weights::Weight,
};
use frame_system::pallet_prelude::BlockNumberFor;
use pallet_balances::Locks;
use sp_runtime::Permill;

Expand All @@ -20,8 +21,9 @@ pub enum Versions {
_V8 = 8,
V9 = 9,
V10 = 10,
#[default]
V11 = 11,
#[default]
V12 = 12,
}

pub(crate) fn on_runtime_upgrade<T: Config>() -> Weight {
Expand Down Expand Up @@ -102,6 +104,12 @@ mod upgrade {

log::info!("V11 Migrating Done.");
}

if onchain_storage_version < StorageVersion::new(Versions::V12 as u16) {
// Set the value of MaxCommissionChange to 10%
MaxCommissionChange::<T>::put(Permill::from_percent(10));
MinCommissionChangeInterval::<T>::put(BlockNumberFor::<T>::from(0u32));
}
// update onchain storage version
StorageVersion::new(Versions::default() as u16).put::<Pallet<T>>();
weight_writes += 1;
Expand Down
14 changes: 10 additions & 4 deletions pallets/parachain-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use sp_runtime::{
impl_opaque_keys,
testing::UintAuthorityId,
traits::{BlakeTwo256, ConvertInto, IdentityLookup, OpaqueKeys},
BuildStorage, Perbill,
BuildStorage, Perbill, Permill,
};
use sp_std::fmt::Debug;

Expand Down Expand Up @@ -154,6 +154,7 @@ parameter_types! {
pub const MinDelegatorStake: Balance = 5;
pub const MinDelegation: Balance = 3;
pub const MaxUnstakeRequests: u32 = 6;

}

impl Config for Test {
Expand Down Expand Up @@ -278,9 +279,14 @@ impl ExtBuilder {
for delegator in self.delegators.clone() {
stakers.push((delegator.0, Some(delegator.1), delegator.2));
}
stake::GenesisConfig::<Test> { stakers, max_candidate_stake: 160_000_000 * DECIMALS }
.assimilate_storage(&mut t)
.expect("Parachain Staking's storage can be assimilated");
stake::GenesisConfig::<Test> {
stakers,
max_candidate_stake: 160_000_000 * DECIMALS,
max_commission_change: Permill::from_percent(10),
min_commission_change_interval: 1,
}
.assimilate_storage(&mut t)
.expect("Parachain Staking's storage can be assimilated");

// stashes are the AccountId
let session_keys: Vec<_> = self
Expand Down
Loading
Loading