OrderBook

First Flight #43
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Front-running risk in buyOrder function

The OrderBook::buyOrder function is vulnerable to front-running attack as it does not specify a minimum amount of tokens to buy. In case of a front-run, the buyer will receive less tokens than expected

Description

OrderBook::buyOrder function is used to buy an order, however it does not specify a minimum amount of tokens to be received and that makes it vulnerable to front-running attacks

The seller sees the buyOrder transaction in the mempool, it calls the OrderBook::amendSellOrder to sell less tokens for the same amount of money and when the buyOrder is executed, the buyer receives less tokens than expected

Risk

Likelihood:

This vulnerability can occur every time the buyOrder is called and the seller sees the pending transaction in the mempool and front-runs it

Impact:

The buyer will receive less tokens than expected

Proof of Concept

As we can see in the following PoC, Dan received 1e6 tokens instead of 2e8 that he wanted to buy

function testFrontRunRiskinBuyOrderFunction() public {
vm.startPrank(alice);
wbtc.approve(address(book), 2e8);
uint256 aliceId = book.createSellOrder(
address(wbtc),
2e8,
180_000e6,
2 days
);
vm.stopPrank();
vm.prank(alice);
book.amendSellOrder(aliceId,1e6,180_000e6,2 days);
vm.startPrank(dan);
usdc.approve(address(book), 200_000e6);
book.buyOrder(aliceId); // dan buys alice wbtc order
vm.stopPrank();
console2.log("Alice's balance:", usdc.balanceOf(alice));
console2.log("Dan's balance:", wbtc.balanceOf(dan));
}
Logs:
Alice's balance: 174600000000
Dan's balance: 1000000

Recommended Mitigation

I see 2 different solutions. The first solution is to remove the amendSellOrder functionality. In this case, the seller will be unable to modify the amount of tokens for sale. If the team wants to keep this functionality, my second solution is to add a minAmountTokens parameter to the function the will be responsible for the amount of tokens to be received by the buyer

+ function buyOrder(uint256 _orderId, uint256 minAmountTokens) 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();
+ if (order.amountToSell < minAmountTokens) revert NotEnoughTokens();
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Buy orders can be front-run and amended maliciously

A malicious seller can front-run a buy order for their order, and decrease the amount of assets to be sold. If the price is unchanged, the buy transaction fulfills, but the buyer gets lesser amount than expected.

Support

FAQs

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