OrderBook

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

Denial of service (DoS) in `emergencyWithdrawERC20` function

No balance check for amount in emergency withdraw in emergencyWithdrawERC20 function.

Description

The function allows the contract owner to withdraw a particular amount from the contract balance incase of an emergency Normally there should be check to keep track of the amount of withdrawable tokens.

But instead, the function did not verify whether the contract has enough balance of token to withdraw before calling the token.safeTransfer(_to, _amount). If _amount is greater than the contract’s balance, the transfer will fail, reverting the that particular transaction.

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);
@> token.safeTransfer(_to, _amount);
emit EmergencyWithdrawal(_tokenAddress, _amount, _to);
}

Risk

Likelihood:

This will happen whenever the contract owner calls the emergencyWithdrawERC20 function and inputs an amount greater than the contract balance.

Impact:

The impact will be that the entire transaction will be reverted

Proof of Concept

  1. I initiated the contract with only 1 token.

  2. Then attempted to withdraw 10 tokens.

  3. Since the contract did check the balance, it reverts due to insufficient funds.

  4. The expectRevert() line confirms that the function will terminate, leading to DoS of the protocol

function testEmergencyWithdrawFailsOnOverdraw() public {
vm.prank(owner);
// Intentionally requesting more than contract holds (10 ether > 1 ether)
uint256 requestedAmount = 10 ether;
vm.expectRevert(); // Expect it to fail
@> book.emergencyWithdrawERC20(address(token), requestedAmount, owner);
vm.stopPrank();
}

Recommended Mitigation

Add a simple balance check before attempting the transfer

+ uint256 contractBalance = token.balanceOf(address(this));
+ if (_amount > contractBalance) {
+ revert("Insufficient token balance for emergency withdrawal");}
IERC20 token = IERC20(_tokenAddress);
token.safeTransfer(_to, _amount);
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

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