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
| Balance | 20,000 USDC |
| Target balance | 10,000 USDC |
| Max backstop exposure | 50,000 USDC |
| Current backstop exposure | varies — live on-chain |
| Replenishment | 50% 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:
- 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.
- Admin deposits. The
deposit_insuranceinstruction 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:
- Backstop absorption. When
backstop_liquidateis 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 itscurrent_backstop_exposurerises. - Backstop unwind losses. As
unwind_backstopcalls 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. - Admin withdrawals. The
withdraw_insuranceinstruction allows admin to pull funds above thetarget_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_exposureon a single event. Comparable in scale to the realistic per-marketeffective_oienvelope 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 escalationThis 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
- Three-Layer Cascade — how Layer 2 invokes the fund and how unwind works.
- Auto-Deleveraging — what happens when the fund is exhausted.
- Protocol Architecture — the insurance fund as one of 7 PDA types.