There is a wrong calculation of the cumulative net profit of the lottery, which affects the calculation of the excess pot and rewards per winning ticket (including the jackpot) in each draw. This vulnerability also leads to a Denial of Service of the Lottery contract.
Proof of Concept
The result of LotteryMath.calculateMultiplier should be used to calculate a percentage of the expected payout for all tickets. This should be done using the getPercentage method from the PercentageMath library, as is done in LotteryMath.calculateReward:
The problem is that instead of calculating the expectedRewardsOut in LotteryMath.calculateNewProfit as a percentage from ticketsSold * expectedPayout, the current implementation will multiply the result of the multiplication by the returned basis points from calculateMultiplier. This will result in making the newProfit extremely high and therefore impact the calculation of rewards and excess pot in all future draws. This can also lead to a DoS because the calculated profit will always be extremely lowered each time the jackpot is not won (since expectedRewardsOut will grow exponentially due to the excess pot, and the multiplier will grow as well) and therefore come to an underflow situation after a certain time has passed.
Tools Used
Manual Review
Recommended Mitigation Steps
Fix the code in LotteryMath.calculateNewProfit in the following way:
Lines of code
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/LotteryMath.sol#L52-L53 https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L240 https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L209 https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L212
Vulnerability details
Impact
There is a wrong calculation of the cumulative net profit of the lottery, which affects the calculation of the excess pot and rewards per winning ticket (including the jackpot) in each draw. This vulnerability also leads to a Denial of Service of the Lottery contract.
Proof of Concept
The result of LotteryMath.calculateMultiplier should be used to calculate a percentage of the expected payout for all tickets. This should be done using the getPercentage method from the PercentageMath library, as is done in LotteryMath.calculateReward:
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/LotteryMath.sol#L96-L112
The problem is that instead of calculating the
expectedRewardsOut
in LotteryMath.calculateNewProfit as a percentage from ticketsSold * expectedPayout, the current implementation will multiply the result of the multiplication by the returned basis points fromcalculateMultiplier
. This will result in making the newProfit extremely high and therefore impact the calculation of rewards and excess pot in all future draws. This can also lead to a DoS because the calculated profit will always be extremely lowered each time the jackpot is not won (since expectedRewardsOut will grow exponentially due to the excess pot, and the multiplier will grow as well) and therefore come to an underflow situation after a certain time has passed.Tools Used
Manual Review
Recommended Mitigation Steps
Fix the code in LotteryMath.calculateNewProfit in the following way:
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/LotteryMath.sol#L50-L53