Eggstravaganza

First Flight #37
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: low
Invalid

Off-by-one error in game end time check allows searching at the exact end time

Summary

The searchForEgg function uses an inclusive comparison (<=) when checking the game's end time (block.timestamp <= endTime). This allows players to potentially search for an egg at the exact timestamp the game is supposed to end, effectively extending the game duration slightly beyond the intended period. A similar issue exists in the getGameStatus function.

Vulnerability Details

In the EggHuntGame contract, the startGame function sets the endTime based on the provided duration: endTime = block.timestamp + duration;. This implies that the game duration spans exactly duration seconds, ending before the endTime timestamp.

However, the searchForEgg function checks if the game is still active using require(block.timestamp <= endTime, "Game ended");:

function searchForEgg() external {
// ... other checks ...
require(block.timestamp <= endTime, "Game ended"); // Allows searching at exactly endTime
// ... rest of the function ...
}

This condition allows a transaction to succeed if block.timestamp is exactly equal to endTime. This means a player could potentially search for an egg one last time precisely at the moment the game is scheduled to conclude.

A similar inclusive check is present in the getGameStatus function:

function getGameStatus() external view returns (string memory) {
if (gameActive) {
// ... other checks ...
} else if (block.timestamp >= startTime && block.timestamp <= endTime) { // Inclusive check
return "Game is active";
} else {
return "Game time elapsed";
}
// ... rest of the function ...
}

This could incorrectly report the game as "active" at the exact endTime.

Impact

The primary impact is a potential off-by-one error where the game duration is effectively extended by one timestamp unit (one block) if a player manages to execute searchForEgg exactly at endTime. This contradicts the duration set by the owner in startGame and slightly deviates from the expected game rules. While the likelihood of hitting this exact timestamp might be low, it represents an inconsistency in time boundary handling.

Tools Used

Manual Review

Recommendations

Modify the time checks in both searchForEgg and getGameStatus to use a strict less than (<) comparison with endTime. This ensures that actions and status checks accurately reflect that the game concludes before the endTime timestamp.

  1. In searchForEgg:

    function searchForEgg() external {
    // ... other checks ...
    require(block.timestamp < endTime, "Game ended"); // Change <= to <
    // ... rest of the function ...
    }
  2. In getGameStatus:

    function getGameStatus() external view returns (string memory) {
    if (gameActive) {
    // ... other checks ...
    } else if (block.timestamp >= startTime && block.timestamp < endTime) { // Change <= to <
    return "Game is active";
    } else { // This condition now correctly includes endTime
    return "Game time elapsed";
    }
    // ... rest of the function ...
    }
Updates

Lead Judging Commences

m3dython Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.