Skip to content

[Staking] Self stake incentive for Validators#11651

Merged
Ank4n merged 168 commits intomasterfrom
ankn-validator-incentive
Apr 21, 2026
Merged

[Staking] Self stake incentive for Validators#11651
Ank4n merged 168 commits intomasterfrom
ankn-validator-incentive

Conversation

@Ank4n
Copy link
Copy Markdown
Contributor

@Ank4n Ank4n commented Apr 6, 2026

Extracted from #10844.
Builds on #11616.
Specs: https://hackmd.io/@jonasW3F/rkN6BXE2ex

Overview

Adds a separate validator self-stake incentive reward track. Validators receive an additional bonus from a dedicated
incentive pot, proportional to their self-stake weight. Payout is flat liquid. Vesting implementation will be in a follow-up PR.

Incentive Weight Curve

Each validator's share of the incentive pot is determined by a piecewise sqrt function:

  • Below optimum: w(s) = √s
  • Between optimum and cap: w(s) = √(T + k² × (s - T)) (diminishing returns)
  • Above cap: plateau

Weights are calculated during era planning and stored per-validator. At payout, each validator's incentive =
(their_weight / total_weight) × era_incentive_budget, prorated across pages.

Changes

New storage: OptimumSelfStake, HardCapSelfStake, SelfStakeSlopeFactor,
ErasValidatorIncentiveAllocation (era budget snapshot), ErasTotalValidatorWeight, ErasValidatorIncentive (per-validator weights).

New extrinsic: set_validator_self_stake_incentive_config: sets optimum, cap, and slope factor. Callable by StakingAdmin. Validates optimum ≤ cap.

New event: ValidatorIncentivePaid { era, validator_stash, dest, amount }

Era lifecycle: end_era_dap now snapshots both staker reward and incentive pots. Era planning calculates and stores incentive weights for each elected validator. Pruning cleans up ErasValidatorIncentive storage.

Payout: do_payout_stakers_by_page calls pay_validator_incentive_for_page after staker rewards. Direct Currency::transfer from incentive era pot to payout account.

TODO

  • Run staking async bench
  • Update integration test with self stake incentive setup.
  • View Functions for Staking Pots.
  • Test with and improve on Kian's UI

Comment thread substrate/frame/staking-async/src/pallet/impls.rs Outdated
Comment thread substrate/frame/staking-async/integration-tests/src/ah/test.rs Outdated
Comment thread substrate/frame/staking-async/integration-tests/src/ah/test.rs
Copy link
Copy Markdown
Contributor

@kianenigma kianenigma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some improvement suggestions for tests and naming and maintanability and so on, but all in all the logic is sounds.

I will approve, but will probably spend a day next week writing mroe tests, and personally auditing the entirety of this line of changes.

(have also triggered another deep audit in our intelligence tool, PTAL as well)

era_reward_points.individual.get(&stash).copied().unwrap_or_else(Zero::zero);

// Nothing to do if they have no reward points.
if validator_reward_points.is_zero() {
Copy link
Copy Markdown
Contributor

@PolkadotDom PolkadotDom Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ank4n @kianenigma

Was thinking.. if the validator does no work, they aren't paid out any incentive either, as seen here. But the overall incentive summation value doesn't change when this happens, meaning the incentive payouts could be considered diluted for other validators. I'm getting 1/n instead of 1/(n-1)!

I back this design, as giving a validator an incentive for other validators to not show up sounds like a security risk, but I think it's something we may want to note as purposeful so others who may see it as a bug don't change it. New unit test and comment? Or just extend zero_reward_points_means_no_payout I suppose. Thoughts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I will add some documentation and test to point out this behaviour.

@Ank4n Ank4n added this pull request to the merge queue Apr 21, 2026
Merged via the queue into master with commit 5cb698c Apr 21, 2026
265 of 269 checks passed
@Ank4n Ank4n deleted the ankn-validator-incentive branch April 21, 2026 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T2-pallets This PR/Issue is related to a particular pallet.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants