Skip to content
Closed
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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 47 additions & 1 deletion cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ use sp_version::RuntimeVersion;
use testnet_parachains_constants::westend::{
consensus::*, currency::*, snowbridge::EthereumNetwork, time::*,
};
use westend_runtime_constants::time::DAYS as RC_DAYS;
use westend_runtime_constants::time::{DAYS as RC_DAYS, HOURS as RC_HOURS};
use xcm_config::{
ForeignAssetsConvertedConcreteId, LocationToAccountId, PoolAssetsConvertedConcreteId,
PoolAssetsPalletLocation, TrustBackedAssetsConvertedConcreteId,
Expand Down Expand Up @@ -1549,6 +1549,37 @@ parameter_types! {
);
}

/// Provides the initial `LastIssuanceTimestamp` for DAP migration.
pub struct DapLastIssuanceTimestamp;
impl frame_support::traits::Get<u64> for DapLastIssuanceTimestamp {
fn get() -> u64 {
pallet_staking_async::ActiveEra::<Runtime>::get()
.and_then(|era| era.start)
.unwrap_or(0)
}
}

/// Default budget: 85% staker rewards, 15% buffer, 0% validator incentive.
///
/// Keys are read from `BudgetRecipients` registered in the runtime config.
pub struct DefaultDapBudget;
impl frame_support::traits::Get<pallet_dap::BudgetAllocationMap> for DefaultDapBudget {
fn get() -> pallet_dap::BudgetAllocationMap {
use sp_runtime::Perbill;
use sp_staking::budget::BudgetRecipientList;

let recipients = <Runtime as pallet_dap::Config>::BudgetRecipients::recipients();
// [dap, StakerRewardRecipient, ValidatorIncentiveRecipient]
let percentages = [Perbill::from_percent(15), Perbill::from_percent(85), Perbill::zero()];

let mut map = pallet_dap::BudgetAllocationMap::new();
for ((key, _), perbill) in recipients.into_iter().zip(percentages) {
let _ = map.try_insert(key, perbill);
}
map
}
}

