Contract Relationships
Position Data Structure
Every position is stored onchain as aPosition struct (see Types Reference for full definition):
There is no
Tenor enum. Maturities are stored as raw uint32 tenorSeconds values from the dynamic registry on Config — Config.getEnabledTenors() enumerates them.The
imLocked field is the only mutable economic field on an open position. It changes when the trader adds or removes margin. All snapshot* fields are immutable after position creation.Read Functions
getPosition
getOpenPositions
Position Queries
| Function | Returns |
|---|---|
nextPositionId() | Next position ID counter |
allOpenPositionIds() | All open position IDs in the system |
allOpenPositionIdsByPair(pairId) | All open position IDs for a specific pair |
openPositionCount() | Total count of open positions |
openPositionCountByPair(pairId) | Open positions for a specific pair |
openPositionCountAtFixingTs(pairId, fixingTimestamp) | Open positions at a (pair, fixing) bucket |
accountGrossNotional(account) | Sum of open notional for an account (used for cap checks) |
getPositionStats(pairId) | (open, matured, liquidatable) counts for one pair |
getAllPositionStats() | Same stats fanned out across every registered pair |
PnL and Risk
| Function | Returns |
|---|---|
unrealizedPnl(positionId) | Unrealized PnL for a single position |
aggregateUnrealizedPnl() | Total unrealized PnL across all positions |
positionEquity(positionId) | Position equity (allocated collateral + unrealized PnL) |
isLiquidatable(positionId) | Whether position is eligible for liquidation |
Write Functions
openPosition
| # | Check | Revert Error |
|---|---|---|
| 1 | Pair must be enabled | PairNotEnabled |
| 2 | Tenor must be enabled | TenorNotEnabled |
| 3 | notional > 0 | ZeroAmount |
| 4 | notional >= minPositionNotional (default 100 USDC) | NotionalTooSmall |
| 5 | margin >= minIM where minIM = notional * imFactorBps / 10000 | MarginBelowMinimum |
| 6 | margin <= notional | MarginExceedsNotional |
| 7 | RiskManager caps: per-position, per-account, pool exposure, rate-of-change | Various risk errors |
increasePosition
addPositionMargin
imLocked + amountmust not exceednotional- Allowed even when liquidatable (rescue mechanism)
- Allowed in NORMAL, DEGRADED, and REDUCE_ONLY modes
removePositionMargin
- Not allowed when liquidatable (reverts
PositionLiquidatable) - Remaining margin must be >=
minIM(using snapshotted IM bps) - Post-removal equity must stay above the MM threshold
- Requires a forward price read (with oracle fee)
closePosition (protocol-only)
setProtocolAuthorized — in practice this is SettlementEngine. Trader-facing close paths (early termination, settlement, liquidation) all go through SettlementEngine, which then calls back into this function.
reducePositionNotional (protocol-only)
SettlementEngine.reducePosition(...), which validates ownership and settles realized PnL on the reduced portion before invoking this.
Snapshotted Parameters
Six configuration parameters are captured at open and remain immutable:| Field | Purpose |
|---|---|
snapshotImBps | Initial margin factor — used for margin removal validation |
snapshotMmBps | Maintenance margin factor — used for liquidation threshold |
snapshotTradingFeeBps | Trading fee rate — used at settlement and close |
snapshotLiquidationPenaltyBps | Liquidation penalty — used only if liquidated |
snapshotOracleFee | Oracle fee per price read |
marginMode | Margin mode (ISOLATED in M2) |
Events
| Event | When Emitted |
|---|---|
PositionOpened | New position created |
PositionIncreased | Position notional increased |
PositionMarginAdded | Margin added to position |
PositionMarginRemoved | Margin removed from position |
PositionClosed | Position closed (any close reason) |
TradingFeeCollected | Trading fee charged at open / increase |
OracleFeeCollected | Oracle fee charged for a price read |
ProtocolAuthorizedSet | setProtocolAuthorized toggled |
Swept | Token swept by owner |
Reduction events are emitted bySettlementEngineasPositionReduced, since reductions are routed through that contract.
Admin Functions
setProtocolAuthorized / setRiskManager
setProtocolAuthorized toggles which contracts may call closePosition / reducePositionNotional (in practice, SettlementEngine). setRiskManager re-points the risk module — pass address(0) to skip cap checks (intended only for emergency unwind, never production).
sweep
Related Pages
Position Lifecycle
Product-level overview of the position lifecycle.
Settlement Engine
Settlement, liquidation, and early termination contract.
Margin Accounts
Collateral management contract.