Liquid Staking

Overview

As Polkadot uses NPoS (Nominated Proof-of-Stake), DOT holders stake their DOT tokens to nominate validators to earn yields. Stakers may want to expand the utility of their staked DOT.
Parallel finance comes out a solution to unlock the liquidity of staked DOT without compromising the security of the network.

Architecture

There are 5 layers of architecture: Application Layer is for user side, Access Layer is for API request, On-chain Layer include main logic about relaychain and parachain. Off-chain Layer implements by stake-client, and Security Layer is for private key security.

Function Module Diagram

It indicates mainly storage and method in parachain.

Stake and Unstake process

Parachain will match all users' stake and unstake requests during one period, and then bond or unbond on relaychain. if the first period is unbond and the second period is bond, it may do rebond first.

View Data Storage

ExchangeRate

The exchange rate converts staking native token to xtoken.
Code
View Method
1
pub type ExchangeRate<T: Config> = StorageValue<_, Rate, ValueQuery>;
Copied!
1
ExchangeRate::<T>::get()
2
Self::exchange_rate()
Copied!

StakingPool

The total amount of staked assets in relaychain.
Code
View Method
1
pub type StakingPool<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
Copied!
1
StakingPool::<T>::get()
2
Self::staking_pool()
Copied!

StakingSettlementRecords

Records reward or slash during each era.
Code
View Method
1
pub type StakingSettlementRecords<T: Config> = StorageDoubleMap<
2
_,
3
Twox64Concat,
4
EraIndex,
5
Twox64Concat,
6
StakingSettlementKind,
7
BalanceOf<T>,
8
>;
Copied!
1
StakingSettlementRecords::<T>::get(era_index: EraIndex, kind: &StakingSettlementKind)
Copied!

PreviousEra

Last updated era index.
Code
View Method
1
pub type PreviousEra<T: Config> = StorageValue<_, EraIndex, ValueQuery>;
Copied!
1
PreviousEra::<T>::get()
2
Self::previous_era()
Copied!

CurrentEra

Current era_index.
Code
View Method
1
pub type CurrentEra<T: Config> = StorageValue<_, EraIndex, ValueQuery>;
Copied!
1
CurrentEra::<T>::get()
2
Self::current_era()
Copied!

UnbondingOperationHistory

Records relay operations during each era.
Code
View Method
1
pub type UnbondingOperationHistory<T: Config> =
2
StorageMap<_, Twox64Concat, EraIndex, Operation<BlockNumberFor<T>, BalanceOf<T>>>;
Copied!
1
UnbondingOperationHistory::<T>::get(era_index: &EraIndex)
Copied!

AccountUnstake

Record all the pending unstaking requests. Key is the owner of assets.
Code
View Method
1
pub type AccountUnstake<T: Config> = StorageDoubleMap<
2
_,
3
Twox64Concat,
4
T::AccountId,
5
Blake2_128Concat,
6
EraIndex,
7
UnstakeMisc,
8
ValueQuery,
9
>;
Copied!
1
AccountUnstake::<T>::get(account_id: T::AccountId,era_index: &EraIndex)
Copied!

EraMatchingPool

Records relay operations during each era.
Code
View Method
1
pub type EraMatchingPool<T: Config> =
2
StorageMap<_, Blake2_128Concat, EraIndex, MatchingLedger<BalanceOf<T>>, ValueQuery>;
Copied!
1
EraMatchingPool::<T>::get(era_index: &EraIndex)
Copied!

View Methods

Stake()

Put assets under staking, the native assets will be transferred to the account owned by the pallet, the user receives the voucher in return, such vouchers can be further used as collateral for lending.
1
pub fn stake(origin: OriginFor<T>, amount: Balance) -> DispatchResultWithPostInfo
Copied!
Name
Substrate Config
Runtime Type
Description
origin
T::Origin
RawOrigin
The account signed this transaction
amount
T::Balance
u128
The amount for staking
RETURN: Returns Ok() when staking succeeds, otherwise return a substrate error type.
Tip: Follow the link to know more about `RawOrigin`.

Unstake()

Unstake by exchange voucher for assets, the assets will not be avaliable immediately. Instead, the request is recorded and pending for the nomination accounts in relaychain to do the unbond operation.
1
pub fn unstake(origin: OriginFor<T>, amount: Balance) -> DispatchResultWithPostInfo
Copied!
Name
Substrate Config
Runtime Type
Description
origin
T::Origin
RawOrigin
The account signed this transaction
amount
T::Balance
u128
The amount for staking
RETURN: Returns Ok() when unstake succeeds, otherwise return a substrate error type.

Claim()

Claim staking currency for given era_index.
1
pub fn claim(origin: OriginFor<T>, era_index: EraIndex) -> DispatchResultWithPostInfo
Copied!
Name
Substrate Config
Runtime Type
Description
origin
T::Origin
RawOrigin
The account signed this transaction
era_index
EraIndex
u32
The era index in relaychain
RETURN: Returns Ok() when claim succeeds, otherwise return a substrate error type.

View Event

Staked

The assets get staked successfully
Staked(T::AccountId, Balance)

Unstaked

The derivative get unstaked successfully
Unstaked(T::AccountId, Balance)

StakeingSettlementRecorded

Reward/Slash has been recorded.
StakeingSettlementRecorded(StakingSettlementKind, Balance)

EraIndexUpdated

Era index updated.
EraIndexUpdated(EraIndex, EraIndex)

View Error

Name
Description
StakeingSettlementAlreadyRecorded
Reward/Slash has been recorded
InvalidExchangeRate
The exchange rate is invalid
EraAlreadyPushed
The era has been pushed before
OperationNotReady
Operation wasn't submitted to relaychain or has been processed
Last modified 1mo ago