Submitted by Cyfrin, also found by minhtrng, adriro, gogo, bin2chen, auditor0517, Yukti_Chinta, and anodaram
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/LotteryMath.sol#L50-L53
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L216-L223
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L238-L247
LotteryMath.calculateNewProfit returns the wrong profit when there is no jackpot winner, and the library function is used when we update currentNetProfit of Lottery contract.
Lottery.currentNetProfit is used during reward calculation, so it can ruin the main functionality of this protocol.
In LotteryMath.calculateNewProfit, expectedRewardsOut is calculated as follows:
The calculation is not correct when there is no jackpot winner. When jackpotWon is false, ticketsSold * expectedPayout is the total payout in reward token, and then we need to apply a multiplier to the total payout, and the multiplier is calculateMultiplier(calculateExcessPot(oldProfit, fixedJackpotSize), ticketsSold, expectedPayout).
The calculation result is expectedRewardsOut, and it is also in reward token, so we should use PercentageMath instead of multiplying directly.
For coded PoC, I added this function in LotteryMath.sol and imported forge-std/console.sol for console log.
The result is as follows:
Foundry
Use PercentageMath instead of multiplying directly.
rand0c0des (Wenwin) confirmed 
