Rock Paper Scissors

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

block.timestamp

Summary

  • The RockPaperScissors contract relies on block.timestamp to enforce timeouts and deadlines for game actions, which could potentially be manipulated by miners (albeit within a limited timeframe). This dependency appears in game creation, join deadlines, and the reveal phase timing mechanisms.

Vulnerability Details

  • Timestamp Dependence: The contract uses block.timestamp for timeout calculations:

// Setting deadlines during game creation
game.creationTime = block.timestamp;
game.joinDeadline = block.timestamp + joinTimeout;
// Setting reveal deadline after commits
game.revealDeadline = block.timestamp + game.timeoutInterval;
// Checking deadlines during game actions
require(block.timestamp <= game.joinDeadline, "Join deadline passed");
require(block.timestamp <= game.revealDeadline, "Reveal phase timed out");
require(block.timestamp > game.revealDeadline, "Reveal phase not timed out yet");

Impact

Scale of Manipulation: Miners can only adjust timestamps by seconds, while the contract's timeouts are generally much longer:

  • joinTimeout defaults to 24 hours

  • _timeoutInterval must be at least 5 minutes

Potential Scenarios:

  • A miner could delay the inclusion of a move reveal to make it appear to have missed the deadline

  • A player who is also a miner could gain a slight advantage in timing their actions
    In close timeout situations, a miner could intentionally trigger or prevent a timeout

Tools Used

Slither, Cursor, Remix, Foundry

Recommendations

Use Block Numbers Instead of Timestamps:

// Instead of time-based deadlines
uint256 public joinBlocks = 5760; // ~24 hours at 15s/block
game.joinDeadlineBlock = block.number + joinBlocks;
// And in checks
require(block.number <= game.joinDeadlineBlock, "Join deadline passed");

Add Buffer Periods:

// Add a safety margin to timestamp requirements
uint256 constant TIMESTAMP_BUFFER = 30; // seconds
require(block.timestamp + TIMESTAMP_BUFFER <= game.joinDeadline, "Join deadline passed");
Updates

Appeal created

m3dython Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational

Code suggestions or observations that do not pose a direct security risk.

m3dython Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational

Code suggestions or observations that do not pose a direct security risk.

Support

FAQs

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