Skip to content

Latest commit

 

History

History
124 lines (67 loc) · 4.8 KB

STAKE_POOL_REWARDS.md

File metadata and controls

124 lines (67 loc) · 4.8 KB

Stake Pool Rewards

As mentioned in the spec, many actions taken by a user will involve redistributing some funds as rewards to "all other stakers". To accomplish this, an algorithm has been developed which works as follows:

Assume n number of users (denoted as u1, u2, ... un) have deposited a total amount of CAW denoted as totalDepositedCaw When an arbitrary user, ui, removes X caw from their balance and distributes this amount as rewards to all other users, the amount added to the account of any arbitrary user (uj, where j ≠ i) will be X multiplied by percentOwnership(uj), where percentOwnership(uj) is the ratio of the balance of uj to the total amount of CAW which has been deposited by all users aside from ui.

percentOwnership(uj) = balanceOf(uj) / (totalDepositedCaw - balanceOf(ui))

The balanceAfterReward of uj can be denoted as follows:

balanceAfterReward(uj) = balanceOf(uj) + X * percentOwnership(uj)

i.e.

balanceAfterReward(uj) = balanceOf(uj) + X * balanceOf(uj) / (totalDepositedCaw - balanceOf(ui))

therefore

balanceAfterReward(uj) = balanceOf(uj) * (1 + X / (totalDepositedCaw - balanceOf(ui))

if we refer to the multiplier of the balance before the rewards as r, where

r = (1 + X / (totalDepositedCaw - balanceOf(ui))

then

balanceAfterReward(uj) = balanceOf(uj) * r

Since each amount distributed as rewards can be different, we can denote each amount as Xn, and

rn = (1 + Xn / (totalDepositedCawn - balancen(ui))

and therefore

balanceOf(n+1)(uj) = balanceOfn(uj) * rn
...
balanceOf3(uj) = balanceOf2(uj) * r2
balanceOf2(uj) = balanceOf1(uj) * r1
balanceOf1(uj) = balanceOf0(uj) * r0

and by substitution, we can compute balance3 as:

balanceOf3(uj) = balanceOf2(uj) * r2
balanceOf3(uj) = balanceOf1(uj) * r1 * r2
balanceOf3(uj) = balanceOf0(uj) * r0 * r1 * r2

To compute the current value of any user at any time, we just need to multiply it's initial balance by the product of all r0...rn. In the solidity contract, we are only ever interested in the current balance, so we can persist a value, rewardMultiplern, which is overwritten with with each reward distribution n as

rewardMultipliern = rewardMultiplier(n-1) * rn

which is equivalent to

rewardMultiplern = r0 * r1 * ... * rn

and therefore, at any time

balanceOfn(uj) = balanceOf0(uj) * rewardMultiplern

--

The one other piece of this algorithm that needs to be considered is the balance of ui, after ui distributes X from it's balance, it should receive no part of X, and must be overwritten as it's pre-distribution balance minus X. Since the current balance of each un is computed by multiplying rewardMultipler, we must overwrite the initial balance of ui to be in terms of rewardMultiplern. Namely,

balanceOf0(ui) = (balanceOfn-1(ui) - Xn) / rewardMultiplern

Since the spec requires several transactions to move funds between users while simultaneously redistributing rewards to all other stakers, the contract uses this process of overwriting balanceOf0 in terms of rewardMultiplern anytime a user receives, spends, deposits, or withdraws any CAW from their balance.

QED

...

...

(p.s. I dedicate this proof to my grlfren, who not only endured me writing it, but also helped)