OrderBook

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

Not Following CEI which leads reentrancy attack in amendSellOrder function

Root + Impact

Description

  • Describe the normal behavior in one or more sentences

  • Explain the specific issue or problem in one or more sentences

// Root cause in the codebase with @> marks to highlight the relevant section
Because of not following CEI(Checks Effects and Interactions) in amendSellOrder function which leads reentrancy attack
so if a attacker create a contract which takes the contract address and contains receive function and another two functions like
toCreateOrder and attack so first the attacker call createOrder function with help contract address with setting low deadlline and high amount.
then he call attack function which will call amend function with low amount so once the amend function send
amount to the contract it he is going to design a recive function in such away that until the totalFees become zero he keeps calliing the amend function
which will drain the total Funds in the contract

Risk

Likelihood:

  • Reason 1 if he call the function with help of other contract

  • Reason 2

Impact:

  • Impact 1 drain total funds in the contract

  • Impact 2

Proof of Concept

//This is my first so that write a Attack contract is the best way to tell how the totalFunds in contract drain
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {OrderBook} from "./OrderBook.sol";
contract Reentrancy {
OrderBook orderbook;
constructor (OrderBook _orderbook){
orderbook = OrderBook(_orderbook);
}
receive() external payable {
if(orderbook.totalFees() > 1) {
attack();
}
}
function callCreateOrder() public {
orderbook.createSellerOrder(addressofthetoken, _amountToSell(big amount),_priceInUSDC,_deadlineDuration);
}
function attack() public {
orderbook.amendSellOrder(uint256 _orderId,uint256 _newAmountToSell(less amount ),uint256 _newPriceInUSDC,uint256 _newDeadlineDuration);
}
}

Recommended Mitigation

- remove this code
function amendSellOrder(
uint256 _orderId,
uint256 _newAmountToSell,
uint256 _newPriceInUSDC,
uint256 _newDeadlineDuration
) public {
Order storage order = orders[_orderId];
// Validation checks
if (order.seller == address(0)) revert OrderNotFound(); // Check if order exists
if (order.seller != msg.sender) revert NotOrderSeller();
if (!order.isActive) revert OrderAlreadyInactive();
if (block.timestamp >= order.deadlineTimestamp) revert OrderExpired(); // Cannot amend expired order
if (_newAmountToSell == 0) revert InvalidAmount();
if (_newPriceInUSDC == 0) revert InvalidPrice();
if (_newDeadlineDuration == 0 || _newDeadlineDuration > MAX_DEADLINE_DURATION) revert InvalidDeadline();
uint256 newDeadlineTimestamp = block.timestamp + _newDeadlineDuration;
IERC20 token = IERC20(order.tokenToSell);
// Handle token amount changes
if (_newAmountToSell > order.amountToSell) {
// Increasing amount: Transfer additional tokens from seller
uint256 diff = _newAmountToSell - order.amountToSell;
token.safeTransferFrom(msg.sender, address(this), diff);
} else if (_newAmountToSell < order.amountToSell) {
// Decreasing amount: Transfer excess tokens back to seller
uint256 diff = order.amountToSell - _newAmountToSell;
token.safeTransfer(order.seller, diff);
}
// Update order details
order.amountToSell = _newAmountToSell;
order.priceInUSDC = _newPriceInUSDC;
order.deadlineTimestamp = newDeadlineTimestamp;
emit OrderAmended(_orderId, _newAmountToSell, _newPriceInUSDC, newDeadlineTimestamp);
}
+ add this code
function amendSellOrder(
uint256 _orderId,
uint256 _newAmountToSell,
uint256 _newPriceInUSDC,
uint256 _newDeadlineDuration
) public {
Order storage order = orders[_orderId];
if (order.seller == address(0)) revert OrderNotFound();
if (order.seller != msg.sender) revert NotOrderSeller();
if (!order.isActive) revert OrderAlreadyInactive();
if (block.timestamp >= order.deadlineTimestamp) revert OrderExpired();
if (_newAmountToSell == 0) revert InvalidAmount();
if (_newPriceInUSDC == 0) revert InvalidPrice();
if (_newDeadlineDuration == 0 || _newDeadlineDuration > MAX_DEADLINE_DURATION) revert InvalidDeadline();
uint256 newDeadlineTimestamp = block.timestamp + _newDeadlineDuration;
IERC20 token = IERC20(order.tokenToSell);
if (_newAmountToSell > order.amountToSell) {
uint256 diff = _newAmountToSell - order.amountToSell;
// updating order.amountToSell will not allow reentrancy
order.amountToSell = _newAmountToSell;
token.safeTransferFrom(msg.sender, address(this), diff);
} else if (_newAmountToSell < order.amountToSell) {
uint256 diff = order.amountToSell - _newAmountToSell;
// updating order.amountToSell will not allow reentrancy
order.amountToSell = _newAmountToSell;
token.safeTransfer(order.seller, diff);
}
// we can also place them front but nothing wrong in keeping them here
order.priceInUSDC = _newPriceInUSDC;
order.deadlineTimestamp = newDeadlineTimestamp;
emit OrderAmended(_orderId, _newAmountToSell, _newPriceInUSDC, newDeadlineTimestamp);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge
about 1 month ago
yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

nolanwick Submitter
about 1 month ago
yeahchibyke Lead Judge
about 1 month ago
yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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