OrderBook

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

Deadline Bypass Before Expiration

Description

The contract allows users to create orders with a deadline field, intended to signal expiration. However, this deadline is never enforced by the smart contract. The order remains executable even after the deadline has passed, unless is explicitly cancelled by the user.

@> order.deadline is stored but never checked in buyOrder() or sellOrder()

This leads to a trust issue where users believe an order is no longer active, but it can still be executed by others, causing confusion or financial loss in a time-sensitive scenario.

Risk


Likelihood:

  • This happens every time a user submits an order with a deadline and forgets to cancel it.

  • May be triggered by third parties calling buyOrder() on expired orders.


Impact:

  • Unexpected trades after user-intended expiration

  • Out-of-date transactions can still be completed

  • Potential front-running if market price has changed since the expiration


Proof of Concept


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOrderBook {
function createOrder(
address token,
uint256 amount,
uint256 price,
uint256 deadline
) external returns (uint256);
function buyOrder(uint256 orderId, uint256 amount) external;
}
contract DeadlineExploit {
IOrderBook public orderbook;
uint256 public orderId;
constructor(address _orderbook) {
orderbook = IOrderBook(_orderbook);
}
function createExpiringOrder() external {
// Create an order that expires in 10 seconds
orderId = orderbook.createOrder(
address(0xToken), // Example token address
100 * 1e18,
1 * 1e18,
block.timestamp + 10
);
}
function exploitExpiredOrder() external {
// Wait 11 seconds, then call this
orderbook.buyOrder(orderId, 10 * 1e18);
// even though the deadline has passed, buyOrder() still works
}
}

Recommended Mitigation

Check the order’s deadline during execution functions like buyOrder():

require(order.deadline == 0 || block.timestamp <= order.deadline, "Order expired");

This allows flexibility:

  • deadline == 0 means no expiration (optional for permanent orders)

  • Otherwise, the order must be executed before the timestamp

Apply this check in both buyOrder() and any other function that executes trades.


- remove this code
function buyOrder(...) external {
+ add this code
function buyOrder(...) external {
require(order.deadline == 0 || block.timestamp <= order.deadline, "Order expired");
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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