DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: low
Invalid

Missing StreamLookup Error Handler in `MarketOrderKeeper` Contract.

Summary

The MarketOrderKeeper contract lacks an error handler for situations when the upkeep cannot fetch the report.

Vulnerability Details

When a user places an order, the OrderBranch::createMarketOrder(...) function is called, emitting a LogCreateMarketOrder event:

/// @notice Emitted when a market order is created.
/// @param sender The account that created the market order.
/// @param tradingAccountId The trading account id.
/// @param marketId The perp market id.
/// @param marketOrder The market order data.
event LogCreateMarketOrder(
address indexed sender,
uint128 indexed tradingAccountId,
uint128 indexed marketId,
MarketOrder.Data marketOrder
);

The protocol sets up a Chainlink automation upkeep for this event to ensure order fulfillment by a keeper. When this event is emitted, a Chainlink Keeper runs the MarketOrderKeeper::checkLog(...) function, which includes a StreamsLookup revert custom error. The StreamsLookup revert enables upkeep to fetch a report from Data Streams which includes the token price info. If reports are fetched successfully, the MarketOrderKeeper::checkCallback(...). function is evaluated offchain.

However, if the reports cannot be fetched, the upkeep will look for a checkErrorHandler(...) function to determine the next steps. Currently this function is missing from the MarketOrderKeeper.

Without checkErrorHandler(...), the upkeep will not be executed (read here), leaving the keeper unable to proceed if there is an error in fetching the price report. Since order fulfillment depends on the price report, an unfetched report results in unfulfilled market orders, leaving them idle.

Users will have to close the previous order and create a new one, which will incur more gas.

Various issues can cause a report to be unfetched, such as no valid report received for 10 seconds or incorrect feed ID. (Read more here).

Impact

The order will not be fulfilled, as the only way to fulfill an order is by calling SettlementBranch::fillMarketOrder(...), which is only callable by the market order keeper.

Tools Used

  • Manual Review

Recommendations

To handle errors in fetching the price report gracefully, consider the following:

  1. Implement a checkErrorHandler(...) function in the MarketOrderKeeper contract. Create a separate state for pending market orders so that if checkErrorHandler(...) is triggered, the order is stored in this pending state. Users can retry the order from the last state by emitting the same event again.

  2. Implement a checkErrorHandler(...) function in the MarketOrderKeeper contract. In case of an error, automatically cancel the market order for the user and notify them via the frontend that the order couldn't be fulfilled.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

checkErrorHandler not used

Support

FAQs

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

Give us feedback!