Reward¶
Overview¶
This pallet provides a way distribute rewards to any number of accounts, proportionally to their stake. It does so using the Scalable Reward Distribution algorithm. It does not directly transfer any rewards - rather, the stakeholders have to actively withdraw their accumulated rewards, which they can do at any time. Stakeholders can also change their stake at any time, without impacting the rewards gained in the past.
Invariants¶
For each
currencyId
,TotalStake[currencyId]
MUST be equal to the sum ofStake[currencyId, accountId]
over all accounts.TotalReward[currencyId]
MUST be equal to the sum ofStake[currencyId, accountId] * RewardPerToken[currencyId] - RewardTally[currencyId, accountId]
over all accounts.For each
accountId
,RewardTally[currencyId, accountId]
MUST be smaller than or equal toStake[currencyId, accountId] * RewardPerToken[currencyId]
Stake[currencyId, accountId]
MUST NOT be negativeRewardTally[currencyId, accountId]
MUST NOT be negative
Data Model¶
Maps¶
TotalStake¶
The total stake deposited to the reward with the given currency.
TotalRewards¶
The total unclaimed rewards in the given currency distributed to this reward pool. This value is currently only used for testing purposes.
RewardPerToken¶
The amount of reward the stakeholders get for the given currency per unit of stake.
Stake¶
The stake in the given currency for the given account.
RewardTally¶
The amount of rewards in the given currency a given account has already withdrawn, plus a compensation that is added on stake changes.
Functions¶
getTotalRewards¶
This function gets the total amount of rewards distributed in the pool with the given currencyId.
Specification¶
Function Signature
getTotalRewards(currencyId)
Parameters
currencyId
: Determines of which currency the amount is returned.
Postconditions
The function MUST return the total amount of rewards that have been distributed in the given currency.
depositStake¶
Adds a stake for the given account and currency in the reward pool.
Specification¶
Function Signature
depositStake(currencyId, accountId, amount)
Parameters
currencyId
: The currency for which to add the stakeaccountId
: The account for which to add the stakeamount
: The amount by which the stake is to increase
Events
Preconditions
Postconditions
Stake[currencyId, accountId]
MUST increase byamount
TotalStake[currencyId]
MUST increase byamount
RewardTally[currencyId, accountId]
MUST increase byRewardPerToken[currencyId] * amount
. This ensures the amount of rewards the given accountId can withdraw remains unchanged.
distributeReward¶
Distributes rewards to the stakeholders.
Specification¶
Function Signature
distributeReward(currencyId, reward)
Parameters
currencyId
: The currency being distributedreward
: The amount being distributed
Events
Preconditions
TotalStake[currencyId]
MUST NOT be zero.
Postconditions
RewardPerToken[currencyId]
MUST increase byreward / TotalStake[currencyId]
TotalRewards[currencyId]
MUST increase byreward
computeReward¶
Computes the amount a given account can withdraw in the given currency.
Specification¶
Function Signature
computeReward(currencyId, accountId)
Parameters
currencyId
: The currency for which the rewards are being calculatedaccountId
: Account for which the rewards are being calculated.
Postconditions
The function MUST return
Stake[currencyId, accountId] * RewardPerToken[currencyId] - RewardTally[currencyId, accountId]
.
withdrawStake¶
Decreases a stake for the given account and currency in the reward pool.
Specification¶
Function Signature
withdrawStake(currencyId, accountId, amount)
Parameters
currencyId
: The currency for which to decrease the stakeaccountId
: The account for which to decrease the stakeamount
: The amount by which the stake is to decrease
Events
Preconditions
amount
MUST NOT be greater thanStake[currencyId, accountId]
Postconditions
Stake[currencyId, accountId]
MUST decrease byamount
TotalStake[currencyId]
MUST decrease byamount
RewardTally[currencyId, accountId]
MUST decrease byRewardPerToken[currencyId] * amount
. This ensures the amount of rewards the given accountId can withdraw remains unchanged.
withdrawReward¶
Withdraw all available rewards of a given account and currency
Specification¶
Function Signature
withdrawReward(currencyId, reward)
Parameters
currencyId
: The currency being withdrawnaccountId
: The account for which to withdraw the rewards
Events
Preconditions
TotalStake[currencyId]
MUST NOT be zero.
Postconditions
Let reward
be the result computeReward when it is called with currencyId
and accountId
as arguments. Then:
TotalRewards[currencyId]
MUST decrease byreward
RewardPerToken[currencyId]
MUST be set toRewardPerToken[currencyId] * Stake[currencyId, accountId]
Events¶
DepositStake¶
Event Signature
DepositStake(currencyId, accountId, amount)
Parameters
currencyId
: the currency for which the stake has been changedaccountId
: the account for which the stake has been changedamount
: the increase in stake
Functions
WithdrawStake¶
Event Signature
WithdrawStake(currencyId, accountId, amount)
Parameters
currencyId
: the currency for which the stake has been changedaccountId
: the account for which the stake has been changedamount
: the decrease in stake
Functions
DistributeReward¶
Event Signature
DistributeReward(currencyId, accountId, amount)
Parameters
currencyId
: the currency for which the reward has been withdrawnamount
: the distributed amount
Functions
WithdrawReward¶
Event Signature
WithdrawReward(currencyId, accountId, amount)
Parameters
currencyId
: the currency for which the reward has been withdrawnaccountId
: the account for which the reward has been withdrawnamount
: the withdrawn amount
Functions