Skip to content

Latest commit

 

History

History
136 lines (77 loc) · 5.28 KB

File metadata and controls

136 lines (77 loc) · 5.28 KB

Known Limitations

This document catalogs all known limitations, simplifications, and potential divergences between the Flash Risk Engine and the production Flash Trade program.


Closed-Source Production Program

The Flash Trade core program is maintained in a private repository (perpetuals-closed.git). The production on-chain program may contain logic not present in the publicly available reference implementation (flash-perpetuals) or SDK (flash-sdk-rust).

All formulas in this engine are derived from:

  1. The open-source reference implementation
  2. The Rust SDK reader functions
  3. The TypeScript SDK IDL and state structures

There is no guarantee that the production program implements these formulas identically.


Specific Divergences

1. Degen Mode

Impact: Medium

Production uses the degen_size_usd field on position accounts to select between two leverage thresholds:

  • custody.pricing.maxLeverage -- Standard threshold
  • custody.pricing.maxDegenLeverage -- Higher threshold for degen positions

This engine always uses maxLeverage. Consequences:

  • Some degen positions may appear liquidatable in this engine when they are not (false positives)
  • Some non-degen positions near the maxDegenLeverage threshold may appear safe when they are actually liquidatable under the standard threshold (false negatives -- though this is unlikely given the threshold ordering)

2. Price Impact USD

Impact: Low to Medium

The price_impact_usd field exists on position accounts and has a corresponding price_impact_set flag. Production may adjust entry prices based on market impact at position open time.

This engine uses the stored entryPrice as-is. If production adjusts PnL calculations using price_impact_usd, the PnL and derived values (margin, leverage, liquidation price) computed by this engine will differ slightly.

3. Unsettled Values

Impact: Unknown

Two fields on position accounts are not used by this engine:

  • unsettled_value_usd -- May represent unrealized value adjustments
  • unsettled_fees_usd -- May represent unpaid fee obligations

If production includes these in margin calculations, this engine's margin and leverage values will differ by the unsettled amounts.

4. Oracle Integration

Impact: Low

Production may integrate Lazer oracle feeds (the lazerFeedId and lazerPrice fields exist on CustomOracle accounts) and depeg adjustments. This engine uses only the primary Custom Oracle price, EMA, and confidence values.

5. Close Fee Computation

Impact: Low

This engine computes close fees as:

close_fee_usd = size_usd * close_position_fee / RATE_POWER

Production may compute them as:

close_fee = exit_fee_amount * token_ema_price

The difference depends on whether EMA price diverges from the spot-based exit price used to compute size_usd.


Timing Limitations

Borrow Rate Staleness

The on-chain borrow rate state (currentRate, cumulativeLockFee, lastUpdate) is updated only when a transaction touches the custody account. Between transactions, the stored rate becomes stale.

This engine extrapolates the cumulative lock fee from the last update time to the current wall-clock time, matching the SDK approach. However, during periods of rapid utilization changes (many transactions), the stored rate may have been updated multiple times since lastUpdate, and this engine cannot observe the intermediate states.

Oracle Staleness

Oracle prices are checked against maxPriceAgeSec from the custody's oracle parameters. The isStale flag is set but does not cause the engine to reject the price. Stale prices are used as-is, which matches how the reference implementation behaves (staleness rejection is handled at the instruction level, not in the reader).


Precision Limitations

Profit Cap

Profit is capped at locked_value_usd, which is computed from the position's locked_amount in collateral token units multiplied by the collateral oracle's midpoint price. Production may use a different pricing method for the locked value.

Integer Truncation

All BN divisions truncate toward zero (floor division for positive values). The Rust program uses the same truncation behavior. However, the exact point of truncation may differ if the production program combines or reorders operations differently.

Liquidation Price Estimate

The liquidation price uses static estimates for interest and close fee at the time of computation. If significant time passes or the borrow rate changes, the actual liquidation price will drift from this estimate. This is inherent to any snapshot-based liquidation price calculation.


Scope Limitations

No Prediction

This engine computes the current risk state. It does not:

  • Predict future price movements
  • Forecast liquidation cascades
  • Estimate time-to-liquidation under assumed volatility
  • Model funding rate dynamics

No Transaction Execution

This engine is read-only. It does not:

  • Submit liquidation transactions
  • Manage positions
  • Interact with the program as a signer

No Historical Analysis

This engine operates on the current on-chain state. It does not:

  • Query historical account states
  • Reconstruct past risk metrics
  • Track risk metric changes over time (except via the --subscribe live mode, which monitors real-time changes)