OrderBook

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

Reentrancy in amendSellOrder and buyOrder functions allows malicious token contracts to manipulate state and potential fund theft.

Root + Impact

Description

  • Describe the normal behavior in one or more sentences

In the current implementation of [amendSellOrder], when the seller decreases the amount of tokens to sell, the contract refunds the token difference before updating the internal [amountToSell] value.

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

If a malicious ERC-20 token with a callback in transfer can reenter [amendSellOrder] before the state update, at a point where [order.amountToSell] still holds the older value. The attacker can repeatedly trigger this logic to manipulate or drain more tokens than intended.

Risk

Likelihood:

  • Reason 1 // Describe WHEN this will occur (avoid using "if" statements)

Seller creates token an order with malicious token.

Seller amends token to reduce token amount.

Token executes callback during [safeTransfer].

Order Manipulation: Attackers can bypass logical checks by exploiting stale state data during reentry.

Impact:

  • Impact 1

    Very high. Any ERC‑20 integrated with your book (even as payment) could carry malicious hooks.

  • Impact 2

    Other users' tokens in the contract are at risk.

    Order Book Corruption: Attackers can manipulate active orders

Potential loss of all tokens in an order, manipulation of orders’ balances, or complete order‑book corruption.

Proof of Concept

Attacker adds malicious token

Then token is whitelisted(unawares)

Attacker creates order with 100 tokens

Attacker calls [attack(orderId)]
a. Contract processes 99 token refund (100 → 1)
b. During transfer, malicious callback triggers
c. Nested [amendSellOrder] executes with ORIGINAL 100 token balance
d. Second refund of 99 tokens processed
e. State finally updates to 1 token

Attacker receives 198 tokens instead of 99

if (_newAmountToSell < order.amountToSell) {
uint256 diff = order.amountToSell - _newAmountToSell;
// Wrong: Transfer occurs before state update
token.safeTransfer(order.seller, diff);
order.amountToSell = _newAmountToSell;
}

Recommended Mitigation

Adding reentrancy protection at contract level.

Always update state variables BEFORE token transfers

Implement on-chain checks for suspicious token behavior.

Require multi-sig approval for new token whitelisting this is to do checks on added tokens.


function amendSellOrder(...) public nonReentrant {
// ...
if (_newAmountToSell < order.amountToSell) {
uint256 diff = order.amountToSell - _newAmountToSell;
// STATE UPDATE FIRST
order.amountToSell = _newAmountToSell;
// THEN INTERACTION
token.safeTransfer(order.seller, diff);
}
// ...
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge
4 months ago
yeahchibyke Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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