Skip to main content
PositionManager handles the full position lifecycle: open, increase, reduce, and margin adjustments. It is the primary entry point for traders interacting with the protocol.

Contract Relationships

Position Data Structure

Every position is stored onchain as a Position struct (see Types Reference for full definition):
struct Position {
    address account;                     // Owner address
    bytes32 pairId;                      // Currency pair identifier (e.g., keccak256("EUR/USD"))
    Side side;                           // LONG or SHORT
    uint256 notional;                    // Position size in USDC (6 decimals)
    uint32 tenorSeconds;                 // Tenor duration in seconds (dynamic registry)
    uint64 openTimestamp;                // Block timestamp when opened
    uint64 fixingTimestamp;              // Maturity date (business day adjusted)
    int256 entryStrike;                  // Forward price at open (18 decimals)
    uint64 entryOracleRoundId;           // Oracle round ID at open
    uint256 imLocked;                    // Locked initial margin (mutable via add/remove)
    uint256 mmThreshold;                 // Maintenance margin liquidation threshold
    PositionStatus status;               // OPEN or CLOSED
    CloseReason closeReason;             // Why it was closed (NONE while open)
    uint64 closeTimestamp;               // When closed (0 while open)
    int256 closePrice;                   // Settlement price at close (18 decimals)
    int256 realizedPnl;                  // Capped PnL used for accounting
    int256 marketPnl;                    // Uncapped true mathematical PnL
    uint16 snapshotImBps;                // IM factor at time of open
    uint16 snapshotMmBps;                // MM factor at time of open
    uint16 snapshotTradingFeeBps;        // Trading fee rate at time of open
    uint16 snapshotLiquidationPenaltyBps; // Liquidation penalty at time of open
    uint256 snapshotOracleFee;           // Oracle fee at time of open
    MarginMode marginMode;               // ISOLATED (M2 only)
}
There is no Tenor enum. Maturities are stored as raw uint32 tenorSeconds values from the dynamic registry on ConfigConfig.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

function getPosition(uint256 positionId) external view returns (Position memory)
Returns the full Position struct for a given ID.

getOpenPositions

function getOpenPositions(address account) external view returns (uint256[] memory)
Returns all open position IDs for an account.

Position Queries

FunctionReturns
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

FunctionReturns
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

function openPosition(OpenPositionParams params) returns (uint256 positionId)
Opens a new position. Only allowed in NORMAL mode. Validation checks (in order):
#CheckRevert Error
1Pair must be enabledPairNotEnabled
2Tenor must be enabledTenorNotEnabled
3notional > 0ZeroAmount
4notional >= minPositionNotional (default 100 USDC)NotionalTooSmall
5margin >= minIM where minIM = notional * imFactorBps / 10000MarginBelowMinimum
6margin <= notionalMarginExceedsNotional
7RiskManager caps: per-position, per-account, pool exposure, rate-of-changeVarious risk errors

increasePosition

function increasePosition(uint256 positionId, uint256 additionalNotional)
Increases an existing position’s notional. Only allowed in NORMAL mode. Preconditions: Owner only, OPEN status, not matured, not liquidatable. The increase uses a weighted average entry strike:
newEntryStrike = (oldNotional * oldStrike + additionalNotional * currentForwardPrice) / newNotional
Additional margin is calculated proportionally:
additionalMargin = additionalNotional * (imLocked / notional)

addPositionMargin

function addPositionMargin(uint256 positionId, uint256 amount)
Increases locked margin. Owner only, position must be OPEN and not matured.
  • imLocked + amount must not exceed notional
  • Allowed even when liquidatable (rescue mechanism)
  • Allowed in NORMAL, DEGRADED, and REDUCE_ONLY modes

removePositionMargin

function removePositionMargin(uint256 positionId, uint256 amount)
Decreases locked margin. Owner only, position must be OPEN and not matured.
  • 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)

function closePosition(
    uint256 positionId,
    CloseReason reason,
    int256 closePrice,
    int256 realizedPnl,
    int256 marketPnl
) external
Finalizes a position with a close price and computed PnL. Restricted to addresses authorized via 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)

function reducePositionNotional(uint256 positionId, uint256 reductionNotional) external
Reduces an open position’s notional. Restricted to protocol-authorized callers (SettlementEngine). The trader-facing entry point is 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:
FieldPurpose
snapshotImBpsInitial margin factor — used for margin removal validation
snapshotMmBpsMaintenance margin factor — used for liquidation threshold
snapshotTradingFeeBpsTrading fee rate — used at settlement and close
snapshotLiquidationPenaltyBpsLiquidation penalty — used only if liquidated
snapshotOracleFeeOracle fee per price read
marginModeMargin mode (ISOLATED in M2)

Events

EventWhen Emitted
PositionOpenedNew position created
PositionIncreasedPosition notional increased
PositionMarginAddedMargin added to position
PositionMarginRemovedMargin removed from position
PositionClosedPosition closed (any close reason)
TradingFeeCollectedTrading fee charged at open / increase
OracleFeeCollectedOracle fee charged for a price read
ProtocolAuthorizedSetsetProtocolAuthorized toggled
SweptToken swept by owner
Reduction events are emitted by SettlementEngine as PositionReduced, since reductions are routed through that contract.

Admin Functions

setProtocolAuthorized / setRiskManager

function setProtocolAuthorized(address account, bool authorized) external
function setRiskManager(address _riskManager) external
Owner-only. 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

function sweep(address token, address recipient, uint256 amount) external
Owner-only. Sweeps an arbitrary ERC-20 balance held by the contract.

Position Lifecycle

Product-level overview of the position lifecycle.

Settlement Engine

Settlement, liquidation, and early termination contract.

Margin Accounts

Collateral management contract.