Trion Documentation V2 · Live on Robinhood Chain
Browse documentation

Signed orders: units, domain, epochs and flags

In one paragraph. A Trion V2 order is a 14-field struct signed once with EIP-712. The signature is what authorizes the matcher to include the order in a batch and what the OrdersV2 contract re-checks on chain. Nothing about the order can be changed after signing; the only ways to stop it are expiry, on-chain cancel, or advancing an epoch. Getting units right matters because the contract checks tick, lot, price band and fee cap against the signed numbers.

The struct

Field order is the signing order and the EIP-712 type string (ORDER_TYPEHASH in overdrive/exchange/core/src/v2.ts):

Order(bytes32 marketId, bytes32 methodologyHash, address trader, bytes32 strategyId,
      uint128 limitPrice, uint64 quantity, uint64 nonce, uint64 expiry,
      uint32 accountEpoch, uint32 strategyEpoch, uint16 maxFeeBps,
      uint8 side, uint8 tif, uint8 flags)
FieldMeaningHow to fill it
marketIdkeccak256(abi.encode(symbol, methodologyHash, unitHash, multiplierWad, fixingMethodHash))Copy from the manifest (deployments/v2/<chain>.perps.json → markets.<SYM>.marketId) or compute with computeMarketId.
methodologyHashBinds the order to one price methodologyCANDIDATE_MARKETS[sym].methodologyHash (e.g. keccak256("CMPT_METHODOLOGY_V2")). The matcher re-reads the registry on admission and rejects an order whose marketId/methodologyHash differ from the registered identity, or whose market is currently disabled.
traderSigner and ownerYour address. Contract accounts are verified via EIP-1271.
strategyIdGroups orders for scoped revocation0x00…00 for a plain order; any 32-byte id for a grid/strategy.
limitPriceWAD USD per unit, multiple of perpTickCMPT tick 1e15 ($0.001), GRID 1e17 ($0.10). parsePerpPrice("2.500")2500000000000000000n.
quantityInteger lots; 1 lot = 1 contract = 1 underlying unittoLots("2", config)2n.
nonceUniqueness onlyAny unused uint64; the web uses Date.now(). Replay protection is by order hash, not by nonce ordering.
expiryUnix seconds; must be > batch timestampWeb uses 300 s for IOC, 24 h for GTC.
accountEpochMust equal OrdersV2.accountEpoch(trader) at settlementRead it before signing; mismatch reverts InvalidEpoch.
strategyEpochMust equal OrdersV2.strategyEpoch(trader, strategyId) when strategyId ≠ 00 for plain orders.
maxFeeBpsHighest fee/rebate you acceptContract rejects if config.takerFeeBps > taker.maxFeeBps (or maker rebate for makers). Local config: taker 5, maker 3.
side0 BUY, 1 SELL
tif0 GTC, 1 IOC, 2 FOK
flagsbit 0 reduce-only, bit 1 post-only; other bits reject2 = post-only; 1 = reduce-only; 3 = both.

Side, Tif, OrderFlags enums and the Order type are exported from @trion/exchange-core/v2.

Domain and helpers

import { orderTypedData, hashOrder, Side, Tif } from "@trion/exchange-core/v2";

const typed = orderTypedData(chainId, ordersV2Address, order); // domain { name: "TrionOrders", version: "2", chainId, verifyingContract }
const signature = await walletClient.signTypedData({ account, ...typed });
const digest = hashOrder(chainId, ordersV2Address, order);      // equals OrdersV2.hashOrder(order) on chain

verifyingContract is the per-market OrdersV2 address, so a CMPT signature cannot be replayed on another market, and a signature for one chain cannot be replayed on any other chain. EOAs must produce low-s signatures with v ∈ {27, 28} (OrdersV2._verifySignature).

Units and a worked example

Notional in collateral atoms is

notionalAtoms = quantityLots × lotWad × multiplierWad × priceWad × 10^collateralDecimals / 10^54

With lotWad = multiplierWad = 1e18, this collapses to quantity × price in dollars. Hypothetical: buy 2 CT of CMPT at $2.500 with six-decimal USDG → notionalAtoms = 2 × 2.5 × 1e6 = 5,000,000 atoms ($5.00). At the Template-A first tier (25 % IM) the initial margin is $1.25. calculateOrderPreview in overdrive/exchange/core/src/units.ts reproduces this before you sign.

What the contract checks

On settleBatch, OrdersV2.validateBatch (called only by the market's PerpetualV2) enforces, per order: not already terminal, expiry, tick, price band (±executionBps of I, 300 bps by default), epochs, signature, maxFeeBps, reduce-only against the current position, post-only cannot be the taker, and cumulative fill ≤ quantity. Each order hash gets an OrderState { filled, acceptedSeq, restedSeq, terminalReason, terminal } readable via orderState(bytes32).

Time-in-force and flags on and off chain

Matcher (EngineV2.submitOrder)Contract
GTCRemainder rests in the bookFills accumulate across batches until filled == quantity
IOCRemainder discarded immediatelyOrder terminalized with reason IOC_END in the batch it appears in
FOKRejected with Fault{stage:"Fill", code:"STATE"} unless fully fillableMust fill entirely in one batch
post-onlyNever matched as takerReverts if the order appears as a taker
reduce-onlyNo margin reservation; clipped to positionFill must reduce, never flip

Cancelling and revoking

Epoch advances are irreversible and cost gas; they are the trader's guaranteed exit if the matcher is unavailable or censoring.

Strategy policies (TP / SL / OCO / TWAP)

StrategyPolicy { Order childTemplate; uint8 kind; uint8 triggerDirection; uint128 triggerMark; uint64 start, end, interval, totalQty; bytes32 ocoId } is signed under TrionStrategyPolicy v2 against the market's StrategyPolicyV2. Child IOC orders derive from the parent; they do not need separate signatures. The parent's limits, fees, epochs and reduce-only flag bind every child. The web submits policies to the matcher scheduler (EngineV2.submitPolicy); execution goes through StrategyPolicyV2.executePolicyPerpetualV2.executeStrategyOrder. docs/RELEASE_V2.md REG-02 recorded a maker-replay finding in this path; whether it has since been remediated is not reconciled in that register (see Risks and security).

Source trail: overdrive/exchange/core/src/v2.ts (ORDER_EIP712_TYPES, orderTypedData, computeMarketId, notionalAtoms, CANDIDATE_MARKETS); overdrive/exchange/core/src/units.ts; overdrive/perps/src/v2/OrdersV2.sol; overdrive/exchange/web/src/pages/perp.ts (order construction).

Repository-owned documentation · September 2026 · Educational material, not investment advice and not an audit.