referrerpolicy=no-referrer-when-downgrade

Crate pallet_staking_async

Source
Expand description

§Staking Async Pallet

This pallet is a fork of the original pallet-staking, with a number of key differences:

  • It no longer has access to a secure timestamp, previously used to calculate the duration of an era.
  • It no longer has access to a pallet-session.
  • It no longer has access to a pallet-authorship.
  • It is capable of working with a multi-page ElectionProvider``, aka. pallet-election-provider-multi-block`.

While pallet-staking was somewhat general-purpose, this pallet is absolutely NOT right from the get-go: It is designed to be used ONLY in Polkadot/Kusama AssetHub system parachains.

The workings of this pallet can be divided into a number of subsystems, as follows.

§User Interactions

TODO

§Session and Era Rotation

TODO

§Exposure Collection

TODO

§Slashing Pipeline and Withdrawal Restrictions

This pallet implements a robust slashing mechanism that ensures the integrity of the staking system while preventing stakers from withdrawing funds that might still be subject to slashing.

§Overview of the Slashing Pipeline

The slashing process consists of multiple phases:

  1. Offence Reporting: Offences are reported from the relay chain through on_new_offences
  2. Queuing: Valid offences are added to the OffenceQueue for processing
  3. Processing: Offences are processed incrementally over multiple blocks
  4. Application: Slashes are either applied immediately or deferred based on configuration

§Phase 1: Offence Reporting

Offences are reported from the relay chain (e.g., from BABE, GRANDPA, BEEFY, or parachain modules) through the on_new_offences function:

struct Offence {
    offender: AccountId,        // The validator being slashed
    reporters: Vec<AccountId>,  // Who reported the offence (may be empty)
    slash_fraction: Perbill,    // Percentage of stake to slash
}

Reporting Deadlines:

  • With deferred slashing: Offences must be reported within SlashDeferDuration - 1 eras
  • With immediate slashing: Offences can be reported up to BondingDuration eras old

Example: If SlashDeferDuration = 27 and current era is 100:

  • Oldest reportable offence: Era 74 (100 - 26)
  • Offences from era 73 or earlier are rejected

§Phase 2: Queuing

When an offence passes validation, it’s added to the queue:

  1. Storage: Added to OffenceQueue: (EraIndex, AccountId) -> OffenceRecord
  2. Era Tracking: Era added to OffenceQueueEras (sorted vector of eras with offences)
  3. Duplicate Handling: If an offence already exists for the same validator in the same era, only the higher slash fraction is kept

§Phase 3: Processing

Offences are processed incrementally in on_initialize each block:

1. Load oldest offence from queue
2. Move to `ProcessingOffence` storage
3. For each exposure page (from last to first):
   - Calculate slash for validator's own stake
   - Calculate slash for each nominator (pro-rata based on exposure)
   - Track total slash and reward amounts
4. Once all pages processed, create `UnappliedSlash`

Key Features:

  • Page-by-page processing: Large validator sets don’t overwhelm a single block
  • Pro-rata slashing: Nominators slashed proportionally to their stake
  • Reward calculation: A portion goes to reporters (if any)

§Phase 4: Application

Based on SlashDeferDuration, slashes are either:

Immediate (SlashDeferDuration = 0):

  • Applied right away in the same block
  • Funds deducted from staking ledger immediately

Deferred (SlashDeferDuration > 0):

  • Stored in UnappliedSlashes for future application
  • Applied at era: offence_era + SlashDeferDuration
  • Can be cancelled by governance before application

§Storage Items Involved

  • OffenceQueue: Pending offences to process
  • OffenceQueueEras: Sorted list of eras with offences
  • ProcessingOffence: Currently processing offence
  • ValidatorSlashInEra: Tracks highest slash per validator per era
  • UnappliedSlashes: Deferred slashes waiting for application

§Withdrawal Restrictions

To maintain slashing guarantees, withdrawals are restricted:

Withdrawal Era Calculation:

earliest_era_to_withdraw = min(
    active_era,
    last_fully_processed_offence_era + BondingDuration
)

Example:

  • Active era: 100
  • Oldest unprocessed offence: Era 70
  • BondingDuration: 28
  • Withdrawal allowed only for chunks with era ≤ 97 (70 - 1 + 28)

Withdrawal Timeline Example with an Offence:

Era:        90    91    92    93    94    95    96    97    98    99    100   ...  117   118
            |     |     |     |     |     |     |     |     |     |     |          |     |
Unbond:     U
Offence:    X
Reported:               R
Processed:              P (within next few blocks)
Slash Applied:                                                                       S
Withdraw:                                                                            ❌    ✓

With BondingDuration = 28 and SlashDeferDuration = 27:
- User unbonds in era 90
- Offence occurs in era 90
- Reported in era 92 (typically within 2 days, but reportable until Era 116)
- Processed in era 92 (within next few blocks after reporting)
- Slash deferred for 27 eras, applied at era 117 (90 + 27)
- Cannot withdraw unbonded chunks until era 118 (90 + 28)

The 28-era bonding duration ensures that any offences committed before or during
unbonding have time to be reported, processed, and applied before funds can be
withdrawn. This provides a window for governance to cancel slashes that may have
resulted from software bugs.

Key Restrictions:

  1. Cannot withdraw if previous era has unapplied slashes
  2. Cannot withdraw funds from eras with unprocessed offences

Re-exports§

pub use weights::WeightInfo;
pub use ledger::StakingLedger;
pub use ledger::UnlockChunk;

Modules§

asset
Contains all the interactions with Config::Currency to manipulate the underlying staking asset.
benchmarking
Staking pallet benchmarking.
config_preludes
Default implementations of DefaultConfig, which can be used to implement Config.
dispatchables
Auto-generated docs-only module listing all defined dispatchables for this pallet.
election_size_tracker
A static size tracker for the election snapshot data.
ledger
A Ledger implementation for stakers.
session_rotation
Manages all era rotation logic based on session increments.
slashing
A slashing implementation for NPoS systems.
storage_types
Auto-generated docs-only module listing all (public and private) defined storage types for this pallet.
testing_utils
Testing utils for staking. Provides some common functions to setup staking state, such as bonding validators, nominators, and generating different types of solutions.
weights
Autogenerated weights for pallet_staking_async

Macros§

log

Structs§

ActiveEraInfo
Information regarding the active era (era in used in session).
AllStakers
A utility struct that provides a way to check if a given account is a staker.
BondedErasBound
Custom bound for BondedEras which is equal to Config::BondingDuration + 1.
BoundedExposurePage
A bounded wrapper for [sp_staking::ExposurePage].
ClaimedRewardsBound
EraRewardPoints
Reward points of an era. Used to split era total payout between validators.
Exposure
A snapshot of the stake backing a single validator in the system.
FixedNominationsQuota
A nomination quota that allows up to MAX nominations for all validators.
GenesisConfig
Can be used to configure the genesis state of this pallet.
IndividualExposure
The amount of exposure for an era that an individual nominator has (susceptible to slashing).
Nominations
A record of the nominations made by a specific account.
PagedExposure
Facade struct to encapsulate PagedExposureMetadata and a single page of ExposurePage.
Pallet
The Pallet struct, the main type that implements traits and standalone functions within the pallet.
PlanningEraOffsetOf
A smart type to determine the Config::PlanningEraOffset, given:
UnappliedSlash
A pending slash record. The value of the slash has been computed but not applied yet, rather deferred for several eras.
UseNominatorsAndValidatorsMap
A simple voter list implementation that does not require any additional pallets. Note, this does not provided nominators in sorted ordered. If you desire nominators in a sorted order take a look at [`pallet-bags-list].
UseValidatorsMap
A simple sorted list implementation that does not require any additional pallets. Note, this does not provide validators in sorted order. If you desire nominators in a sorted order take a look at [pallet-bags-list].
ValidatorPrefs
Preference of what happens regarding validation.

