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

SEV 9: Protocol does not account for changes in-between creating a market order and filling the order

Severity: Medium

Summary

Market orders are filled in two steps: trader creates an order and then keeper fills the order. The protocol peforms validations on the account when the order was created which may no longer hold by the time a keeper fills the order leading to a Time-Of-Check, Time-Of-Use (TOC, TOU) issue.

Vulnerability Details

Execution of market orders happens in two steps

  1. Trader creates a market order using the OrderBranch::createMarketOrder function

  2. Market keeper calls SettlementBranch::fillMarketOrder to fill the created order.

Three of the validations performed at the time of creation which might not hold:

  1. The account active positions <= protocol limit

  2. The account is not liquidatable

  3. Account owner that created the market order is the owner when the order is filled

These invariants can change in-between step 1 and step 2:

  1. Trader has positions in 4 markets and protocol limit is 5.

    • createMarketOrder allows for creating the position in 5th market.

    • Trader also creates an offchain order for a new market.

    • Trader creats a market order in 5th market.

    • The positions limit check will succeed as trader still has only 4 active positions.

    • The offchain order is filled before the market order.

    • The active positions become 5.

    • After the market order is filled it becomes 6.

  2. The positions of the account might make losses because of price movements. The account might become liquidatable.

    • If the market order decreases the position size and the collateral balance satisfies margin requirements after the losses then the trade will succeed.

    • Protocol allowed for a trade of liquidatable account.

  3. The owner of the trading account sells an account on an off-chain market. Before the NFT transfer transaction is included in the chain, the malicious owner creates a bad market order between the off-chian transaction and NFT transfer transaction. The market order is filled resulting in losses for the new owner.

Positions limit check in the createMarketOrder function: OrderBranch.sol#L285-L291

Liquidatable accounts check in the simulateTrade function:
OrderBranch.sol#L129-L136

The TradingAccountBranch::notifyOwner function does not clear the market order created by previous owner: TradingAccountBranch.sol#L405-L410

Definition of fillMarketOrder function: SettlementBranch.sol#L107-L114

Impact

  • Traders can open position in 1 market more than the protocol limit

  • Market order of a liquidatable account might be filled.

  • The new owner might make losses after the transfer of the trading account NFT.

Tools Used

Manual Review

Recommendations

  • Perform the validations at the time of filling the order in the SettlementBranch::_fillOrder function for the first two invariants.

  • Update the notifyAccountTransfer function to clear any pending market order.

Updates

Lead Judging Commences

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

`maxPositionsPerAccount` may be exceeded by combining onchain and offchain orders

When a user creates an order and then transfers the account NFT, pending orders should clear

Support

FAQs

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

Give us feedback!