Assessment reports>Tradoor>Threat Model>Message: ExecutePerpOrder

Message: ExecutePerpOrder

This operation allows one of the trusted executors to execute a previously requested perpetual order. Orders can only be executed if they involve a registered and enabled asset.

The message must carry enough TON to cover for the executePerpOrderGas and transferJettonGas amounts configured in the contract.

The price for the asset is provided in the message. This price is not verified and is fully controlled by the executor. Limit orders are checked to ensure the price provided in the message satisfies the trigger condition.

Additionally, orders increasing the position size could have specified optional take-profit and/or stop-loss conditions; these conditions are turned into orders, which are inserted in the book at this moment.

The user long or short position size and margin are adjusted to increase or decrease them according to the order type and parameters. If the order is for decreasing a position, the size and margin changes are limited so that the position size and margin do not become negative (accounting for fees in the case of the margin).

The global net position is also adjusted accordingly; the global net position represents the imbalance between long and short positions taken by the traders, and it is in effect the net exposure taken collectively by the liquidity providers, which is not compensated between the perpetual traders. The global position of the same type of the order (long or short) is first reduced. If the order is bigger than the current global net position, the global net position takes the remaining size, with inversed side.

The following fees are applied:

  • Trading fees are computed as a percentage of the position size increase or decrease, configured per token (tokenConfig.tradingFeeRate). A per-token configurable percentage of the trading fees (tokenConfig.lpTradingFeeRate) is passed to the LPs, while the rest is credited to the protocol. The protocol also receives a configurable percentage (normalPositionShareRate) of the PNL change realized by the LPs, only if the PNL is positive.

  • Funding fees are always added to the position margin, crediting the user. The funding fee is computed as .

  • Rollover fees are always taken from the position margin, charging the user. The fee is computed as .

We note that the executor fully controls the and parameters and can therefore decide the fee values, even turning them negative. The fee mechanisms are opaque and controlled by the executors; we did not receive details on how these values are computed off chain nor design notes detailing the rationale behind the fees.

Orders to increase a position size and orders to decrease a position, leaving it nonempty, are subject to margin and leverage checks, ensuring the user position does not cross the risk thresholds configured for the asset. If the health checks fail, the order cannot be executed and the state changes are reverted.

Orders to decrease a position also trigger a payout of the requested margin decrease.

Finally, an event signals the order execution is emitted, the order is deleted from storage, execution fees are sent to the receiver (optionally specified in the message, defaulting to the message sender), and the excess TON attached with the message is refunded to the sender.

Inputs

The incoming message has the following structure:

message ExecutePerpOrder { executionFeeReceiver: Address?; orderId: Int as uint64; trxId: Int as uint64; tokenId: Int as uint16; price: Int as uint128; premiumRate: Int as int32; fundingFeeGrowth: Int as int128; rolloverFeeGrowth: Int as int128; }
  • executionFeeReceiver

    • Validation: None.

    • Impact: Optional address that will receive the execution fees.

  • orderId

    • Validation: Must be an existing, nonpending order.

    • Impact: Identifies the order to be executed.

  • trxId

    • Validation: None required.

    • Impact: Does not affect the core contract logic.

  • tokenId

    • Validation: None.

    • Impact: Not used and not necessary — the token ID is taken from the order stored in the contract.

  • price

    • Validation: None.

    • Impact: Price of the asset of the order, used to compute position values, PNLs, and fees.

  • premiumRate

    • Validation: None.

    • Impact: Not used.

  • fundingFeeGrowth

    • Validation: None.

    • Impact: Used to compute the funding fees.

  • rolloverFeeGrowth

    • Validation: None.

    • Impact: Used to compute rollover fees.

Test coverage

Intended branches

Negative behavior

Zellic © 2025Back to top ↑