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