Enums§

Call
Contains a variant per dispatchable extrinsic that this pallet has.
ConfigOp
Possible operations on the configuration values of this pallet.
Error
The Error enum of this pallet.
Event
The Event enum of this pallet
Forcing
Mode of era-forcing.
HoldReason
A reason for placing a hold on funds.
RewardDestination
A destination account for payment.
SnapshotStatus
Status of a paged snapshot progress.
StakerStatus
Representation of the status of a staker.
UnexpectedKind
Represents unexpected or invariant-breaking conditions encountered during execution.

Traits§

Config
Configuration trait of this pallet.
DefaultConfig
Based on Config. Auto-generated by #[pallet::config(with_default)]. Can be used in tandem with #[register_default_config] and #[derive_impl] to derive test config traits based on existing pallet config traits in a safe and developer-friendly way.
EraPayout
Handler for determining how much of a balance should be paid out on the current era.
NominationsQuota
Something that defines the maximum number of nominations per nominator based on a curve.

Type Aliases§

ActiveEra
The active era information, it holds index and start.
BalanceOf
The balance type of this pallet.
Bonded
Map from all locked “stash” accounts to the controller account.
BondedEras
A mapping from still-bonded eras to the first session index of that era.
BoundedExposuresOf
Alias for a bounded set of exposures behind a validator, parameterized by this pallet’s election provider.
CanceledSlashPayout
The amount of currency given to reporters of a slash event which was canceled by extraordinary circumstances (e.g. governance).
CancelledSlashes
Cancelled slashes by era and validator with maximum slash fraction to be cancelled.
ChillThreshold
The threshold for when users can start calling chill_other for other validators / nominators. The threshold is compared to the actual number of validators / nominators (CountFor*) in the system compared to the configured max (Max*Count).
ClaimedRewards
History of claimed paged rewards by era and validator.
CurrentEra
The current planned era index.
ElectableStashes
A bounded list of the “electable” stashes that resulted from a successful election.
ErasRewardPoints
Rewards for the last Config::HistoryDepth eras. If reward hasn’t been set or has been removed then 0 reward is returned.
ErasStakersOverview
Summary of validator exposure at a given era.
ErasStakersPaged
Paginated exposure of a validator at given era.
ErasTotalStake
The total amount staked for the last Config::HistoryDepth eras. If total hasn’t been set or has been removed then 0 stake is returned.
ErasValidatorPrefs
Exposure of validator at era with the preferences of validators.
ErasValidatorReward
The total validator era payout for the last Config::HistoryDepth eras.
ForceEra
Mode of era forcing.
Invulnerables
Any validators that may never be slashed or forcibly kicked. It’s a Vec since they’re easy to initialize and the performance hit is minimal (we expect no more than four invulnerables) and restricted to testnets.
Ledger
Map from all (unlocked) “controller” accounts to the info regarding the staking.
MaxNominationsOf
Maximum number of nominations per nominator.
MaxNominatorsCount
The maximum nominator count before we stop allowing new validators to join.
MaxStakedRewards
Maximum staked rewards, i.e. the percentage of the era inflation that is used for stake rewards. See Era payout.
MaxValidatorsCount
The maximum validator count before we stop allowing new validators to join.
MaxWinnersOf
Alias for the maximum number of winners (aka. active validators), as defined in by this pallet’s config.
MaxWinnersPerPageOf
Alias for the maximum number of winners per page, as expected by the election provider.
MinCommission
The minimum amount of commission that validators can set.
MinNominatorBond
The minimum active bond to become and maintain the role of a nominator.
MinValidatorBond
The minimum active bond to become and maintain the role of a validator.
MinimumActiveStake
The minimum active nominator stake of the last successful election.
ModuleDeprecated
Type alias to Pallet, to be used by construct_runtime.
NegativeImbalanceOf
NextElectionPage
Keeps track of an ongoing multi-page election solution request.
Nominators
The map from nominator stash key to their nomination preferences, namely the validators that they wish to support.
OffenceQueue
Stores reported offences in a queue until they are processed in subsequent blocks.
OffenceQueueEras
Tracks the eras that contain offences in OffenceQueue, sorted from earliest to latest.
Payee
Where the reward payment should be made. Keyed by stash.
ProcessingOffence
Tracks the currently processed offence record from the OffenceQueue.
RewardPoint
Counter for the number of “reward” points earned by a given validator.
SlashRewardFraction
The percentage of the slash that is distributed to reporters.
UnappliedSlashes
All unapplied slashes that are queued for later.
ValidatorCount
The ideal number of active validators.
ValidatorSlashInEra
All slashing events on validators, mapped by era to the highest slash proportion and slash value of the era.
Validators
The map from (wannabe) validator stash key to the preferences of that validator.
VirtualStakers
Stakers whose funds are managed by other pallets.
VoterSnapshotStatus
Voter snapshot progress status.