allora-network / allora-chain

Node software to run the Allora Network
https://www.allora.network/
Apache License 2.0
73 stars 67 forks source link

[WIP] Fix Rounding Errors Causing Broken Invariant balance of "pendingrewardfordelegators" != sumAll(rewardDebt) #424

Closed relyt29 closed 1 month ago

relyt29 commented 1 month ago

What is the purpose of the change

In #407, I wrote a simulator that tests various token balance related invariants. One such invariant is that the balance of tokens in the "PendingRewardForDelegators" account must always be Equal to the RewardPerShare of every staker minus the sum of all accumulated RewardDebt in the system. This accounting matters, because the rewards per share and reward debt are used to determine how many tokens to pay out to delegators. If the values are non equal, or at least if we don't have more tokens in the bank account than we think we owe people, then the system will lack funds to pay everybody.

This code attempts to fix that bug. It has mostly to do with the algorithm used to determine the rewardsPerShare and rewardDebt of a participant in the system, and rounding errors having to do with precision and truncation to integers necessary for token transfers.

Testing and Verifying

This code is already covered by existing tests. It changes the TestEqualStakeRewardsToDelegatorAndReputer test because the way in which delegator and reputer rewards are split is changed in this PR.

Previously we did not handle rounding errors due to integer rounding at all. Now we always round delegator rewards to the nearest integer value first which leaves whatever reward is left for the reputer. This changes the EqualStakeRewards test because we define reputer_reward = (total - delegatorReward) rather than doing e.g. reputer_reward = reputer_stake/total_stake * total_reward (which is what we do for delegator reward).

Explained with an example: in the case of e.g. 9 tokens for rewards, with equal stake split between both delegator and reputer, the formula does 9/2 = 4.5, round down to 4 tokens for the delegator and 5 tokens for the reputer. As opposed to 9/2 = 4.5, 4 tokens for delegator and 4 tokens for reputer.

This means that in cases where there's extra tokens left over after division we pay them to the reputer for the service of doing the work.

Documentation and Release Note

Where is the change documented?