27 major breaking releases

new 30.0.0 Mar 18, 2024
29.0.0 Feb 26, 2024
28.0.0 Feb 13, 2024
27.0.0 Jan 23, 2024
0.0.0 Nov 21, 2022

#752 in Magic Beans

Download history 443/week @ 2023-12-03 755/week @ 2023-12-10 409/week @ 2023-12-17 174/week @ 2023-12-24 751/week @ 2023-12-31 982/week @ 2024-01-07 567/week @ 2024-01-14 623/week @ 2024-01-21 529/week @ 2024-01-28 522/week @ 2024-02-04 1166/week @ 2024-02-11 2007/week @ 2024-02-18 1875/week @ 2024-02-25 624/week @ 2024-03-03 606/week @ 2024-03-10 1103/week @ 2024-03-17

4,386 downloads per month
Used in 59 crates (4 directly)

Apache-2.0

2MB
39K SLoC

Made with Substrate, for Polkadot.

github - polkadot

Fast Unstake Pallet

A pallet to allow participants of the staking system (represented by Config::Staking, being StakingInterface) to unstake quicker, if and only if they meet the condition of not being exposed to any slashes.

Overview

If a nominator is not exposed anywhere in the staking system, checked via StakingInterface::is_exposed_in_era (i.e. "has not actively backed any validators in the last StakingInterface::bonding_duration days"), then they can register themselves in this pallet and unstake faster than having to wait an entire bonding duration.

Being exposed with validator from the point of view of the staking system means earning rewards with the validator, and also being at the risk of slashing with the validator. This is equivalent to the "Active Nominator" role explained in here.

Stakers who are certain about NOT being exposed can register themselves with Pallet::register_fast_unstake. This will chill, fully unbond the staker and place them in the queue to be checked.

A successful registration implies being fully unbonded and chilled in the staking system. These effects persist even if the fast-unstake registration is retracted (see Pallet::deregister and further).

Once registered as a fast-unstaker, the staker will be queued and checked by the system. This can take a variable number of blocks based on demand, but will almost certainly be "faster" (as the name suggest) than waiting the standard bonding duration.

A fast-unstaker is either in Queue or actively being checked, at which point it lives in Head. Once in Head, the request cannot be retracted anymore. But, once in Queue, it can, via Pallet::deregister.

A deposit equal to Config::Deposit is collected for this process, and is returned in case a successful unstake occurs (Event::Unstaked signals that).

Once processed, if successful, no additional fee for the checking process is taken, and the staker is instantly unbonded.

If unsuccessful, meaning that the staker was exposed, the aforementioned deposit will be slashed for the amount of wasted work they have inflicted on the chain.

All in all, this pallet is meant to provide an easy off-ramp for some stakers.

Example

  1. Fast-unstake with multiple participants in the queue.

  2. Fast unstake failing because a nominator is exposed.

Pallet API

See the pallet module for more information about the interfaces this pallet exposes, including its configuration trait, dispatchables, storage items, events and errors.

Low Level / Implementation Details

This pallet works off the basis of on_idle, meaning that it provides no guarantee about when it will succeed, if at all. Moreover, the queue implementation is unordered. In case of congestion, no FIFO ordering is provided.

A few important considerations can be concluded based on the on_idle-based implementation:

  • It is crucial for the weights of this pallet to be correct. The code inside Pallet::on_idle MUST be able to measure itself and report the remaining weight correctly after execution.

  • If the weight measurement is incorrect, it can lead to perpetual overweight (consequently slow) blocks.

  • The amount of weight that on_idle consumes is a direct function of ErasToCheckPerBlock.

  • Thus, a correct value of ErasToCheckPerBlock (which can be set via Pallet::control) should be chosen, such that a reasonable amount of weight is used on_idle. If ErasToCheckPerBlock is too large, on_idle will always conclude that it has not enough weight to proceed, and will early-return. Nonetheless, this should also be safe as long as the benchmarking/weights are accurate.

  • See the inline code-comments on do_on_idle (private) for more details.

  • For further safety, in case of any unforeseen errors, the pallet will emit Event::InternalError and set ErasToCheckPerBlock back to 0, which essentially means the pallet will halt/disable itself.

Dependencies

~18–37MB
~621K SLoC