Critical Vulnerability in emergencyWithdrawERC20()
Allows Withdrawal of Tokens Locked in Active Orders, Causing Permanent Loss of User Funds
The emergencyWithdrawERC20()
function contains a critical vulnerability that allows the contract owner to withdraw tokens that are currently locked in active sell orders. This function was designed to withdraw accidentally sent tokens, but it fails to distinguish between "free" tokens and tokens that are locked as collateral for active orders. When tokens locked in orders are withdrawn, the affected orders become permanently unfulfillable, leading to irreversible loss of user funds and breaking the protocol's core functionality.
The emergencyWithdrawERC20()
function is intended to allow the owner to recover tokens that were accidentally sent to the contract. However, the function has a fundamental flaw in its design - it does not check whether the tokens being withdrawn are currently locked in active orders.
Vulnerable Code:
The function only prevents withdrawal of the four core tokens (WETH, WBTC, WSOL, USDC) but allows withdrawal of any other ERC20 token, regardless of whether those tokens are locked in active orders.
Attack Scenario:
Owner allows a custom ERC20 token for trading via setAllowedSellToken()
Users create sell orders with this custom token, locking their tokens in the contract
Owner calls emergencyWithdrawERC20()
to withdraw these locked tokens
Orders remain active in the system but cannot be fulfilled
Users cannot buy the orders (insufficient tokens in contract)
Users cannot cancel their orders (contract has no tokens to return)
User funds are permanently lost
This vulnerability has severe consequences for the protocol and its users:
Direct Financial Impact:
Permanent Loss of User Funds: Users who have active sell orders with affected tokens lose their locked tokens permanently
Protocol Insolvency: The contract becomes unable to fulfill its obligations to users
Broken Order State: Orders remain active in the system but are impossible to execute or cancel
Operational Impact:
Complete Protocol Breakdown: For affected tokens, the entire order book functionality becomes non-operational
Loss of User Trust: Users lose confidence in the protocol's ability to protect their funds
Legal and Regulatory Risk: Permanent loss of user funds could lead to legal consequences
Technical Impact:
State Inconsistency: The contract's internal state (active orders) becomes inconsistent with its actual token holdings
Cascading Failures: Multiple orders can be affected simultaneously if they use the same token
High. This vulnerability can be triggered by the contract owner at any time for any non-core token that has active orders. The conditions required are:
A non-core token is allowed for trading (common operational requirement)
Users create orders with this token (normal protocol usage)
Owner calls emergencyWithdrawERC20()
(intended for legitimate emergency use)
The vulnerability does not require malicious intent from the owner - it could be triggered accidentally during legitimate emergency operations.
The following test demonstrates the critical vulnerability where emergency withdrawal breaks active orders and causes permanent loss of user funds.
Test File: test/EmergencyWithdrawTokenLockingVulnerability.t.sol
Successful Test Output:
The test clearly demonstrates that:
The emergency withdraw function successfully removes all tokens from the contract
Active orders remain in the system but become unfulfillable
Users cannot buy or cancel these broken orders
User funds are permanently lost
The emergencyWithdrawERC20()
function must be modified to prevent withdrawal of tokens that are locked in active orders. Here are the recommended fixes:
Add a mapping to track how many tokens of each type are currently locked in active orders:
Prevent emergency withdrawal of any token that is currently allowed for trading:
Require that all orders be cancelled before emergency withdrawal:
Critical. This vulnerability meets all criteria for critical severity:
Direct Loss of Funds: Users can permanently lose their tokens locked in orders
Protocol Breaking: The core functionality of the order book becomes non-operational for affected tokens
No Recovery Mechanism: Once tokens are withdrawn, there is no way to restore the broken orders
High Likelihood: The vulnerability can be triggered during normal protocol operations
Wide Impact: Multiple users and orders can be affected simultaneously
The emergencyWithdrawERC20()
function represents a critical security flaw that undermines the fundamental safety guarantees of the OrderBook protocol. The function's inability to distinguish between free and locked tokens creates a scenario where legitimate emergency operations can result in permanent loss of user funds. This vulnerability must be addressed immediately before the protocol is deployed to mainnet or handles significant user funds.
The recommended fix (Option 1) provides the most robust solution by implementing proper token accounting that tracks locked balances, ensuring that emergency withdrawals can only affect truly "free" tokens while preserving the protocol's ability to fulfill its obligations to users.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.