# Possibility to steal jackpot bypassing restrictions in the executeDraw()

Off-by-one timestamp check lets attacker call executeDraw at the last second, read the Chainlink random number, then buy the winning ticket in the same block.

- Payout: Contest reward
- Severity: medium
- Program: Wenwin
- Credited: dingo2077
- Disclosed: 2023-04-12
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-03-wenwin-findings/issues/343
- Library page: https://bugbountylibrary.com/r/c4%3A2023-03-wenwin%3AM-04
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** Lottery.sol executeDraw / ticket registration deadline
**Root cause:** executeDraw uses `block.timestamp < drawScheduledAt` and beforeTicketRegistrationDeadline uses `block.timestamp > ticketRegistrationDeadline`, both off-by-one, so draw execution and ticket purchase are allowed at the same boundary second.
**Steps:**
1. Deploy with COOL_DOWN_PERIOD=0; warp to last second of draw period (e.g. 172800)
2. Call `lot.executeDraw()` — passes because `<` should be `<=`
3. Chainlink fulfills `onRandomNumberFulfilled(randomNumber)`
4. Read `lot.winningTicket(0)` to get winning ticket encoding
5. Call `lot.buyTickets(drawId, [winningTicket], address(0), address(0))` — passes because `>` should be `>=`
6. Call `lot.claimWinningTickets([ticketID])` to collect jackpot
**How found:** Code review of timestamp comparisons in executeDraw and the beforeTicketRegistrationDeadline modifier; noticed `<` and `>` should be `<=`/`>=`, allowing both actions in the same boundary second.
**Exploitation:** Attacker waits until the final second of the draw period, triggers executeDraw to request randomness, observes the fulfilled random number on-chain, then buys a ticket matching the winning combination before the registration deadline check rejects it, and claims the jackpot.
**Insight:** When a draw/round boundary is enforced by two separate timestamp comparisons (start-of-draw vs registration deadline), check whether both are inclusive/exclusive consistently — an off-by-one on either side lets randomness request and ticket purchase collide in one block.
