Skip to content

Instantly share code, notes, and snippets.

@joepetrowski
Last active March 17, 2020 15:09
Show Gist options
  • Save joepetrowski/3a331fc5b604bede613083df942a9608 to your computer and use it in GitHub Desktop.
Save joepetrowski/3a331fc5b604bede613083df942a9608 to your computer and use it in GitHub Desktop.

Lazy Payouts

Polkadot makes all stakers claim their rewards for past eras by submitting a transaction. This naturally leads to spreading out reward distribution, as people make transactions at disparate times, rather than updating the accounts of all stakers in a single block. Even if everyone submitted a reward claim at the same time, the fact that they are individual transactions would allow the block construction algorithm to process only a limited number per block and ensure that Polkadot maintains a constant block time.

Lazy payouts requires 1 transaction per staker per era to claim rewards, where a staker can be either a validator or a nominator. The reason Polkadot requires this is to avoid an attack where someone has several thousand accounts nominating a single validator. The major cost in reward distribution is mutating the accounts in storage, and Polkadot cannot pay out several thousand accounts in a single transaction.

Claiming Rewards

Polkadot stores up to 84 eras of reward info like maps of era number to validator points, inflationary rewards, and nomination exposures.

Validators

In order to claim rewards, validators must submit a payout_validator(era: EraIndex) transaction from their controller key, where era is the era for which they are claiming rewards.

Nominators

Nominators will need to submit a payout_nominator(era: EraIndex, validators: Vec<(T::AccountId, u32)>) transaction from their controller key, where:

  • era is the era for which that the nominator is claiming rewards.
  • validators is a list of tuples of:
    • Validator stash account IDs that the nominator was nominating during era, and
    • The nominator's index in the list of nominators for that validator for that era.

Providing the index eliminates search and allows for a lower transaction fee.

F.A.Q. and Cautionary Notes

  1. Caution: Once a user claims rewards for an era, all reward information for that user for previous eras is removed. Regular users should not construct these transactions themselves, but should use a wallet or front end that safely claims in the correct order.
  2. Rewards expire after 84 eras. On Polkadot, that's about 84 days. On Kusama, it is 21 days.
  3. Users must use their controller key to claim payouts. The stash key should remain in cold storage.
  4. Claiming rewards (or neglecting to claim rewards) does not affect nominations in any way. Nominations will persist after claiming rewards or the rewards expire.
  5. Polkadot provides a batch function under the Utility pallet that allows the user to batch several transactions into a single transaction from the same origin. Therefore, users can use this function to claim rewards for several eras for a single validator or nominator.

Future Plans

This scheme protects against malicious nominators, but is difficult for UX and especially hurts smaller nominators who would rather be passive participants and for whom the transaction fee could represent a non-trivial fraction of their rewards. We are actively investigating other solutions that would, for example, let a single user trigger the payout for all nominators of a single validator as long as that user is willing to pay the transaction fee.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment