OrderBook

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

L - OrderBook.sol - Accidentally Sent USDC Cannot Be Recovered

Root + Impact

Description

The OrderBook contract should allow recovery of accidentally sent tokens while protecting funds that are legitimately locked in orders. USDC is only used for fees and payments, never deposited by users in sell orders, so any excess USDC beyond tracked fees should be recoverable.

However, the emergency withdrawal function blocks all USDC withdrawals, preventing recovery of accidentally sent USDC that exceeds the tracked fee amount.

function emergencyWithdrawERC20(address _tokenAddress, uint256 _amount, address _to) external onlyOwner {
if (
_tokenAddress == address(iWETH) || _tokenAddress == address(iWBTC) || _tokenAddress == address(iWSOL)
@> || _tokenAddress == address(iUSDC) // Blocks ALL USDC withdrawals
) {
revert("Cannot withdraw core order book tokens via emergency function");
}
// ... rest of function
}
function withdrawFees(address _to) external onlyOwner {
// Only withdraws tracked fees, not accidentally sent USDC
@> iUSDC.safeTransfer(_to, totalFees);
totalFees = 0;
}

Risk

Likelihood:

  • Users may accidentally send USDC during testing or integration

  • Developers might send tokens to wrong addresses during deployment

Impact:

  • Accidentally sent USDC becomes permanently locked in the contract

  • Potential loss of funds due to user error or integration mistakes

Recommended Mitigation

Allow emergency withdrawal of excess USDC beyond tracked fees:

function emergencyWithdrawERC20(address _tokenAddress, uint256 _amount, address _to) external onlyOwner {
if (
_tokenAddress == address(iWETH) || _tokenAddress == address(iWBTC) || _tokenAddress == address(iWSOL)
- || _tokenAddress == address(iUSDC)
) {
revert("Cannot withdraw core order book tokens via emergency function");
}
+
+ // For USDC, only allow withdrawal of excess beyond tracked fees
+ if (_tokenAddress == address(iUSDC)) {
+ uint256 excessUSDC = iUSDC.balanceOf(address(this)) - totalFees;
+ if (_amount > excessUSDC) revert InsufficientExcessBalance();
+ }
+
if (_to == address(0)) {
revert InvalidAddress();
}
IERC20 token = IERC20(_tokenAddress);
token.safeTransfer(_to, _amount);
emit EmergencyWithdrawal(_tokenAddress, _amount, _to);
}

This allows recovery of accidentally sent USDC while protecting legitimate fees.

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.