Assessment reports>Avantis>Threat Model>openTrade

Function: openTrade(ITradingStorage.Trade t, IExecute.OpenLimitOrderType _type, uint256 _slippageP, bytes[] priceUpdateData, uint256 _executionFee)

This opens a new market/limit trade.

Inputs

  • t

    • Control: Fully controlled by the caller.

    • Constraints: None.

    • Impact: The details of the trade to open.

  • _type

    • Control: Fully controlled by the caller.

    • Constraints: None.

    • Impact: Market or limit or stop limit type of trade.

  • _slippageP

    • Control: Fully controlled by the caller.

    • Constraints: None.

    • Impact: The slippage percentage.

  • priceUpdateData

    • Control: Fully controlled by the caller.

    • Constraints: None.

    • Impact: Pyth price update data.

  • _executionFee

    • Control: Fully controlled by the caller.

    • Constraints: None.

    • Impact: The fee for executing the trade (in USDC).

Branches and code coverage

Intended branches

  • If the order type is MARKET, store the pending market order and call the fulfill function in aggregator to fulfill the order and unregister the pending order.

  • If the order type is LIMIT, store the open limit order.

  • If TP and SL are provided, check if they are in correct range.

Negative behavior

  • Revert if the open trades count plus the pending market open count plus the open limit-orders count is greater than or equal to the max trades per pair.

  • Revert if leverage is not in the correct range.

  • Revert if the position size multiplied by leverage is less than the minimum leverage position.

Function call analysis

  • this.storageT.priceAggregator()

    • What is controllable? N/A.

    • If the return value is controllable, how is it used and how can it go wrong? Returned value is the PriceAggregator contract, to which calls will be made.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • aggregator.pairsStorage()

    • What is controllable? N/A.

    • If the return value is controllable, how is it used and how can it go wrong? Returned value is the TradingStorage contract, to which calls will be made.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • this.storageT.openTradesCount(msg.sender, t.pairIndex)

    • What is controllable? msg.sender and t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the count of open trades for the user and trading pair.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.pendingMarketOpenCount(msg.sender, t.pairIndex)

    • What is controllable? msg.sender and t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the count of pending market orders for the user and trading pair.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.openLimitOrdersCount(msg.sender, t.pairIndex)

    • What is controllable? msg.sender and t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the count of open limit orders for the user and trading pair.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.maxTradesPerPair()

    • What is controllable? N/A.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the max amount of trades per pair.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • this.storageT.pendingOrderIdsCount(msg.sender)

    • What is controllable? msg.sender.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the count of pending orders for the user.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.maxPendingMarketOrders()

    • What is controllable? N/A.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the max pending market orders.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • PositionMath.mul(t.positionSizeUSDC, t.leverage)

    • What is controllable? t.positionSizeUSDC and t.leverage.

    • If the return value is controllable, how is it used and how can it go wrong? Calculates the position size based on leverage.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • pairsStored.pairMinLevPosUSDC(t.pairIndex)

    • What is controllable? t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Retrieves the minimum leverage position USDC for the trading pair.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • pairsStored.pairMinLeverage(t.pairIndex)

    • What is controllable? t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Retrieves the minimum leverage for the trading pair.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • pairsStored.pairMaxLeverage(t.pairIndex)

    • What is controllable? t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Retrieves the maximum leverage for the trading pair.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.transferUSDC(msg.sender, address(this.storageT), t.positionSizeUSDC + _executionFee)

    • What is controllable? msg.sender, t.positionSizeUSDC, and _executionFee.

    • If the return value is controllable, how is it used and how can it go wrong? Transfers USDC from the caller to the storage contract.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.firstEmptyOpenLimitIndex(msg.sender, t.pairIndex)

    • What is controllable? msg.sender and t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Finds the first empty open limit index for the user and trading pair.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.storeOpenLimitOrder(OpenLimitOrder(msg.sender, t.pairIndex, index, t.positionSizeUSDC, t.buy, t.leverage, t.tp, t.sl, t.openPrice, t.openPrice, block.number, _executionFee))

    • What is controllable? msg.sender, t.pairIndex, index, t.positionSizeUSDC, t.buy, t.leverage, t.tp, t.sl, t.openPrice, block.number, and _executionFee.

    • If the return value is controllable, how is it used and how can it go wrong? Stores an open limit order — no return value.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • aggregator.executions().setOpenLimitOrderType(msg.sender, t.pairIndex, index, _type)

    • What is controllable? msg.sender, t.pairIndex, index, and _type.

    • If the return value is controllable, how is it used and how can it go wrong? Sets the open limit order type — no return value.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • aggregator.getPrice(t.pairIndex, OrderType.MARKET_OPEN)

    • What is controllable? t.pairIndex.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the orderId of the current order.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

  • this.storageT.storePendingMarketOrder(PendingMarketOrder(Trade(msg.sender, t.pairIndex, 0, 0, t.positionSizeUSDC, 0, t.buy, t.leverage, t.tp, t.sl, 0), 0, t.openPrice, _slippageP), orderId, True)

    • What is controllable? msg.sender, t.pairIndex, t.positionSizeUSDC, t.buy, t.leverage, t.tp, t.sl, t.openPrice, and _slippageP.

    • If the return value is controllable, how is it used and how can it go wrong? Stores the pending market order — no return value.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • aggregator.fulfill{value: msg.value}

    • What is controllable? msg.value.

    • If the return value is controllable, how is it used and how can it go wrong? Fulfills the update margin order — no return value.

    • What happens if it reverts, reenters or does other unusual control flow? If it reverts, the entire call will revert — no reentrancy scenarios.

Zellic © 2025Back to top ↑