Staking Pallet Architecture Diagram¶
General Structure¶
┌─────────────────────────────────────────────────────────────────┐
│ Staking Pallet │
├─────────────────────────────────────────────────────────────────┤
│ mod.rs (Structure) impls.rs (Logic) │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ Config │ │ Core Functions │ │
│ │ - Currency │ │ - ledger() │ │
│ │ - Time │ │ - calculate_interest │ │
│ │ - Economics │ │ - do_payout_stakers │ │
│ │ - Elections │ │ - new_session() │ │
│ └─────────────────┘ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ Storage │ │ Session Management │ │
│ │ - Bonded │ │ - new_session() │ │
│ │ - Ledger │ │ - start_session() │ │
│ │ - Validators │ │ - end_session() │ │
│ │ - Nominators │ └─────────────────────────┘ │
│ │ - Eras │ │
│ └─────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ Events │ │ Election Provider │ │
│ │ - Rewarded │ │ - get_npos_voters() │ │
│ │ - Slashed │ │ - get_npos_targets() │ │
│ │ - Bonded │ │ - electing_voters() │ │
│ │ - VividStaking│ │ - electable_targets() │ │
│ └─────────────────┘ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ ┌───────────────────────────┐ ┌─────────────────────────┐ │
│ │ Errors │ │ Runtime API │ │
│ │ - NotStash │ │ - api_nominations_quota│ │
│ │ - NotController │ │ - api_estimate_payout │ │
│ │ - InsufficientBond │ │ - StakingInterface │ │
│ │ - VividStakingInProgress│ └─────────────────────────┘ │
│ └───────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Detailed Storage Structure¶
Storage Layer
├── Account Management
│ ├── Bonded<T> // stash -> controller mapping
│ ├── Ledger<T> // controller -> StakingLedger
│ └── Payee<T> // stash -> RewardDestination
│
├── Validators & Nominators
│ ├── Validators<T> // validator -> ValidatorPrefs
│ ├── Nominators<T> // nominator -> Nominations
│ ├── ValidatorCount<T> // desired validator count
│ └── MinimumValidatorCount<T> // minimum validators
│
├── Era Management
│ ├── CurrentEra<T> // current era index
│ ├── ActiveEra<T> // active era info
│ ├── ErasStartSessionIndex<T> // era -> session mapping
│ ├── ErasStakers<T> // era -> validator -> Exposure
│ ├── ErasStakersClipped<T> // clipped exposures
│ ├── ErasValidatorPrefs<T> // era -> validator -> prefs
│ ├── ErasDuration<T> // era -> duration
│ ├── ErasRewardPoints<T> // era -> reward points
│ └── ErasTotalStake<T> // era -> total stake
│
├── Slashing
│ ├── UnappliedSlashes<T> // era -> Vec<UnappliedSlash>
│ ├── SlashingSpans<T> // stash -> SlashingSpans
│ ├── SpanSlash<T> // (stash, span) -> SpanRecord
│ ├── ValidatorSlashInEra<T> // era -> validator -> (fraction, amount)
│ └── NominatorSlashInEra<T> // era -> nominator -> amount
│
└── Configuration
├── MinNominatorBond<T> // minimum nominator bond
├── MinValidatorBond<T> // minimum validator bond
├── ForceEra<T> // force era mode
├── StakingActive<T> // staking enabled flag
└── IssuanceLimit<T> // maximum token issuance
Data Flow for Reward Payouts¶
Payout Flow
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ User │ │ Runtime │ │ Staking │
│ Call │─▶ │ Dispatch │───▶│ Pallet │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ do_payout_stakers() │
├─────────────────────────────────────────────────────────┤
│ 1. Validate era and check permissions │
│ 2. Get exposure from ErasStakersClipped │
│ 3. Calculate interest for each nominator │
│ - Check vivid staking status │
│ - Apply standard + vivid interest rates │
│ 4. Calculate validator commission │
│ 5. Create payouts via make_payout() │
│ - Controller/Stash/Staked/Account/None │
│ 6. Emit Rewarded events │
│ 7. Update ledger.claimed_rewards │
└─────────────────────────────────────────────────────────┘
Vivid Staking Flow¶
Vivid Staking Process
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ User │ │ vivid() │ │ Storage │
│ Call │──▶ │ Function │───▶│ Update │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Vivid Staking Logic │
├─────────────────────────────────────────────────────────┤
│ 1. Validate months_count parameter │
│ 2. Check no existing vivid staking │
│ 3. Calculate starting and ending eras │
│ 4. Create VividStakingState │
│ 5. Update ledger.vivid_staking │
│ 6. Emit VividStakingScheduled event │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Interest Calculation │
├─────────────────────────────────────────────────────────┤
│ calculate_interest(era, vivid_staking) │
│ ├── Check if era is within vivid period │
│ ├── Calculate months locked │
│ └── Return: StandardInterest + VividInterest * months │
└─────────────────────────────────────────────────────────┘
Election Provider Flow¶
Election Process
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Session │ │ Election │ │ Validator │
│ Manager │───▶│ Provider │───▶│ Selection │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ get_npos_voters() │
├─────────────────────────────────────────────────────────┤
│ 1. Iterate through VoterList │
│ 2. Filter by weight (exclude zero weights) │
│ 3. Separate validators and nominators │
│ 4. Apply bounds constraints │
│ 5. Track minimum active stake │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ get_npos_targets() │
├─────────────────────────────────────────────────────────┤
│ 1. Iterate through TargetList │
│ 2. Filter active validators only │
│ 3. Apply bounds constraints │
│ 4. Return validator list │
└─────────────────────────────────────────────────────────┘
Session Management Flow¶
Session Lifecycle
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Session │ │ Era │ │ Validator │
│ Start │──▶ │ Planning │───▶│ Rotation │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ new_session() │
├─────────────────────────────────────────────────────────┤
│ 1. Check current era │
│ 2. Analyze force era modes │
│ 3. Check session limit per era │
│ 4. Trigger new era if needed │
│ 5. Return new validator set │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ start_era() │
├─────────────────────────────────────────────────────────┤
│ 1. Increment active era index │
│ 2. Update BondedEras │
│ 3. Clean old era data │
│ 4. Apply deferred slashes │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ end_era() │
├─────────────────────────────────────────────────────────┤
│ 1. Calculate era duration │
│ 2. Estimate payouts │
│ 3. Check issuance limit │
│ 4. Disable staking if limit exceeded │
└─────────────────────────────────────────────────────────┘
Economic Model¶
Economic Model
┌─────────────────────────────────────────────────────────┐
│ Interest Calculation │
├─────────────────────────────────────────────────────────┤
│ Standard Staking: │
│ └── StandartStakingInterest (base rate) │
│ │
│ Vivid Staking: │
│ ├── StandartStakingInterest (base rate) │
│ └── VividStakingInterestPerMonth * months_locked │
│ │
│ Total Interest = Base + (Vivid * Months) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Payout Calculation │
├─────────────────────────────────────────────────────────┤
│ Era Duration = Current Time - Era Start │
│ Portion = Era Duration / Year Duration │
│ Interest = calculate_interest(era, vivid_staking) │
│ Payout = Portion * Interest * Stake │
│ │
│ Validator Commission: │
│ ├── Validator gets: own_stake * interest │
│ ├── Validator gets: commission * nominator_rewards │
│ └── Nominators get: (1 - commission) * their_rewards │
└─────────────────────────────────────────────────────────┘
Security and Validation¶
Security Measures
┌─────────────────────────────────────────────────────────┐
│ Input Validation │
├─────────────────────────────────────────────────────────┤
│ ├── Era bounds checking │
│ ├── Balance sufficiency │
│ ├── Slashing span validation │
│ ├── Vivid staking constraints │
│ └── Commission limits │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ State Consistency │
├─────────────────────────────────────────────────────────┤
│ ├── Ledger total = active + sum(unlocking) │
│ ├── VoterList count = Validators + Nominators │
│ ├── Exposure total = own + sum(others) │
│ └── Era progression validation │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Economic Limits │
├─────────────────────────────────────────────────────────┤
│ ├── IssuanceLimit: Maximum token creation │
│ ├── StakingActive: Enable/disable staking │
│ ├── MinNominatorBond: Minimum stake for nominators │
│ └── MinValidatorBond: Minimum stake for validators │
└─────────────────────────────────────────────────────────┘
This architecture provides: - Modularity: Clear separation of structure and logic - Security: Multiple checks and validations - Performance: Optimized algorithms and storage - Flexibility: Support for different types of staking - Scalability: Efficient management of large datasets