/// Migrations to apply on runtime upgrade.
pub type Migrations = (
// v9420
Expand Down Expand Up @@ -1588,6 +1619,8 @@ pub type Migrations = (
// permanent
pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
cumulus_pallet_aura_ext::migration::MigrateV0ToV1<Runtime>,
// unreleased
pallet_dap::migrations::MigrateV1ToV2<Runtime, DapLastIssuanceTimestamp, DefaultDapBudget>,
);

/// Asset Hub Westend has some undecodable storage, delete it.
Expand Down Expand Up @@ -2865,6 +2898,19 @@ fn ensure_key_ss58() {
assert_eq!(acc, RootMigController::sorted_members()[0]);
}

#[test]
fn issuance_cadence_smaller_than_era_length() {
use crate::staking::{RelaySessionDuration, SessionsPerEra};
let era_length_ms = SessionsPerEra::get() as u64 *
RelaySessionDuration::get() as u64 *
RELAY_CHAIN_SLOT_DURATION_MILLIS as u64;
let cadence = <Runtime as pallet_dap::Config>::IssuanceCadence::get();
assert!(
cadence < era_length_ms,
"IssuanceCadence ({cadence}ms) must be smaller than era length ({era_length_ms}ms)"
);
}

#[test]
fn ensure_epmb_weights_sane() {
use sp_io::TestExternalities;
Expand Down
60 changes: 34 additions & 26 deletions cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,29 +228,20 @@ impl pallet_bags_list::Config<VoterBagsListInstance> for Runtime {
type WeightInfo = weights::pallet_bags_list::WeightInfo<Runtime>;
}

pub struct EraPayout;
impl pallet_staking_async::EraPayout<Balance> for EraPayout {
fn era_payout(
_total_staked: Balance,
_total_issuance: Balance,
era_duration_millis: u64,
) -> (Balance, Balance) {
pub struct PolkadotIssuanceCurve;
impl sp_staking::budget::IssuanceCurve<Balance> for PolkadotIssuanceCurve {
fn issue(_total_issuance: Balance, elapsed_millis: u64) -> Balance {
const MILLISECONDS_PER_YEAR: u64 = (1000 * 3600 * 24 * 36525) / 100;
// A normal-sized era will have 1 / 365.25 here:
let relative_era_len =
FixedU128::from_rational(era_duration_millis.into(), MILLISECONDS_PER_YEAR.into());
let relative_period =
FixedU128::from_rational(elapsed_millis.into(), MILLISECONDS_PER_YEAR.into());

// Fixed total TI that we use as baseline for the issuance.
let fixed_total_issuance: i128 = 5_216_342_402_773_185_773;
let fixed_inflation_rate = FixedU128::from_rational(8, 100);
let yearly_emission = fixed_inflation_rate.saturating_mul_int(fixed_total_issuance);

let era_emission = relative_era_len.saturating_mul_int(yearly_emission);
// 15% to treasury, as per Polkadot ref 1139.
let to_treasury = FixedU128::from_rational(15, 100).saturating_mul_int(era_emission);
let to_stakers = era_emission.saturating_sub(to_treasury);

(to_stakers.saturated_into(), to_treasury.saturated_into())
let period_emission = relative_period.saturating_mul_int(yearly_emission);
period_emission.saturated_into()
}
}

Expand All @@ -268,8 +259,8 @@ parameter_types! {
pub const MaxControllersInDeprecationBatch: u32 = 751;
// alias for 16, which is the max nominations per nominator in the runtime.
pub const MaxNominations: u32 = <NposCompactSolution16 as frame_election_provider_support::NposSolution>::LIMIT as u32;
pub const MaxEraDuration: u64 = RelaySessionDuration::get() as u64 * RELAY_CHAIN_SLOT_DURATION_MILLIS as u64 * SessionsPerEra::get() as u64;
pub MaxPruningItems: u32 = 100;
pub const StakingPalletId: PalletId = PalletId(*b"py/stkng");
}

impl pallet_staking_async::Config for Runtime {
Expand All @@ -281,13 +272,15 @@ impl pallet_staking_async::Config for Runtime {
type CurrencyToVote = sp_staking::currency_to_vote::SaturatingCurrencyToVote;
type RewardRemainder = Dap;
type Slash = Dap;
type UnclaimedRewardHandler = Dap;
type Reward = ();
type GeneralPots = pallet_staking_async::Seed<StakingPalletId>;
type EraPots = pallet_staking_async::Seed<StakingPalletId>;
type SessionsPerEra = SessionsPerEra;
type BondingDuration = BondingDuration;
type NominatorFastUnbondDuration = NominatorFastUnbondDuration;
type SlashDeferDuration = SlashDeferDuration;
type AdminOrigin = EitherOf<EnsureRoot<AccountId>, StakingAdmin>;
type EraPayout = EraPayout;
type MaxExposurePageSize = MaxExposurePageSize;
type ElectionProvider = MultiBlockElection;
type VoterList = VoterList;
Expand All @@ -300,8 +293,15 @@ impl pallet_staking_async::Config for Runtime {
type EventListeners = (NominationPools, DelegatedStaking);
type PlanningEraOffset = ConstU32<6>;
type RcClientInterface = StakingRcClient;
type MaxEraDuration = MaxEraDuration;
type MaxPruningItems = MaxPruningItems;
type StakerRewardCalculator =
pallet_staking_async::reward::DefaultStakerRewardCalculator<Runtime>;
/// Vest validator incentive rewards over 2 days (in relay chain blocks).
type VestingDuration = ConstU32<{ 2 * RC_DAYS }>;
/// Relay chain session length in RC blocks (1 hour on Westend).
type BlocksPerSession = ConstU32<RC_HOURS>;
type ValidatorIncentivePayout =
pallet_staking_async::VestedIncentivePayout<pallet_vesting::Pallet<Runtime>>;
type WeightInfo = weights::pallet_staking_async::WeightInfo<Runtime>;
}

Expand Down Expand Up @@ -344,22 +344,30 @@ impl pallet_staking_async_rc_client::Config for Runtime {

parameter_types! {
pub const DapPalletId: frame_support::PalletId = frame_support::PalletId(*b"dap/buff");
/// Minimum time (ms) between issuance drips. 60s = drip at most once per minute.
/// Drip inflation every 60 seconds. Must be smaller than era length.
/// When adding DAP to other runtimes, copy the `issuance_cadence_smaller_than_era_length`
/// test from this runtime.
pub const IssuanceCadence: u64 = 60_000;
/// Safety ceiling (ms) for elapsed time in a single drip. Prevents over-minting after stalls.
/// Safety ceiling on elapsed time per drip: 10 minutes.
/// Prevents over-minting if blocks are delayed or chain stalls.
pub const MaxElapsedPerDrip: u64 = 600_000;
}

impl pallet_dap::Config for Runtime {
type Currency = Balances;
type PalletId = DapPalletId;
/// Noop — DAP does not mint until budget drip is enabled.
type IssuanceCurve = ();
type BudgetRecipients = (pallet_dap::Pallet<Runtime>,);
type Time = pallet_timestamp::Pallet<Runtime>;
type IssuanceCurve = PolkadotIssuanceCurve;
type BudgetRecipients = (
Dap,
pallet_staking_async::StakerRewardRecipient<pallet_staking_async::Seed<StakingPalletId>>,
pallet_staking_async::ValidatorIncentiveRecipient<
pallet_staking_async::Seed<StakingPalletId>,
>,
);
type Time = Timestamp;
type IssuanceCadence = IssuanceCadence;
type MaxElapsedPerDrip = MaxElapsedPerDrip;
type BudgetOrigin = frame_system::EnsureRoot<AccountId>;
type BudgetOrigin = EnsureRoot<AccountId>;
type WeightInfo = ();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,14 @@ impl<T: frame_system::Config> pallet_staking_async::WeightInfo for WeightInfo<T>
.saturating_add(Weight::from_parts(0, 0))
.saturating_add(T::DbWeight::get().writes(1))
}
fn set_max_commission() -> Weight {
// TODO(ank4n): Run benchmarks
todo!()
}
fn set_validator_self_stake_incentive_config() -> Weight {
// TODO(ank4n): Run benchmarks
todo!()
}
/// Storage: `System::Account` (r:1 w:0)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `Staking::VirtualStakers` (r:1 w:0)
Expand Down
2 changes: 1 addition & 1 deletion polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ impl pallet_bags_list::Config<VoterBagsListInstance> for Runtime {
}

pub struct EraPayout;
impl pallet_staking::EraPayout<Balance> for EraPayout {
impl sp_staking::EraPayout<Balance> for EraPayout {
fn era_payout(
_total_staked: Balance,
_total_issuance: Balance,
Expand Down
2 changes: 1 addition & 1 deletion polkadot/runtime/westend/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ use frame_support::{
WhitelistedStorageKeys,
},
};
use pallet_staking::EraPayout;
use sp_core::{crypto::Ss58Codec, hexdisplay::HexDisplay};
use sp_keyring::Sr25519Keyring::{self, Alice};
use sp_runtime::generic::Era;
use sp_staking::EraPayout;
use xcm_runtime_apis::conversions::LocationToAccountHelper;

const MILLISECONDS_PER_HOUR: u64 = 60 * 60 * 1000;
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/dap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ pub mod pallet {
use frame_system::pallet_prelude::*;

/// The in-code storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);

#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
Expand Down
19 changes: 5 additions & 14 deletions substrate/frame/nomination-pools/test-delegate-stake/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,6 @@ pallet_staking_reward_curve::build! {
parameter_types! {
pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &I_NPOS;
pub static BondingDuration: u32 = 3;
pub static EraPayout: (Balance, Balance) = (1000, 100);
}

/// A simple EraPayout implementation for testing that returns fixed values.
pub struct TestEraPayout;
impl pallet_staking_async::EraPayout<Balance> for TestEraPayout {
fn era_payout(
_total_staked: Balance,
_total_issuance: Balance,
_era_duration_millis: u64,
) -> (Balance, Balance) {
EraPayout::get()
}
}

/// A mock RcClientInterface for tests that don't need actual session/validator set management.
Expand All @@ -126,13 +113,17 @@ impl pallet_staking_async::Config for Runtime {
type Currency = Balances;
type AdminOrigin = frame_system::EnsureRoot<Self::AccountId>;
type BondingDuration = BondingDuration;
type EraPayout = TestEraPayout;
type ElectionProvider =
frame_election_provider_support::NoElection<(AccountId, BlockNumber, Staking, (), ())>;
type VoterList = VoterList;
type TargetList = pallet_staking_async::UseValidatorsMap<Self>;
type EventListeners = (Pools, DelegatedStaking);
type RcClientInterface = MockRcClient;
type VestingDuration = ConstU64<0>;
type BlocksPerSession = ConstU64<1>;
type ValidatorIncentivePayout = pallet_staking_async::ImmediateIncentivePayout<Balances>;
type StakerRewardCalculator =
pallet_staking_async::reward::DefaultStakerRewardCalculator<Runtime>;
}

parameter_types! {
Expand Down
5 changes: 5 additions & 0 deletions substrate/frame/staking-async/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ rand_chacha = { workspace = true }
scale-info = { features = ["derive", "serde"], workspace = true }
serde = { features = ["alloc", "derive"], workspace = true }
sp-application-crypto = { features = ["serde"], workspace = true }
sp-arithmetic = { workspace = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-npos-elections = { workspace = true }
Expand All @@ -42,6 +43,7 @@ frame-benchmarking = { workspace = true, default-features = true }
frame-support = { features = ["experimental"], workspace = true, default-features = true }
pallet-bags-list = { workspace = true, default-features = true }
pallet-balances = { workspace = true, default-features = true }
pallet-dap = { workspace = true, default-features = true }
rand_chacha = { workspace = true, default-features = true }
sp-tracing = { workspace = true, default-features = true }
substrate-test-utils = { workspace = true }
Expand All @@ -64,6 +66,7 @@ std = [
"scale-info/std",
"serde/std",
"sp-application-crypto/std",
"sp-arithmetic/std",
"sp-core/std",
"sp-core/std",
"sp-io/std",
Expand All @@ -79,6 +82,7 @@ runtime-benchmarks = [
"frame-system/runtime-benchmarks",
"pallet-bags-list/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-dap/runtime-benchmarks",
"pallet-staking-async-rc-client/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
Expand All @@ -89,6 +93,7 @@ try-runtime = [
"frame-system/try-runtime",
"pallet-bags-list/try-runtime",
"pallet-balances/try-runtime",
"pallet-dap/try-runtime",
"pallet-staking-async-rc-client/try-runtime",
"sp-runtime/try-runtime",
]
2 changes: 2 additions & 0 deletions substrate/frame/staking-async/integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pallet-dap = { workspace = true, default-features = true }
pallet-election-provider-multi-block = { workspace = true, default-features = true }
pallet-staking-async = { workspace = true, default-features = true }
pallet-staking-async-rc-client = { workspace = true, default-features = true }
pallet-vesting = { workspace = true, default-features = true }

# pallets we need in the RC
pallet-authorship = { workspace = true, default-features = true }
Expand All @@ -64,6 +65,7 @@ try-runtime = [

"pallet-staking-async-rc-client/try-runtime",
"pallet-staking-async/try-runtime",
"pallet-vesting/try-runtime",

"frame-election-provider-support/try-runtime",
"frame-support/try-runtime",
Expand Down
Loading