OrderBook

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

[Gas-2] Missing check for Sufficient Token Balance in `emergencyWithdrawERC20` function in the `OrderBook` contract

Description:
The emergencyWithdrawERC20 function in the OrderBook contract currently lacks a check to verify that the contract holds a sufficient balance of the specified ERC20 token before attempting to process a withdrawal. As a result, if the contract owner tries to withdraw more tokens than are actually available in the contract, the function will proceed until it reaches the token.safeTransfer(_to, _amount); statement, at which point the transaction will revert due to insufficient balance. This revert occurs only after the function has already performed other checks and computations, leading to unnecessary gas consumption and a less user-friendly experience.

Additionally, the absence of a pre-transfer balance check can make it harder for users and integrators to quickly diagnose why a withdrawal transaction failed, as the revert will be triggered deep within the ERC20 transfer logic rather than by a clear, descriptive error at the start of the function.

Impact:
Failing to check the contract's token balance before attempting a withdrawal can result in wasted gas for the contract owner, who may repeatedly attempt to withdraw an unavailable amount without understanding the cause of the failure. Each failed attempt incurs gas costs, and the error message may not be immediately clear, especially if the underlying ERC20 implementation does not provide detailed revert reasons. This inefficiency can be particularly frustrating in emergency situations where quick and predictable access to funds is critical. Moreover, the lack of an explicit check reduces the overall robustness and clarity of the contract's code.

Proof of Concept:

  1. Suppose the contract holds 100 tokens of a particular ERC20 token.

  2. The owner initiates a call to emergencyWithdrawERC20 with _amount = 200.

  3. The function performs its initial checks (such as verifying the token is not a core protocol token and that the recipient address is valid), but does not check the contract's token balance.

  4. The function then calls token.safeTransfer(_to, _amount);, which reverts because the contract does not have enough tokens to fulfill the transfer.

  5. The owner pays gas for the failed transaction, and the revert message may not clearly indicate that the failure was due to insufficient contract balance.

Recommended Mitigation:
To address this issue, add an explicit check at the beginning of the emergencyWithdrawERC20 function to ensure that the contract's balance of the specified token is at least equal to the requested withdrawal amount. If the balance is insufficient, the function should revert immediately with a clear and descriptive error message, saving gas and improving the user experience. For example:

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"
);
}
if (_to == address(0)) {
revert InvalidAddress();
}
IERC20 token = IERC20(_tokenAddress);
+ require(_amount > token.balanceOf(address(this)), "Excess withdrawal error")
token.safeTransfer(_to, _amount);
emit EmergencyWithdrawal(_tokenAddress, _amount, _to);
}
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.