OrderBook

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

Bypass of Token Allowlist in Active Orders

Root + Impact

The buyOrder function does not revalidate whether the token being bought is still allowed:

if (!allowedSellToken[order.tokenToSell]) revert InvalidToken(); // Missing

This check exists in createSellOrder(...) but is omitted in buyOrder(...). Thus, once an order is created, its execution is not blocked even if the associated token is later marked as disallowed.

Description

The contract fails to enforce the allowed token list (allowedSellToken) during the execution of active sell orders. This allows users to buy tokens that have been explicitly disallowed by the contract owner, defeating the purpose of the allowlist mechanism and potentially exposing users to risky or malicious tokens.

Risk

Likelihood: Medium (public function, easy to exploit)

Severity:High (token security bypass)

Impact:

  • Security Risk: Users can be tricked into buying tokens that the admin has deemed dangerous (e.g., malicious or scam tokens).

  • Control Bypass: The setAllowedSellToken() function becomes ineffective after order creation.

Proof of Concept

function test_buyBlacklistedTokenOrder() public {
// alice creates sell order for wbtc
vm.startPrank(alice);
wbtc.approve(address(book), 2e8);
uint256 aliceId = book.createSellOrder(address(wbtc), 2e8, 180_000e6, 2 days);
vm.stopPrank();
//assert checks
assert(aliceId == 1);
assert(wbtc.balanceOf(alice) == 0);
assert(wbtc.balanceOf(address(book)) == 2e8);
//owner removes wbtc as allowed token
vm.prank(owner);
book.setAllowedSellToken(address(wbtc), false);
vm.stopPrank();
//assert check
assert(book.allowedSellToken(address(wbtc))== false);
//dan attempts to buy the blacklisted token
vm.startPrank(dan);
usdc.approve(address(book), 200_000e6);
book.buyOrder(aliceId); // dan buys alice wbtc order
vm.stopPrank();
//assert check
assert(wbtc.balanceOf(dan) == 2e8);
}
//

** . Alice creates a sell order** for WBTC (a currently allowed token).

  • WBTC is transferred to the contract (2 WBTC held in book).

  • Owner blacklists WBTC using setAllowedSellToken(..., false).

  • Blacklist is not enforced in buyOrder().

  • Dan buys the order and receives the blacklisted WBTC.

  • Bypass observed: Disallowed token can still be sold.

  • Impact: Breaks admin control; blacklisting is ineffective.

Recommended Mitigation

Add the missing validation check in the buyOrder() function:

if (!allowedSellToken[order.tokenToSell]) revert InvalidToken(); // Enforce token allowlist
Updates

Lead Judging Commences

yeahchibyke Lead Judge
11 days ago
yeahchibyke Lead Judge 11 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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