OrderBook

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

Presence of protocolFee variable in buyOrder function causing the orderSeller to receive less USDC than amount in priceInUSDC

Description

When a user tries to buy an order, the buyOrder functionality is set up in such a way that it takes out 3% from the priceInUSDC amount, stores this amount as protocolFees and sends the remainder to the order seller as sellerReceives.

The presence of this logic which is not defined in the protocol documentation will make the order seller to receive less amount than what has been initially listed in the order, thereby losing a part of his funds to fees.

Risk

Likelihood:

This occurs whenever a user buys an existing sellOrder

Impact:

This affects the seller's funds

Proof of Concept

1. A user creates a `sellOrder` and includes a desired price in USDC to sell at.
2. Another user decides to buy that order by calling `buyOrder`
3. The validation checks are done and when successful, he proceeds to buy the order
4. The `buyOrder` function transfers `3%` of the `sellOrder` USDC amount as fee from the buyers wallet to the `OrderBook` smart contract
5. The `buyOrder` then deducts this fee from the `priceInUSDC`, storing it as `sellerReceives` variable and transfers `sellerReceives` from the buyer to the seller.
Place this in the TestOrderBook.t.sol Test Suite
function test_userReceivesLessThanPriceInUSDC() public {
// bob creates sell order for weth
vm.startPrank(bob);
weth.approve(address(book), 2e18);
uint256 bobId = book.createSellOrder(
address(weth),
2e18,
5_000e6,
2 days
);
vm.stopPrank();
vm.startPrank(dan);
usdc.approve(address(book), 200_000e6);
book.buyOrder(bobId); // dan buys bob weth order
assert(usdc.balanceOf(bob) < 5_000e6);
console.log(
"Bob's USDC balance after Dan buys his order: ",
usdc.balanceOf(bob)
);
}
**Recommended Mitigation:**

Recommended Mitigation

Remove the fee logic entirely. Another alternative is to set up the `createOrder` function in such a way that it adds the supposed fee to the `amountToSell` so that when a user buys that order, the buyer covers the fee charge.
function createSellOrder(
address _tokenToSell,
uint256 _amountToSell,
uint256 _priceInUSDC,
uint256 _deadlineDuration
) public returns (uint256) {
.
.
.
+ uint256 protocolFee = (order.priceInUSDC * FEE) / PRECISION;
+ uint256 finalAmountToSell = _amountToSell + protocolFee;
+ uint256 finalPriceInUSDC = _priceInUSDC + protocolFee;
IERC20(_tokenToSell).safeTransferFrom(
msg.sender,
address(this),
_amountToSell
);
- // Store the order
- orders[orderId] = Order({
- id: orderId,
- seller: msg.sender,
- tokenToSell: _tokenToSell,
- amountToSell: _amountToSell,
- priceInUSDC: _priceInUSDC,
- deadlineTimestamp: deadlineTimestamp,
- isActive: true
- });
+ // Store the order
+ orders[orderId] = Order({
+ id: orderId,
+ seller: msg.sender,
+ tokenToSell: _tokenToSell,
+ amountToSell: finalAmountToSell,
+ priceInUSDC: finalPriceInUSDC,
+ deadlineTimestamp: deadlineTimestamp,
+ isActive: true
+ });
.
.
.
}
```
Updates

Lead Judging Commences

yeahchibyke Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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