OrderBook

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

Lack of Restriction on setAllowedSellToken Allows Disabling of Core Assets Used by Order Book

Root + Impact

Description

  • In normal behavior, the order book contract relies on core assets such as WETH, WBTC, and WSOL to remain always tradable as sellable tokens. These tokens are whitelisted in the constructor and are expected to be consistently usable throughout the contract's lifetime.

  • However, the setAllowedSellToken function allows the owner to disable any token, including the core ones initialized in the constructor. This contradicts the protocol's intended behavior and could lead to blocked trading activity, even though the tokens are otherwise valid and integrated.

// Root cause in the codebase with @> marks to highlight the relevant section
function setAllowedSellToken(address _token, bool _isAllowed) external onlyOwner {
if (_token == address(0) || _token == address(iUSDC)) revert InvalidToken();
@> allowedSellToken[_token] = _isAllowed;
emit TokenAllowed(_token, _isAllowed);
}

Risk

Likelihood: Low

  • This issue can only be triggered by the contract owner.

  • It requires the owner to deliberately or accidentally disable a core asset using setAllowedSellToken.

Impact: Medium

  • Disabling a core token like WETH would prevent users from placing or filling orders using that token.

  • If ownership is renounced after disabling, the system becomes permanently unable to re-enable that token, breaking a fundamental trading path.

Proof of Concept

owner Disables weth using setAllowedSellToken.

  • Alice fails to create an order because it's no longer in allowedSellToken.

  • Then the owner attempts to withdraw WETH via emergencyWithdrawERC20, which fails not because of allowedSellToken, but because it's still classified as a protected core token.

function test_AbleToDisableCoreContractToken() public {
// Owner disables a core order book token (WETH)
vm.startPrank(owner);
book.setAllowedSellToken(address(weth), false);
vm.stopPrank();
// Alice tries to create a sell order with the now-disabled WETH
vm.startPrank(alice);
weth.approve(address(book), 1 ether);
vm.expectRevert(); // Expect revert due to token being not allowed
book.createSellOrder(address(weth), 1 ether, 1500e6, 2 days);
vm.stopPrank();
// Owner tries to perform emergency withdrawal of WETH
// But WETH is still treated as a protected core token, so should revert
vm.startPrank(owner);
// First, simulate someone accidentally sending WETH to the contract
deal(address(weth), address(book), 1 ether);
vm.expectRevert("Cannot withdraw core order book tokens via emergency function");
book.emergencyWithdrawERC20(address(weth), 1 ether, owner);
vm.stopPrank();
}

Recommended Mitigation

Prevents the owner from disabling core order book tokens (WETH, WBTC, WSOL) to ensure essential trading functionality remains intact and protocol behavior stays consistent.

- remove this code
+ add this code
function setAllowedSellToken(address _token, bool _isAllowed) external onlyOwner {
if (_token == address(0) || _token == address(iUSDC)) revert InvalidToken();
+ if (!_isAllowed && (
+ _token == address(iWETH) || _token == address(iWBTC) || _token == address(iWSOL)
+ )) {
+ revert("Cannot disable core order book tokens");
+ }
allowedSellToken[_token] = _isAllowed;
emit TokenAllowed(_token, _isAllowed);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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