Closed sherlock-admin3 closed 1 month ago
Not an issue in practice as the reward will always be many orders of magnitudes larger than the rewardsDuration (the reward will be (much) larger than 10^18) so the rewardRate will always be greater than 0. But even if that was not the case, the owner could always recover any rewards dust using recoverERC20(). In any case, note that this relates to the pre-existing Synthetix contract, which is out of scope as per the rules: "Any issue that exists in the original non-Maker Syntetix staking rewards contract is out of scope."
EFCCWEB3
Medium
PrecisionLoss in NotifyRewardAmount
Summary
The
notifyRewardAmount
function in the smart contract has an incorrect validation mechanism for the reward rate. The current implementation uses integer division to check if the reward rate is within the contract's balance, leading to potential precision loss and incorrect validation, especially over long durations like 7 days. This can cause the function to pass invalid reward rates, resulting in incorrect reward distributions. https://github.com/sherlock-audit/2024-06-makerdao-endgame/blob/main/endgame-toolkit/src/synthetix/StakingRewards.sol#L144Vulnerability Detail
The require statement intended to validate the reward rate uses integer division, which truncates the result, leading to potential precision loss. This can result in an incorrect validation of the reward rate, particularly in scenarios where the division leads to unexpected results due to truncation.
rewardsDuration = 7 days = 604800 seconds balance = 1000000 tokens rewardRate initially set to 0
Let's say we want to set reward = 500000 tokens.
rewardRate ≈ 0.826 balance / rewardsDuration ≈ 1
Since 0.826 <= 1, the require statement passes.
Let assume a scenario where the balance is less than the RewardDuration due to reduction of balance and of that. Assume balance = 10000 tokens and rewardsDuration = 7 days = 604800 seconds.
rewardRate = 0 balance / rewardsDuration = 0
Since 0 <= 0, the require statement passes. However, let's look at what happens in terms of rewards distribution:
Total distributed reward: rewardRate rewardsDuration = 0 604800 = 0 tokens. Given reward: 4 tokens.
Impact
Precision loss in the balance of tokens to be distributed to the stakers, resulting in incorrect reward distributions.
Code Snippet
Tool used
Manual Review
Recommendation
You could accumulate the differences that occur due to precision/truncation and let users claim them at the end and according to their shares
Duplicate of #3