Platform: Code4rena
Start Date: 06/03/2023
Pot Size: $36,500 USDC
Total HM: 8
Participants: 93
Period: 3 days
Judge: cccz
Total Solo HM: 3
Id: 218
League: ETH
Rank: 17/93
Findings: 1
Award: $407.79
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: dingo2077
Also found by: 0x73696d616f, Blockian, d3e4, savi0ur
407.7933 USDC - $407.79
https://github.com/code-423n4/2023-03-wenwin/blob/91b89482aaedf8b8feb73c771d11c257eed997e8/src/LotterySetup.sol#L114 https://github.com/code-423n4/2023-03-wenwin/blob/91b89482aaedf8b8feb73c771d11c257eed997e8/src/Lottery.sol#L135
A user can buy a ticket after the winning ticket was set by inserting the transaction in the same block, which allows them to win the jackpot. In addition, it allows for winning more than the intended jackpot amount.
Buying tickets is blocked with the modifier beforeTicketRegistrationDeadline
which reverts if block.timestamp
is larger than ticketRegistrationDeadline(drawId)
which is drawScheduledAt(drawId) - drawCoolDownPeriod
The draw itself reverts if block.timestamp < drawScheduledAt(currentDraw)
.
This means that if drawCoolDownPeriod
is 0
(allowed by the constructor) and block.timestamp
equals drawScheduledAt(currentDraw)
a ticket can be purchased in this block, even after the drawing happens.
This allows for someone to call buyTickets
with currentDraw
and the winning ticket.
If this is done also after receiveRandomNumber
is called (which in some random source implementation seems to be the case, as this is called from within executeDraw
, or in the case the random number is also provided in the same block) than winAmount[drawFinalized][selectionSize]
is set to be drawRewardSize(drawFinalized, selectionSize) / jackpotWinners;
so that each jackpot winner receives their share from the pot. The problem is that the tickets were purchased after this calculation, causing it to be not correct and allowing for the withdrawal of more funds than in the pot.
Auditing
Change beforeTicketRegistrationDeadline
modifier to actually check it's before the registration deadline, i.e. make it like so:
modifier beforeTicketRegistrationDeadline(uint128 drawId) { // slither-disable-next-line timestamp if (block.timestamp >= ticketRegistrationDeadline(drawId)) { revert TicketRegistrationClosed(drawId); } _; }
#0 - c4-judge
2023-03-10T10:14:52Z
thereksfour changed the severity to 2 (Med Risk)
#1 - c4-judge
2023-03-10T10:14:58Z
thereksfour marked the issue as primary issue
#2 - rand0c0des
2023-03-14T10:15:36Z
This is a good finding. I agree with medium severity because of highly unlikely scenario of deploying lottery with cool down period of 0, plus the way current oracles are working.
#3 - c4-sponsor
2023-03-14T10:15:41Z
rand0c0des marked the issue as sponsor confirmed
#4 - c4-judge
2023-03-19T09:59:05Z
thereksfour marked issue #343 as primary and marked this issue as a duplicate of 343
#5 - c4-judge
2023-03-19T10:07:31Z
thereksfour marked the issue as satisfactory