The getTimeRemaining()
function in the contract is intended to return the remaining time in a game session. However, it fails to account for situations where a game is manually ended before the originally scheduled end time.
getTimeRemaining()
function?Typically, getTimeRemaining()
would be designed to calculate how much time is left in the game based on the current time (block.timestamp
) and the game's endTime
(the point in time when the game is supposed to end).
The basic logic might look like this:
This function assumes that endTime
represents when the game will automatically end (whether through a timer or another condition). It calculates the difference between the current time and the endTime
to determine how much longer the game will last.
The vulnerability arises when the game is manually ended before the endTime
. For example, an admin might call an endGame()
function or another method that ends the game, even though the game's endTime
is still far in the future.
In such a case, the getTimeRemaining()
function still relies on the original endTime
and does not account for the manual intervention that ended the game early.
Let’s assume:
The game is supposed to last 1 hour (3600 seconds).
The game’s endTime
is set to block.timestamp + 3600
.
The game is manually ended after 30 minutes (1800 seconds).
Now, if a player calls getTimeRemaining()
, it would return:
However, since the game was manually ended at the 1800-second mark (30 minutes), there should be no time remaining. But because the getTimeRemaining()
function does not consider the manual game end, it gives the misleading value of 1800 seconds remaining.
Here’s a proof of concept to illustrate how this vulnerability can manifest in the game. The following test simulates a situation where the game is manually ended before the original endTime
.
Start the Game: The game is started with a 1-hour duration.
Simulate Game Progress: We simulate that 30 minutes have passed by using vm.warp()
, which allows us to fast-forward time in the test.
Manual Game End: The game is then manually ended using game.endGame()
.
Check Time Remaining: After the game is manually ended, we check the time remaining with game.getTimeRemaining()
. This should return 0
Since the game was manually ended. However, the vulnerability means it could return the wrong value (e.g., 1800
), which is incorrect.
While this vulnerability might seem minor at first, it has the potential to severely affect how the game is perceived and played, especially when it comes to transparency and player experience.
Misleading Information: Players might think that they have more time to participate in the game or complete tasks when, in reality, the game has already ended. This can lead to confusion, frustration, and a poor player experience.
Potential Abuse: If the game end time is incorrectly reported, malicious actors may use this to exploit the game, believing they still have time to act (such as searching for eggs in this case). This is especially important if the game's outcome is dependent on the time remaining.
Inaccurate Statistics: Reporting incorrect time remaining can also mess with the game's statistics and reporting mechanisms. If any part of the game logic is time-dependent, such as rewards or leaderboard updates, they could be incorrectly calculated, leading to unfair outcomes.
Compromising Admin Actions: Admins or game managers who manually end games need to rely on accurate time reporting. If they mistakenly believe the game is still ongoing when it isn’t, they might make decisions based on outdated or incorrect information, leading to further mismanagement of the game state.
The fix for this vulnerability is relatively straightforward: The getTimeRemaining()
function needs to be updated to check whether the game has been manually ended. If the game was manually ended, the function should return 0
regardless of the endTime
.
getTimeRemaining()
Function:In this example, gameEnded
would be a boolean variable that gets set to true
when an admin manually ends the game using a function like endGame()
. This ensures that the game’s time remaining is reported accurately, even if the game ends prematurely.
Ensure that the gameEnded
state is updated whenever an admin calls endGame()
.
This update does not require a change in how the game’s endTime
is set or managed, but rather adds an extra check to account for manual termination.
The issue with incorrect game status reporting arises from the failure to account for manually ended games in the getTimeRemaining()
function. This leads to misleading time remaining values, which can confuse players, compromise game integrity, and lead to incorrect game outcomes.
By adding a check for manual game termination, we can ensure that the getTimeRemaining()
function always reports accurate information, improving the fairness and transparency of the game.
Incorrect values reported when a game is ended early
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.