Beatland Festival

First Flight #44
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

[L-7] - Block Timestamp Manipulation Risk

Block Timestamp Manipulation Risk + Time-Based Logic Exploitability

Description

  • Normal Behavior:
    In Ethereum, block.timestamp is commonly used for time-based logic, such as validating event start times, enforcing cooldowns, or determining if an event is active. However, block.timestamp is not perfectly accurate: miners can manipulate it within a range of up to 30 seconds in either direction. For most applications, this is acceptable, but for high-value or time-sensitive operations, this can be exploited to gain unfair advantages or bypass restrictions.

  • Issue:
    In the FestivalPass contract, several functions use block.timestamp for critical logic:

    • createPerformance: Validates that the start time is in the future.

    • attendPerformance: Checks cooldown periods between attendances.

    • isPerformanceActive: Determines if a performance is currently active.
      Because miners can manipulate block.timestamp, users or validators may be able to attend performances outside intended windows or bypass cooldowns, especially if the contract is deployed on a chain with low block times or low miner diversity.

  • Relevant Code Example:

function createPerformance(uint256 startTime, uint256 duration, uint256 reward) external onlyOrganizer {
@> require(startTime > block.timestamp, "Start time must be in the future");
// ...
}
function attendPerformance(uint256 performanceId) external {
@> require(block.timestamp >= lastCheckIn[msg.sender] + cooldown, "Cooldown period not met");
// ...
}
function isPerformanceActive(uint256 performanceId) public view returns (bool) {
@> return block.timestamp >= start && block.timestamp <= end;
}

Risk

Likelihood:

  • This will occur whenever a miner or validator is incentivized to manipulate the timestamp to benefit themselves or a user, such as to attend a performance early, bypass a cooldown, or claim a reward.

  • The risk is present in all deployments, but is higher on chains with low miner/validator diversity or where time-based rewards are valuable.

Impact:

  • Bypass of Restrictions: Users may be able to attend performances or claim rewards outside the intended time windows.

  • Unfair Advantage: Validators or miners can give themselves or their friends an edge in time-sensitive operations, undermining fairness.

  • Potential MEV: In high-value scenarios, this can be exploited for maximal extractable value (MEV), especially if rewards are significant.

Proof of Concept

To observe the effect of timestamp manipulation, copy and paste the following test code into your test file (e.g., test/contract.t.sol). This test simulates a user attending a performance slightly before the intended window by manipulating the block timestamp:

function test_BlockTimestampManipulation() public {
// Organizer creates a performance scheduled to start in 1 hour
uint256 startTime = block.timestamp + 1 hours;
uint256 duration = 2 hours;
uint256 reward = 100e18;
vm.prank(organizer);
uint256 perfId = festivalPass.createPerformance(startTime, duration, reward);
// User buys a pass
vm.prank(user1);
festivalPass.buyPass{value: 0.05 ether}(1);
// Miner manipulates block.timestamp to just before the start time
vm.warp(startTime - 20); // 20 seconds before official start
// User attempts to attend performance
vm.prank(user1);
// Should revert, but may succeed if block.timestamp is manipulated
bool reverted = false;
try festivalPass.attendPerformance(perfId) {
// If this succeeds, timestamp manipulation is possible
} catch {
reverted = true;
}
// The test passes if the function reverts, fails if it does not
assertTrue(reverted, "Attendance should not be allowed before start time");
}

Explanation:

  • The test schedules a performance and manipulates the block timestamp to just before the start.

  • It attempts to attend the performance, which should fail, but may succeed if timestamp manipulation is possible.

Recommended Mitigation

For most festival use cases, the 30-second window is acceptable and should be documented as a known limitation. For higher-value or more sensitive applications, consider these mitigations:

- require(startTime > block.timestamp, "Start time must be in the future");
+ // Option 1: Use block.number and estimate time based on average block time
+ // Option 2: Use an external time oracle for critical time-based logic

Documentation:

  • Clearly document in the contract and user-facing materials that time-based logic is subject to a small window of miner manipulation.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 2 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.