Normal behavior:
The winner should be declarable as soon as the grace period expires (block.timestamp >= lastClaimTime + gracePeriod).
Specific issue:
The contract uses a strict greater-than comparison (>) instead of greater-than-or-equal (>=) when checking if the grace period has expired. This creates an off-by-one error where the winner cannot be declared at the exact expiry timestamp, only one second after.
Likelihood:
This will occur whenever someone tries to declare the winner at the exact expiry moment.
Impact:
Creates a one-second window where the game cannot progress.
Causes unnecessary transaction failures and wasted gas.
Can be exploited or cause user confusion about when the grace period actually ends.
The following test demonstrates the bug. At the exact grace period expiry time, declareWinner() reverts, but succeeds one second later.
Change the comparison from > to >= to allow winner declaration at the exact expiry time:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.