OrderBook

First Flight #43
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: low
Valid

Expired Orders Remain Active and Lock Tokens Indefinitely Causing Potential Denial of Service

Root + Impact

Description

  • Normally, sellers create orders with deadlines and can cancel or amend them. Once expired, orders should ideally be cleared or made inactive to free locked tokens.

  • The contract does not automatically handle expired orders, and only the seller can cancel them. If a seller abandons or ignores an expired order, the tokens remain locked indefinitely, causing a denial of service by blocking access to those tokens and reducing market liquidity.

function cancelSellOrder(uint256 _orderId) public {
Order storage order = orders[_orderId];
// Validation checks
if (order.seller == address(0)) revert OrderNotFound();
if (order.seller != msg.sender) revert NotOrderSeller(); // @> Only the seller can cancel the order
if (!order.isActive) revert OrderAlreadyInactive(); // @> Order must be active to cancel
// Mark as inactive
order.isActive = false;
// Return locked tokens to the seller
IERC20(order.tokenToSell).safeTransfer(order.seller, order.amountToSell);
emit OrderCancelled(_orderId, order.seller);
}

Risk

Likelihood:

  • Sellers may abandon or neglect to cancel their expired orders, leaving tokens locked indefinitely.

  • The contract lacks an automatic mechanism or alternative party to reclaim tokens from expired orders, making this a recurring issue over time.

Impact:

  • Locked tokens reduce market liquidity and degrade user experience, as those funds become unusable.

  • Prolonged token locking can lead to loss of user trust and hinder the platform’s reputation and adoption.

Proof of Concept


A seller creates a sell order with a short deadline. After the order expires, if the seller does not cancel the order to reclaim their tokens, those tokens remain locked in the contract indefinitely. Since no mechanism allows others to recover these tokens, they become permanently inaccessible, causing a denial of service.

// Seller creates an order and transfers tokens to the contract
orderId = orderBook.createSellOrder(tokenAddress, amount, price, shortDeadline);
// Time passes, order expires (block.timestamp > deadline)
// No cancellation by seller, tokens remain in contract
// No function exists to recover tokens by others
// Attempt to buy order will revert due to expiration
orderBook.buyOrder(orderId); // Reverts with OrderExpired error
// Tokens locked indefinitely inside contract for this order

Recommended Mitigation

Allow anyone to cancel expired orders to release locked tokens, preventing indefinite lockup and improving market liquidity.

- remove this code
Remove this code (no automatic handling of expired orders):
// No automatic expiry handling; only seller can cancel orders
+ add this code
Add this code to enable anyone to cancel expired orders and unlock tokens:
error OrderNotExpired();
function cancelExpiredOrder(uint256 _orderId) external {
Order storage order = orders[_orderId];
if (order.seller == address(0)) revert OrderNotFound();
if (!order.isActive) revert OrderAlreadyInactive();
if (block.timestamp < order.deadlineTimestamp) revert OrderNotExpired();
order.isActive = false;
IERC20(order.tokenToSell).safeTransfer(order.seller, order.amountToSell);
emit OrderCancelled(_orderId, order.seller);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Expired orders can cause backlog

By design only `seller` can call `cancelSellOrder()` on their `order`. But when an `order` expires, and the `seller` doesn't have access to the protocol, the expired `order `should be be able to be cancelled by an `admin`.

Support

FAQs

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