Open sherlock-admin2 opened 4 months ago
The suggested mitigation is a good addition to the draw auction logic, however the difference in behaviour between the fix and the current behaviour is minimal:
Current Behaviour:
When there is not enough reserve to pay for the finishDraw
, the draw will not be awarded and the prize liquidity will gracefully roll over to the next draw (the prize pool is well-equipped to handle skipped draws). The only loss here is on the agent that started the draw, who will not receive the rewards for doing so.
Behaviour After Fix
When there is not enough reserve to pay for the finishDraw
, the auction price will remain at the value of whatever is left until the end of the auction incase a benevolent actor decides to push it through at a loss. If no one pushes it through, the draw will be skipped the same as before and the agent that started the draw will still receive no rewards.
The only difference is the amount of time that a benevolent actor has to push the draw through at a loss. No core protocol functionality is broken since the prize pool is only expected to award prizes if there are enough incentives to do so, and it's built to handle skipped draws without loss.
@trmid I see users that was supposed to be awarded in the original draw as losing their funds as well (since they lose their chance to win), not just the agent that started the draw.
Was this behavior documented as expected behavior? If not I would lean towards agreeing that high severity is appropriate.
A severity of high
seems inappropriate for this issue.
The prize pool uses part of the yield generation (the reserve) to incentivize the RNG auctions. If the generated value is insufficient for a draw to be awarded, then the prize pool keeps all the prize liquidity for the draw and includes it in the next draw. The issue mentioned here is not something that can be forced or exploited, rather it is describing a better way to handle the auction pricing when there is less yield than required to incentivize the RNG. The only difference between the current behaviour and the suggested mitigation behaviour is that the auction will be available for a longer period of time when it does not have proper liquidity for a profitable payout.
This issue is assuming that there are not enough incentives for the RNG auctions to provide profitable payouts, therefore medium
seems more appropriate:
Causes a loss of funds but requires certain external conditions or specific states, or a loss is highly constrained. The losses must exceed small, finite amount of funds, and any amount relevant based on the precision or significance of the loss.
The protocol team fixed this issue in the following PRs/commits: https://github.com/GenerationSoftware/pt-v5-draw-manager/pull/18
Fixed with https://github.com/GenerationSoftware/pt-v5-draw-manager/pull/17 and https://github.com/GenerationSoftware/pt-v5-draw-manager/pull/18 Now the max reward is limited to remaining fraction after the other rewards are considered
The Lead Senior Watson signed off on the fix.
berndartmueller
high
Draw auction rewards likely exceed the available rewards, resulting in overpaying rewards or running into an
InsufficientReserve
errorSummary
The sum of the calculated
startDraw
andfinishDraw
reward fractions likely exceeds1.0
, which can lead to overpaying rewards or anInsufficientReserve
error.Vulnerability Detail
The
finishDraw
function calculates the rewards for starting and finishing a draw and distributes them to the respective participants. The total rewards (availableRewards
) are based on the available prize pool reserve (upper capped bymaxRewards
). Those rewards are then split into the start draw rewards and the finish draw rewards. Internally, the portion each participant receives is denominated in fractions ([0.00, 1.00]). No more thanavailableRewards
(i.e., the upper cap or the total available prize pool reserve)can be distributed.However, it is very likely that the sum of all fractions exceeds
1.0
, which would result in utilizing more rewards thanavailableRewards
. Consequently, if the reserve has been larger than themaxRewards
upper cap, more rewards would be paid out thanavailableRewards
. Or, if the reserve has been smaller thanmaxRewards
, which means the entire reserve is supposed to get used for rewards, using more than1.0 * availableRewards
would result in anInsufficientReserve
error.Basically, in the former case, rewards are overpaid, and in the latter case, the draw can not be awarded due to the
InsufficientReserve
error.The following test case demonstrates this issue by having two
startDraw
calls, both of which are supposed to receive~0.1e18
rewards, which would already exceed the0.1e18
available reserve. Please note that due to mocking the calls to the prize pool, the actualInsufficientReserve
error is not triggered. However, by inspecting the emitted events, it can be seen that the rewards are overpaid.Please copy and paste the above test case into the
pt-v5-draw-manager/test/DrawManager.t.sol
file and run it withforge test -vv --match-test "test_finishDraw_multipleStarts_with_exceeding_reserve"
.Impact
Either rewards for
startDraw
andfinishDraw
are overpaid, or the draw can not be awarded.Code Snippet
DrawManager.finishDraw#L314-L352
Tool used
Manual Review
Recommendation
Consider ensuring that the sum of all fractions does not exceed
1.0
to prevent overpaying rewards or running into anInsufficientReserve
error.