Blast the balloon SC Audit
After a spin has been executed and depending on certain probabilities, the duration of the current round decreases. The chances of a round duration decreasing are 20% by default and can take the round duration down significantly or even to 0. This effectively moves the end date in the past and closes the round.
The round duration decreasing mechanism as it is, is incompatible with the existing 2 step spin callback mechanism because it does not take into consideration pending spins when the spin duration deduction would close the round.
Users that have bought a spin in the same block as the round duration reduction, but before it within the block itself, will lose their funds without actually receiving a spin. The same issue appears for users that have bought a spin in the block before the reduction and it is execute in the same block as the reduction but after it.
This issue appears because when a spin is bought, a random number generation is initiated via the pyth entropy contract. It takes the pyth contract exactly 1 block to call the game callback with the newly generate random number to complete the spin. As an Optimism fork, Blast has 2 seconds blocks. If the time reduction is applied and closes the round, the second step of the spin fails.
In the _gameTimeImpact function, when reducing the round duration, cap the reduction to the present time plus a tolerance of 2 seconds, so that any pending spins will have time to complete.
Example implementation:
uint32 public constant DURATION_TOLERANCE = 2 seconds;
uint32 endTime = roundInfo.startTime + roundInfo.duration;
uint32 maximumReduction = endTime > uint32(block.timestamp) + DURATION_TOLERANCE ? endTime - uint32(block.timestamp) - DURATION_TOLERANCE : 0;
roundInfo.duration -= (secondLevelImpact >= maximumReduction) ? maximumReduction : secondLevelImpact;
Blast the balloon SC Audit