Description:
The emergencyWithdrawERC20
function is intended to allow the owner to recover non-core tokens accidentally sent to the contract. It contains a check to prevent the withdrawal of the four initial tokens (iWETH
, iWBTC
, iWSOL
, iUSDC
). However, this check is static and does not account for new tokens added via the setAllowedSellToken
function. This creates a critical vulnerability where the owner can introduce a new market and then rug all the liquidity providers for that market.
Attack Scenario:
The owner observes that a new token, XYZ
, is gaining popularity.
The owner calls setAllowedSellToken(address(XYZ), true)
, officially opening a market for XYZ
on the platform.
Multiple users, trusting the platform, create sell orders for XYZ
, transferring their tokens into the custody of the OrderBook.sol
contract.
The emergencyWithdrawERC20
function's safety check does not recognize XYZ
as a core token, as its address is not one of the four immutable addresses from the constructor.
The owner calls emergencyWithdrawERC20(address(XYZ), XYZ.balanceOf(address(this)), owner_address)
, draining the contract of all deposited XYZ
tokens.
Recommendation:
The safety mechanism in emergencyWithdrawERC20
is critically flawed. The check should not be against a static list of tokens. Instead, it should verify that the token being withdrawn is not an actively supported market. The most robust solution is to check against the allowedSellToken
mapping.
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.