OrderBook

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

[M-1] Missing Reentrancy Protection on Critical External Functions


Description

The `OrderBook` contract lacks reentrancy protection on key functions that interact with user funds and token transfers.
Specifically:
`buyOrder()`, `amendSellOrder()`, `cancelSellOrder()`, `withdrawFees()`
While `SafeERC20` is used, it does not protect against reentrancy attacks initiated by malicious or non-standard ERC20 tokens that may invoke reentrant calls via fallback or hook mechanisms (e.g., transfer, approve, transferFrom behaviors).
This violates a widely accepted best practice: using the Checks-Effects-Interactions (CEI) pattern along with nonReentrant modifiers in any function that handles external token transfers.

Risk

Impact:

A malicious token could re-enter functions like `withdrawFees()` or `buyOrder()`, potentially interfering with internal state updates like `totalFees`, `order.isActive`, etc.
Combined with CEI violations (which you’ve already flagged), this can lead to:
- Double-withdrawal of fees
- Inconsistent order status
- Unintended token drains
While such attacks are rare in well-behaved ERC20 tokens, many tokens (especially wrapped tokens, proxies, or composable contracts) have custom fallback behaviors that can break assumptions.

Proof of Concept

Imagine a malicious token that implements the following pattern:
```javascript
function transfer(address to, uint256 amount) public override returns (bool) {
// Callback on transfer (not part of ERC20, but possible)
OrderBook(orderBookAddress).withdrawFees(attackerAddress); // Reentrant call
return true;
}
```
If the `OrderBook` contract sends such a token or receives it via `safeTransferFrom`, it executes the transfer, which then re-enters into a vulnerable function, bypassing internal logic due to improper CEI or no guard.

Recommended Mitigation

1. Inherit ReentrancyGuard from OpenZeppelin:
```javascript
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract OrderBook is Ownable, ReentrancyGuard {
...
}
```
2. Add nonReentrant modifier to sensitive external functions:
```javascript
function buyOrder(uint256 _orderId) public nonReentrant { ... }
function cancelSellOrder(uint256 _orderId) public nonReentrant { ... }
function amendSellOrder(...) public nonReentrant { ... }
function withdrawFees(address _to) public onlyOwner nonReentrant { ... }
```
Updates

Lead Judging Commences

yeahchibyke Lead Judge
about 1 month ago
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.