sherlock-audit / 2024-05-pooltogether-judging

8 stars 4 forks source link

0x73696d616f - `DrawManager::finishDraw()` may hand out more rewards than the reserve if RNG requests fail #100

Closed sherlock-admin4 closed 2 months ago

sherlock-admin4 commented 3 months ago

0x73696d616f

medium

DrawManager::finishDraw() may hand out more rewards than the reserve if RNG requests fail

Summary

DrawManager::finishDraw() calculates reward fractions for each tried auction within a draw, but does not verify if the total fraction is bigger than the reserve, leading to the failure of some draws.

Vulnerability Detail

DrawManager::startDraw() is the entrypoint to start draw actions and hands out rewards according to the curve in the docs. The target reward fraction is a fraction of the reserve, so a number between 0 and 1. Considering for example that the start reward fraction is 0.25, the finish fraction (there is an auction to finish the draw by calling DrawManager::finishDraw()) is 0.25 and there are 2 retries, if the first 2 requests fail but the third succeeds, the reward fraction will exceed 1 and DrawManager::finishDraw() will revert due to withdrawing more from the reserve than possible. For example, in the scenario above, assuming the draws are executed slightly later than the target time, the total reward fraction is 0.251 + 0.251 + 0.251 + 0.251 = 1.004, so it tries to fetch more from the reserve than possible and reverts in PrizePool::allocateRewardFromReserve(),

if (_amount > _reserve) {
  revert InsufficientReserve(_amount, _reserve);
}

This is less likely to happen if the reserve is bigger than maxRewards in the DrawManager, but even then it may still happen. If the reserve is smaller than maxRewards, it is more likely.

Impact

Failed draws due to not limiting the rewards fraction to 1, as it underflows in PrizePool::allocateRewardFromReserve().

Code Snippet

https://github.com/sherlock-audit/2024-05-pooltogether/blob/main/pt-v5-draw-manager/src/DrawManager.sol#L237 https://github.com/sherlock-audit/2024-05-pooltogether/blob/main/pt-v5-draw-manager/src/DrawManager.sol#L454 https://github.com/sherlock-audit/2024-05-pooltogether/blob/main/pt-v5-draw-manager/src/DrawManager.sol#L471

Tool used

Manual Review

Vscode

Recommendation

Limit the reward fraction to 1, for example by dividing pro-rata to the excess of the total reward fraction. For example, if the total is 1.1, each reward fraction may be decreased 1.1 times to not make the draw revert.

Duplicate of #125