OrderBook

First Flight #43
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

Timestamp Manipulation + Minor Gaming Risk

Description

  • Blockchain applications should account for the fact that miners can manipulate timestamps within certain bounds.

  • The contract relies on block.timestamp for deadline enforcement, which miners can manipulate by up to ~15 seconds, potentially affecting order timing.

function createSellOrder(...) public returns (uint256) {
// ...
uint256 deadlineTimestamp = block.timestamp + _deadlineDuration;
// ...
}
function amendSellOrder(...) public {
// ...
if (block.timestamp >= order.deadlineTimestamp) revert OrderExpired();
uint256 newDeadlineTimestamp = block.timestamp + _newDeadlineDuration;
// ...
}
function buyOrder(uint256 _orderId) public {
// ...
if (block.timestamp >= order.deadlineTimestamp) revert OrderExpired();
// ...
}

Risk

Likelihood:

  • When orders have very short deadlines (minutes to hours)

  • When miners have incentive to include/exclude specific transactions

  • During periods of high network congestion with MEV opportunities

Impact:

  • Orders may expire slightly earlier or later than intended

  • Miners could potentially manipulate order execution timing

  • Minor unfairness in deadline enforcement (±15 seconds)

Proof of Concept

Miner Manipulation Scenario: This demonstrates how miners can manipulate timestamps to affect order timing.

function testTimestampManipulation() public {
// Alice creates order with 1 hour deadline
vm.startPrank(alice);
weth.approve(address(book), 1e18);
uint256 orderId = book.createSellOrder(address(weth), 1e18, 3000e6, 1 hours);
vm.stopPrank();
// Simulate miner manipulation - advance time to just before expiry
vm.warp(block.timestamp + 1 hours - 10); // 10 seconds before expiry
// Miner could manipulate timestamp by +15 seconds to expire the order
vm.warp(block.timestamp + 15);
// Order is now expired due to timestamp manipulation
vm.startPrank(dan);
usdc.approve(address(book), 3000e6);
vm.expectRevert(OrderBook.OrderExpired.selector);
book.buyOrder(orderId);
vm.stopPrank();
}

Manipulation scenarios:

  • Favorable inclusion: Miner manipulates timestamp to make favorable orders execute

  • Unfavorable exclusion: Miner manipulates timestamp to prevent unfavorable orders

  • MEV opportunities: Miners coordinate timestamp manipulation with arbitrage strategies

  • Short deadline orders: Orders with minutes-level deadlines are most vulnerable

  • Network congestion: During high gas periods, miners have more manipulation incentive

Recommended Mitigation

Solution: Document the limitation and consider block-based deadlines for critical applications.

// Document the timestamp dependency
/// @dev Uses block.timestamp which can be manipulated by miners by ~15 seconds
/// Consider this tolerance when setting short deadlines
// For more critical applications, consider block-based deadlines:
+ uint256 public constant AVERAGE_BLOCK_TIME = 12; // seconds
function createSellOrder(
address _tokenToSell,
uint256 _amountToSell,
uint256 _priceInUSDC,
- uint256 _deadlineDuration
+ uint256 _deadlineBlocks
) public returns (uint256) {
- uint256 deadlineTimestamp = block.timestamp + _deadlineDuration;
+ uint256 deadlineBlock = block.number + _deadlineBlocks;
orders[orderId] = Order({
// ...
- deadlineTimestamp: deadlineTimestamp,
+ deadlineBlock: deadlineBlock,
// ...
});
}

Why this works:

  • Block-based deadlines: Miners cannot manipulate block numbers as easily as timestamps

  • Predictable progression: Blocks advance at a more predictable rate than timestamps

  • Reduced manipulation: Eliminates the ±15 second timestamp manipulation window

  • Better for short deadlines: More reliable for time-sensitive orders

Trade-offs:

  • Variable block times: Block times can vary (8-20 seconds), making exact timing harder

  • User experience: Users think in time units, not blocks

  • Current implementation: May be acceptable for most use cases with longer deadlines (hours/days)

Updates

Lead Judging Commences

yeahchibyke Lead Judge
14 days ago
yeahchibyke Lead Judge 8 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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