Skip to main content
Exposure caps protect LPs by limiting how much directional risk the pool can take on. If the pool’s net exposure reaches the cap, new positions in that direction are blocked until existing positions close or the pool grows. These limits ensure the pool can absorb losses even in a worst-case market move, keeping LP capital safe. The liquidity pool serves as the counterparty to all trader positions. Without exposure limits, a sufficiently large or skewed set of positions could threaten pool solvency. The protocol enforces a stress-adjusted net exposure cap that scales dynamically with pool equity, ensuring the pool can absorb losses even under adverse market conditions.
All exposure cap parameters are managed by the RISK_ADMIN_ROLE and take effect immediately upon update. Changes affect new position validation but do not retroactively close existing positions that exceed updated caps.

Net Exposure Cap

The maximum net exposure the pool can take on is calculated using a stress-adjusted formula:
maxNetExposure = (poolEquity * netExposureCapFactorBps) / stressMoveBps
ParameterDefaultDescription
netExposureCapFactorBps10,000 (100%)Pool equity fraction available for exposure
stressMoveBps200 (2%)Hypothetical adverse price move for stress testing
Why stress-adjusted? The stressMoveBps parameter represents a hypothetical worst-case price move. By dividing by this value, the formula ensures that even if the market moves by the stress amount, the pool’s total loss would not exceed the fraction of equity allocated for exposure. This is a fundamental risk management technique borrowed from traditional finance stress testing.

Worked Example

With a pool equity of 10,000,000 USDC (10M):
maxNetExposure = (10,000,000 * 10,000) / 200
               = 500,000,000 USDC (500M)
This means the pool can support up to 500M USDC of net directional exposure. If the market moves 2% against the pool’s net position, the maximum loss would be:
maxStressLoss = 500M * 2% = 10M USDC = poolEquity
The stress scenario is calibrated so the pool’s entire equity serves as the loss buffer.

Exposure Tracking

The protocol tracks two distinct exposure metrics in real time, both per-pair and in aggregate:

Net Exposure

netExposure (int256 — signed)Represents the pool’s directional bias. Updated on every position open, close, increase, and reduce:
  • LONG position opened: netExposure -= notional (pool takes the short side)
  • SHORT position opened: netExposure += notional (pool takes the long side)
Closing a position reverses the effect.

Gross Notional

grossNotional (uint256 — unsigned)Sum of all open position notionals regardless of direction. Increases when positions are opened, decreases when positions are closed or reduced. Used for utilization calculations and rate-of-change limits.
Net exposure can be positive or negative. A positive value means the pool is net long (more SHORT trader positions); a negative value means the pool is net short (more LONG trader positions). The cap applies to the absolute value: |netExposure| <= maxNetExposure.

Pool Utilization

Utilization measures how much of the pool’s assets are backing open positions:
notionalUtilization = grossNotional * BPS_DENOMINATOR / totalAssets

Withdrawal Restriction

LP withdrawals are restricted when utilization is high. The maxUtilizationBps parameter (default: 8,000 = 80%) caps how much of the pool’s assets can be committed to open positions after a withdrawal:
maxWithdrawable = totalAssets - (grossNotional * BPS_DENOMINATOR / maxUtilizationBps)
If current utilization already exceeds maxUtilizationBps, LP withdrawals are blocked entirely until positions close and utilization drops. This protects traders by ensuring the pool retains sufficient liquidity to cover potential payouts on open positions.
The 80% default ensures a 20% liquidity buffer remains in the pool at all times. This buffer serves two purposes:
  1. Payout capacity: If all open positions move in the traders’ favor simultaneously, the pool needs unencumbered assets to pay out profits.
  2. Operational headroom: The buffer absorbs fee payments, bad debt events, and oracle-fee costs without immediately blocking withdrawals.
The parameter can be adjusted by the contract owner. Setting it to 0 disables the utilization check entirely.

Rate-of-Change Limits

Beyond absolute caps, the protocol can enforce rolling window limits on how quickly exposure changes. This prevents sudden spikes in exposure that could indicate manipulation or a coordinated attack.
Limits the total notional added within a rolling window:
windowGrossAdded + notional <= maxGrossNotionalDeltaPerWindow
Prevents a burst of position openings from overwhelming the pool in a short time frame.

Window Configuration

ParameterDefaultDescription
rateWindowSeconds3,600 (1 hour)Rolling window duration
maxGrossNotionalDeltaPerWindow0 (disabled)Max gross notional added per window
maxNetExposureDeltaPerWindow0 (disabled)Max net exposure change per window
In the current M2 deployment, both rate-of-change limits are set to 0, which disables them. They are available as defense mechanisms that the risk admin can activate if unusual trading patterns are detected. When enabled, exceeding either limit reverts with RateOfChangeExceeded.
Windows reset automatically. When block.timestamp exceeds windowStartTime + rateWindowSeconds, the counters reset and a new window begins.

Pool Equity Floor

In extreme scenarios where cumulative bad debt from liquidated positions exceeds pool equity, the pool equity is clamped to zero:
poolEquity = max(0, totalAssets - totalLiabilities)
Pool equity cannot go negative. If bad debt erodes the pool completely, the equity floors at zero. In this state:
  • maxNetExposure computes to 0, blocking all new positions
  • LP share value effectively reaches zero
  • Existing positions can still be settled and closed
  • The pool can recover if new deposits are made
This is a last-resort safety mechanism. The combination of margin requirements, exposure caps, and liquidation is designed to prevent this scenario.

Dynamic Scaling

All caps scale dynamically with pool equity, which creates a self-regulating system:
1

Pool Grows

As LPs deposit more USDC, poolEquity increases. This raises maxNetExposure, which in turn raises position and account caps. The protocol can support more trading activity.
2

Pool Shrinks

When the pool pays out trader profits or absorbs bad debt, poolEquity decreases. Caps tighten automatically. New positions must be smaller, and the pool becomes more conservative.
3

Equilibrium

The system naturally finds an equilibrium where trading activity is proportional to available liquidity. Profitable pools attract more LP deposits, enabling more trading. Unprofitable pools contract, reducing risk.

Exposure Events

The protocol emits events whenever exposure changes, enabling off-chain monitoring and alerting:
EventFieldsIndexed
ExposureUpdatednetExposure, grossNotional
PairExposureUpdatedpairId, netExposure, grossNotionalpairId
These events are indexed by the subgraph and available for querying via the PoolState and DailyStats entities. Monitor the netExposure field to track the pool’s directional bias over time.