protocol
protocol copied to clipboard
Batch reward calls on round initialization
I thought of another approach for calculating and distributing rewards. This approach has a change in the mechanism of how rewards are called. 2 new variables are introduced in each delegation pool - prevRoundRewards
, claimedPrevRoundRewards
+ orchestratorCutForTheRound
(which can be read from the staking manager).
[⛔️ After writing this I realized that I completely missed that there is a need to track if individual delegator has claimed reward, still keeping this comment here for reference]
step 1 - instead of each orchestrator calling reward individually, rewards for all the orchestrators will be called at the same time when initializeRound
is called [1] end of round [this comment] (https://github.com/livepeer/protocol/issues/463#issuecomment-922581787).
step 2 - Now instead of calculating cuts for orchestrator and delegators individually, the total value of reward is simply added to the respective pool and the prevRoundRewards
is overwritten with the value and claimedPrevRoundRewards
is set to 0 [2]. However, Before the overwrite the unclaimed rewards from previous round is calculated as prevRoundRewards - claimedPrevRoundRewards
which can be used as per [3]
step 3 - Now, each delegator and orchestrator can individually call a claimReward
function which will use the current shares, prevRoundRewards
and orchestratorCutForTheRound
to calculate respective rewards [4].
delegator rewards = prevRoundRewards * (1-orchestratorCutForTheRound) * delegator's share
orchestrator rewards = prevRoundRewards * orchestratorCutForTheRound * orchestrator's share
then the delegator's and orchestrator's stakes are updated.
step 4 - for each claim, update claimedPrevRoundRewards
notes -
- Since there are a fixed number of orchestrators that is 100, calling reward for all the orchestrators will be a constant time function
- due to overwrite there won't be an unbonded growth for the storage
- The unclaimed rewards can be used for a variety of purposed. eg - can be given to orchestrator, can be used for governance etc. A part of this can even be used to reward the account which calls
initializeRound
as it now has a greater gas usage. - This also solves the problem where delegators are dependant upon orchestrators for calling reward, now they don't lose reward even if the orchestrator doesn't call reward. Also, if the user does not call reward, they lose the reward, which is similar to the current approach.
additional notes -
- The first step does increase gas usage as the rewards are calculated for each orchestrator but for individual users the gas will be much lower
- This solves the problem of instant eligibility, dilution before reward call and also dilution after reward call
Originally posted by @kautukkundan in https://github.com/livepeer/protocol/issues/463#issuecomment-927912360
From @kautukkundan in https://github.com/livepeer/protocol/issues/463#issuecomment-927939556
possible fix to the problem in my previous comment add a
lastClaimedRound
variable in the delegation struct and check it before callingclaimReward
https://github.com/livepeer/protocol/blob/next/contracts/bonding/Delegations.sol#L28-L31
From a high level the proposal and some iterations I've done myself on this boil down to:
- Keep track of a reward pool across orchestrators accruing each round based on each Os equity share of stake
- Keep track of a delegation pool per orchestrators
- When commission rates are changed move accrued rewards from pool in [1] to the delegation pool minus orchestrator commissions
After reviewing the above proposal, going through some design iterations with the same purpose myself and discussing it with @kautukkundan we concluded the following things:
-
The commission rate makes it hard because some transition needs to happen when the commission rates are changed by an orchestrator. The difference in commission rates across O's also makes it impossible to calculate an inflation rate that is equal for all accounts
-
The transition that needs to happen when commission rates are changed means that accrued rewards under a previous commission rate need to be processed , which is essentially very similar to a reward call. It's also highly likely that this cost would need to be socialised (e.g. also fall onto delegators if state hasn't progressed yet). In earlier discussions regarding confluence staking and solving the double reward problem me and @yondonfu sort of agreed that this might not be the best UX tradeoff in terms of cost predictability (and effective cost paid), but @kautukkundan mentioned that in a discussion with @adamsoffer that there could also be a benefit; more predictability in rewards.
However the argument above might not be entirely valid anymore as in the current confluence design we already socialize the cost of some state progression based on who takes the first delegation action (or rewards/fees added) in a round. So I think this is definitely an interesting problem area to put some more thought in if we are okay with the cost of some state progressions being socialised.