OrderBook

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

## OrderBook.sol ## [ Missing check for Allowance and Balance ]

Root + Impact

Description

The buyOrder function does not validate whether the buyer has enough USDC balance or has granted sufficient allowance before calling safeTransferFrom. Without these pre-checks, the transaction may revert unexpectedly during execution, leading to a poor user experience and wasted gas.

function buyOrder(uint256 _orderId) public {
Order storage order = orders[_orderId];
// Validation checks
if (order.seller == address(0)) revert OrderNotFound();
if (!order.isActive) revert OrderNotActive();
if (block.timestamp >= order.deadlineTimestamp) revert OrderExpired();
order.isActive = false;
uint256 protocolFee = (order.priceInUSDC * FEE) / PRECISION;
uint256 sellerReceives = order.priceInUSDC - protocolFee;
iUSDC.safeTransferFrom(msg.sender, address(this), protocolFee);
iUSDC.safeTransferFrom(msg.sender, order.seller, sellerReceives);
IERC20(order.tokenToSell).safeTransfer(msg.sender, order.amountToSell);
totalFees += protocolFee;
emit OrderFilled(_orderId, msg.sender, order.seller);
}

Risk

Likelihood:

  • The issue occurs when a user attempts to buy an order without approving enough USDC allowance or lacking sufficient balance.

Impact:

  • The transaction reverts mid-way, wasting gas and causing confusion.

  • It may lead to frustration for users especially if the dApp UI doesn’t handle or explain the error clearly.

Proof of Concept

A user with:

balanceOf(user) = 10 USDC
allowance(user, contract) = 5 USDC
tries to purchase an order worth 12 USDC

The transaction reverts during safeTransferFrom, despite passing earlier validations.


Recommended Mitigation

Add explicit checks for allowance and balance before proceeding with transfers:

+ uint256 totalAllowance = iUSDC.allowance(msg.sender, address(this));
+ if (totalAllowance < order.priceInUSDC) {
+ revert InsufficientAllowance();
+ }
+ uint256 userBalance = iUSDC.balanceOf(msg.sender);
+ if (userBalance < order.priceInUSDC) {
+ revert InsufficientBalance();
+ }

This improves fail-fast behavior, user experience, and avoids unnecessary gas usage.

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.