DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: high
Valid

Incorrect `fill price` Validation Logic for Buy and Sell Orders in `fillOffchainOrders()`

Summary

The fill price validation logic for buy and sell orders is incorrectly implemented, potentially allowing trades to execute at unfavorable prices.

Vulnerability Details

In fillOffchainOrders(), the fill price is validated as follows:

// if the order increases the trading account's position (buy order), the fill price must be less than or
// equal to the target price, if it decreases the trading account's position (sell order), the fill price
// must be greater than or equal to the target price.

However, this is implemented as follows:

ctx.isFillPriceValid = (ctx.isBuyOrder && ctx.offchainOrder.targetPrice <= ctx.fillPriceX18.intoUint256())
|| (!ctx.isBuyOrder && ctx.offchainOrder.targetPrice >= ctx.fillPriceX18.intoUint256());

Logical Error:

  1. Buy Order: The fill price should be less than or equal to the target price.

  2. Sell Order: The fill price should be greater than or equal to the target price.

But as seen, the current does not correctly enforce these conditions.

Example Scenario
Buy Order

  • Target Price: $100

  • Fill Price: $105

Incorrect Validation: The current logic will incorrectly validate this fill price as acceptable when such a trade should be rejected.

Impact

Traders may have their orders executed at unfavorable prices, leading to potential financial losses.

Tools Used

Manual Review

Recommendations

To ensure the correct validation of the fill price, the logic should correctly handle the conditions for both buy and sell orders.

- ctx.isFillPriceValid = (ctx.isBuyOrder && ctx.offchainOrder.targetPrice <= ctx.fillPriceX18.intoUint256())
- || (!ctx.isBuyOrder && ctx.offchainOrder.targetPrice >= ctx.fillPriceX18.intoUint256());
+ if (ctx.isBuyOrder) {
+ // Buy order: fill price must be less than or equal to the target price
+ ctx.isFillPriceValid = ctx.fillPriceX18.intoUint256() <= ctx.offchainOrder.targetPrice;
+ } else {
+ // Sell order: fill price must be greater than or equal to the target price
+ ctx.isFillPriceValid = ctx.fillPriceX18.intoUint256() >= ctx.offchainOrder.targetPrice;
+ }
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

fillOffchainOrders inverses the comparison between `fillPrice` and `targetPrice`

Support

FAQs

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