🚧 SportsPerp is currently live on devnet. Mainnet target: before Jun 12, 2026 (World Cup kickoff).
TradingInsurance Fund

Insurance Fund

The insurance fund is a single, global USDC pool that absorbs underwater positions at Layer 2 of the liquidation cascade, preventing routine liquidations from requiring ADL.

Current state

Balance20,000 USDC
Target balance10,000 USDC
Max backstop exposure50,000 USDC
Current backstop exposurevaries — live on-chain
Replenishment50% of each Layer 1 partial liquidation’s net proceeds
Account seed["insurance"] (single global PDA)

The insurance PDA stores four balance-related fields (state/insurance.rs):

  • total_balance — current USDC in the insurance token account.
  • max_backstop_exposure — ceiling on total absorbed position notional outstanding. Prevents the fund from taking on more counterparty risk than it can wind down.
  • current_backstop_exposure — actively absorbed positions not yet fully unwound.
  • target_balance — the “healthy” threshold — admin withdrawal is only permitted above this.

How it fills

Two inflow channels:

  1. Liquidation allocations. Every Layer 1 partial liquidation sends 50% of the closed slice’s net collateral (after the 5% liquidator reward) to the insurance fund. In normal operation this is the dominant source — the fund self-replenishes proportionally to liquidation activity.
  2. Admin deposits. The deposit_insurance instruction lets the protocol admin top up the fund from an external USDC source. Used at initial capitalization and for emergency funding.

How it drains

Three outflow channels:

  1. Backstop absorption. When backstop_liquidate is called on a position with margin ≤ 13.33%, the insurance fund takes ownership of the position at mark price. The fund’s balance doesn’t decrease at the absorption moment — only its current_backstop_exposure rises.
  2. Backstop unwind losses. As unwind_backstop calls close 10% chunks of the absorbed position against the live mark price, the fund realizes PnL. If the unwind closes at a worse price than absorption, the fund’s balance decreases.
  3. Admin withdrawals. The withdraw_insurance instruction allows admin to pull funds above the target_balance. A withdrawal attempt that would leave the balance below target is rejected by the program — not just advisory. See insurance_admin.rs.

The withdrawal floor is the key anti-raid guarantee: admin cannot drain the fund below its target, regardless of wallet permissions.

Why 20K / 10K / 50K

The three parameters are tuned for the expected Layer 2 flow at devnet scale:

  • 20K current balance — enough to absorb ~2× the 10K target without hitting max_backstop_exposure on a single event. Comparable in scale to the realistic per-market effective_oi envelope on mainnet launch.
  • 10K target — a “healthy” floor that admin deposits try to maintain. Below this, admin withdrawals are blocked and deposits are prioritized.
  • 50K max exposure — the cap on outstanding absorbed position notional. Chosen as 2.5× the current balance: the fund can safely take on up to 2.5 positions at its current size before unwind is completed.

These are per-market-portfolio numbers, not per-market. One insurance fund covers all 68 markets. This means a stress event in one market has access to the full capital pool, and replenishment from other markets’ liquidations is aggregated.

Scaling to mainnet

The 20K devnet capitalization is a floor, not a target. For mainnet, the expectation is a multi-hundred-thousand-dollar fund, funded by:

  • Initial protocol capitalization. Seeded from treasury at launch.
  • Liquidation fees. Same 50% allocation, but at much higher organic volume.
  • Potential future token-holder staking. A post-launch design option: let $SPERP holders stake into the insurance fund and earn a share of liquidation fees, with capital at risk if Layer 3 ADL is invoked. Not in v1 — tracked as a future consideration in $SPERP tokenomics.

The configure_insurance admin instruction lets max_backstop_exposure and target_balance be updated as the fund scales, without requiring a program redeploy.

Observability

Every position on a market with current_backstop_exposure > 0 should see a risk flag in its UI — the fund’s buffer is partially spoken for. Integrators should query:

const insurance = await client.getInsuranceFund();
const utilization = insurance.currentBackstopExposure / insurance.maxBackstopExposure;
// > 0.8 → high risk of ADL escalation

This is public, unauthenticated on-chain state. The monitoring service polls it every 60 seconds and sends a Telegram alert if utilization > 0.75 or total_balance < target_balance × 0.5.

Statistics and transparency

The insurance fund tracks lifetime counters for audit:

  • total_absorbed — sum of all notional that has passed through Layer 2 absorption since fund inception.
  • total_unwound — sum that has been unwound back out.

total_absorbed − total_unwound equals current_backstop_exposure. These counters are append-only — they can never decrease — so historical fund performance is fully reconstructable from on-chain data without any off-chain ledger.

Further reading