Precision Constants
BPS_DENOMINATOR
10,000Basis point calculations. 1 bps = 0.01%. Used for margin factors, fee rates, exposure caps, and all percentage-based parameters.
PRICE_PRECISION
1e18Internal price representation. All prices use 18 decimal fixed-point arithmetic. EUR/USD 1.08 is stored as
1,080,000,000,000,000,000.USDC_PRECISION
1e6Collateral token precision. Matches the USDC standard of 6 decimals. 1 USDC =
1,000,000 raw units. All notional and margin values are denominated in raw USDC units.BPS_DENOMINATOR (10,000)
Basis points are the standard unit for all percentage-based parameters in the protocol. Using an integer denominator of 10,000 avoids floating-point math entirely.| Parameter | Typical Value (bps) | Percentage |
|---|---|---|
| Initial Margin (IM) | 200 | 2.0% |
| Maintenance Margin (MM) | 100 | 1.0% |
| Trading Fee | 5 | 0.05% |
| Liquidation Penalty | 30 | 0.3% |
| Max Utilization | 8,000 | 80.0% |
| Fee Split (Pool) | 7,000 | 70.0% |
| Fee Split (Treasury) | 3,000 | 30.0% |
PRICE_PRECISION (1e18)
All prices in the protocol are represented as 18-decimal fixed-point integers. This matches the common EVM convention (same precision asether in wei).
Why 18 decimals? FX rates like EUR/USD typically move in the 4th-5th decimal place (pips). Using 18 decimals provides more than enough precision for accurate PnL calculations without rounding errors accumulating over multiple operations.
| Real Value | Onchain Representation |
|---|---|
| EUR/USD = 1.08000 | 1,080,000,000,000,000,000 |
| EUR/USD = 1.08550 | 1,085,500,000,000,000,000 |
| EUR/USD = 0.99123 | 991,230,000,000,000,000 |
Pyth oracle prices use a different exponent (typically -5 for FX pairs). The OracleModule converts Pyth prices to 18-decimal precision before storing them onchain.
USDC_PRECISION (1e6)
All monetary values — notional amounts, margin deposits, PnL, fees — are denominated in raw USDC units with 6 decimals of precision.| Real Value | Onchain Representation |
|---|---|
| 1 USDC | 1,000,000 |
| 1,000 USDC | 1,000,000,000 |
| 0.50 USDC | 500,000 |
| 10,000 USDC | 10,000,000,000 |
Conversion Examples
Initial Margin Calculation
For a 1,000 USDC notional position with 200 bps (2%) initial margin:PnL Calculation
PnL is computed from the price difference scaled by notional:Trading Fee Calculation
For a 1,000 USDC notional with 5 bps (0.05%) trading fee:Maintenance Margin Threshold
The MM threshold determines when a position becomes liquidatable:Enum Reference
All enums are defined in theTypes library (see Types Reference) and mirrored in both the TypeScript SDK (@nile-markets/sdk) and the Rust SDK (fx-contracts).
| Enum | Values | Description |
|---|---|---|
| Side | LONG (0), SHORT (1) | Trade direction. LONG profits when EUR/USD rises. |
| Tenor | ONE_DAY (0), ONE_WEEK (1), ONE_MONTH (2), TEST_60S (3) | Forward contract duration. TEST_60S is dev/local only. |
| PositionStatus | OPEN (0), CLOSED (1) | One-way transition: OPEN to CLOSED only. |
| CloseReason | NONE (0), MATURED (1), LIQUIDATED (2), EARLY_TERMINATION (3) | Why a position was closed. NONE for open positions. |
| Mode | NORMAL (0), DEGRADED (1), REDUCE_ONLY (2), PAUSED (3) | Protocol operating mode. Severity increases with ordinal. |
| MarginMode | ISOLATED (0), CROSS (1) | Margin model. M2 uses ISOLATED only. |
Tenor Durations
| Tenor | Duration | Seconds | M2 Status |
|---|---|---|---|
| ONE_DAY | 24 hours | 86,400 | Enabled |
| ONE_WEEK | 7 days | 604,800 | Enabled |
| ONE_MONTH | 30 days | 2,592,000 | Enabled |
| TEST_60S | 60 seconds | 60 | Dev/local only |
Mode Transitions
| Mode | Open | Increase | Close/Reduce | Settle | Liquidate |
|---|---|---|---|---|---|
| NORMAL | Yes | Yes | Yes | Yes | Yes |
| DEGRADED | Yes | Yes | Yes | Yes | Yes |
| REDUCE_ONLY | No | No | Yes | Yes | Yes |
| PAUSED | No | No | No | No | No |
Rounding Behavior
All integer math in the protocol uses Solidity’s default truncation (round toward zero). There is no explicit rounding mode applied. Key rounding implications:- Margin calculations:
notional * factorBps / BPS_DENOMINATORtruncates, meaning the actual margin required may be slightly less than the theoretical percentage. This is negligible for practical position sizes. - PnL calculations:
notional * priceDiff / PRICE_PRECISIONtruncates. For small positions, this can result in rounding to zero. - Fee calculations: Fees truncate toward zero, slightly favoring the trader over the protocol.
- ERC-4626 vault: The
redeemfunction rounds down shares-to-assets per the ERC-4626 standard. LPs may receive up to 1 wei less than the theoretical value.