Open hats-bug-reporter[bot] opened 2 months ago
Hello. Thank you for submission and participating in the contest
Rounding the timestamps to the era is a desirable and intended feature. The point is that we are not interested in changes in balances, etc. during the epoch, only the final balance in this epoch is important.
For example:
We are not interested in intermediate actions, as only the final balance is important, because it is part of the voting power for which the reward will be received on mVeNFT. And only the final balance will be rewarded.
So, we overwrite the user's balance always within the same epoch to have only the final state. Since we are not interested in intermediate ones. You can also see that the reward is rounded to the epoch, not the timestamp
The latter state is important because it is the only one that will be used as part of the vote. Therefore, it is the only one that will be rewarded
Github username: @MatinR1 Twitter username: MatinRezaii1 Submission hash (on-chain): 0x232ecd860c5fe8b879cbdd8b6a674a06fdb462130a4401d254ebc86374577fe6 Severity: high
Description: Description\ The
onDettach()
function is designed to handle user fund withdrawals and reward harvesting. However, it currently has a critical flaw that can lead to incorrect reward calculations, potentially causing significant fund loss for users.The core issue stems from the behavior of the binary search algorithm used to find relative checkpoint indexes. When the binary search algorithm encounters a timestamp that is equal to the last time index checkpoint, it returns the
middle
index. This leads to an incorrect index being used in subsequent calculations.In other words, the checkpointing mechanism which is designed to carefully track the balances and corresponding epochs, can lead to imprecise and wrong keeping of the balances by having multiple deposits/withdraws in a same epoch index.
Another point is that, all the timestamps for checkpointing task are indeed the week presentation of time, thus all the activites inside a week are rounded to just 1 epoch and checkpoints are overwritten.
Here’s a step-by-step breakdown of the problem:
Checkpoint Update During Withdrawal:
onDettach()
function first calls the withdraw function.withdraw()
function inside the writes a new checkpoint and updates the last timestamp to the current timestamp. (both storage info timestamp for token and balance)withdraw()
, theonDettach()
function calls theharvest()
function.harvest()
function uses the updated last timestamp to determine the reward.harvest()
function at its heart calls the_calculateAvailableRewardsAmount()
function that is responsible for calculating the available rewards. This function attempts to find the nearest index of checkpoint for a token:startEpoch
would be the middle index of all the checkpoints.in the cases of calling
onAttach()
/onDettach()
multiple times for a token id in same epoch timestamp, this problem becomes a serious issue which results in miscalculated rewards and potential fund loss.Attachments
block.timestamp
rather than week presentation)