DiffusalInsuranceFund
Fee collection and liquidation shortfall coverage
The DiffusalInsuranceFund contract collects protocol trading fees and provides a safety net for liquidation shortfalls. When a liquidation's proceeds don't cover the user's debt, the insurance fund steps in to cover the gap, preventing protocol insolvency.
Overview
The insurance fund serves three purposes:
| Function | Description |
|---|---|
| Fee Collection | Receives trading fees as feeRecipient for OrderBook and RFQ |
| Liquidation Shortfall | Covers debt when liquidation proceeds are insufficient |
| Settlement Shortfall | Covers batch settlement shortfalls when shorts can't pay |
Fund Flow
┌─────────────────────────────────────────────────────────────────┐
│ FEE COLLECTION │
│ │
│ OrderBook ────────────────┐ │
│ (maker + taker fees) │ │
│ ├───► Insurance Fund ───► Vault │
│ RFQ ──────────────────────┘ (deposit) │
│ (RFQ fees) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ SHORTFALL COVERAGE │
│ │
│ Liquidation ───► Shortfall? ───┐ │
│ Engine │ │
│ ├───► Insurance Fund.cover() │
│ Settlement ───► Shortfall? ───┘ │ │
│ Engine ▼ │
│ Vault.transferCollateral() │
│ │ │
│ └───► Cover bad debt │
└─────────────────────────────────────────────────────────────────┘Key Concepts
Balance Storage
The insurance fund doesn't hold USDC directly. Instead, it maintains a deposit in the CollateralVault:
function getBalance() external view returns (uint256 balance) {
return vault.getDeposit(address(this));
}This design:
- Leverages existing vault infrastructure
- Simplifies fund accounting
- Enables seamless transfers during liquidation
Fee Recipient Role
The insurance fund should be set as feeRecipient on both trading contracts:
// On OrderBook
orderBook.setFeeRecipient(address(insuranceFund));
// On RFQ
rfq.setFeeRecipient(address(insuranceFund));When fees are collected, they're transferred to the insurance fund's vault deposit.
Shortfall Coverage
When a liquidation or batch settlement has insufficient funds:
// In LiquidationEngine._coverShortfall()
if (shortfall <= insuranceBalance) {
insuranceFund.cover(shortfall); // Full coverage
} else if (insuranceBalance > 0) {
insuranceFund.cover(insuranceBalance); // Partial coverage
}
// In SettlementEngine.settlePositionBatch()
// If short collection < long payout:
if (shortfall > 0) {
insuranceFund.cover(shortfall); // Cover batch settlement gap
}Storage & State
The contract uses ERC-7201 namespaced storage for upgradeability:
/// @custom:storage-location erc7201:diffusal.storage.InsuranceFund
struct InsuranceFundStorage {
address owner;
address collateralVault;
address liquidationEngine;
address settlementEngine;
}The contract is intentionally simple—all funds are stored in the vault.
View Functions
getBalance
Returns the current insurance fund balance.
function getBalance() external view returns (uint256 balance)Returns: USDC balance (6 decimals) from vault deposit.
owner
Returns the contract owner.
function owner() external view returns (address)collateralVault
Returns the collateral vault address.
function collateralVault() external view returns (address)liquidationEngine
Returns the authorized liquidation engine address.
function liquidationEngine() external view returns (address)settlementEngine
Returns the authorized settlement engine address.
function settlementEngine() external view returns (address)Authorized Engine Functions
cover
Covers a liquidation or settlement shortfall by transferring funds.
function cover(uint256 amount) external nonReentrant onlyAuthorizedEngine| Parameter | Type | Description |
|---|---|---|
amount | uint256 | Shortfall amount to cover (USDC) |
Requirements:
- Caller must be the liquidation engine OR settlement engine
amount > 0amount <= getBalance()
Effect: Transfers amount from insurance fund's vault deposit to the calling engine.
Emits: ShortfallCovered
Owner Functions
withdraw
Withdraws excess funds from the insurance fund.
function withdraw(uint256 amount) external nonReentrant onlyOwner| Parameter | Type | Description |
|---|---|---|
amount | uint256 | Amount to withdraw (USDC) |
Requirements:
amount > 0amount <= getBalance()
Effect: Transfers amount to owner's vault deposit.
Use case: Withdraw excess funds when balance grows beyond needed safety cushion.
Emits: Withdrawal
setLiquidationEngine
Sets the authorized liquidation engine.
function setLiquidationEngine(address engine_) external onlyOwnerEmits: LiquidationEngineUpdated
setSettlementEngine
Sets the authorized settlement engine.
function setSettlementEngine(address engine_) external onlyOwnerEmits: SettlementEngineUpdated
setCollateralVault
Updates the collateral vault reference.
function setCollateralVault(address vault_) external onlyOwnerEmits: CollateralVaultUpdated
transferOwnership
Transfers contract ownership.
function transferOwnership(address newOwner) external onlyOwnerEmits: OwnershipTransferred
Events
| Event | Parameters | Description |
|---|---|---|
ShortfallCovered | amount | Shortfall covered (liquidation or settlement) |
Withdrawal | to, amount | Owner withdrew funds |
LiquidationEngineUpdated | oldEngine, newEngine | Liquidation engine changed |
SettlementEngineUpdated | oldEngine, newEngine | Settlement engine changed |
CollateralVaultUpdated | oldVault, newVault | Vault reference changed |
OwnershipTransferred | previousOwner, newOwner | Ownership changed |
Integration Points
Depends On
| Contract | Purpose |
|---|---|
| DiffusalCollateralVault | Stores insurance fund balance |
Used By
| Contract | Purpose |
|---|---|
| DiffusalLiquidationEngine | Liquidation shortfall coverage |
| DiffusalSettlementEngine | Batch settlement shortfall coverage |
| DiffusalOptionsOrderBook | Fee recipient |
| DiffusalOptionsRFQ | Fee recipient |
Security Considerations
Access Control
| Function | Access |
|---|---|
cover() | Liquidation engine OR settlement engine |
withdraw() | Owner only |
getBalance() | Public |
Reentrancy Protection
Both cover() and withdraw() use nonReentrant modifier.
Fund Adequacy
The insurance fund should maintain sufficient balance to cover potential shortfalls. Monitoring should track:
- Fund balance vs total protocol exposure
- Historical shortfall frequency
- Average shortfall size
No Margin Requirements
The insurance fund has no positions and thus no margin requirements. Its "deposit" in the vault is a pure balance.
Example: Shortfall Coverage
Scenario
A user with 3 positions gets liquidated:
- Debt: $10,000 (IM - equity)
- Liquidation proceeds: $8,000
- Shortfall: $2,000
Process
// In LiquidationEngine._settleCollateral()
if (totalProceeds < debt) {
uint256 shortfall = debt - totalProceeds; // $2,000
insuranceUsed = _coverShortfall(shortfall);
}
// In _coverShortfall()
function _coverShortfall(uint256 shortfall) internal returns (uint256 insuranceUsed) {
uint256 balance = insuranceFund.getBalance(); // e.g., $50,000
if (shortfall <= balance) {
insuranceFund.cover(shortfall); // Cover full $2,000
insuranceUsed = shortfall;
}
}Result
- User's positions closed
- $8,000 collected from positions
- $2,000 drawn from insurance fund
- Total coverage: $10,000 (matches debt)
- Insurance fund balance: $48,000
Code Reference
Source: packages/contracts/src/DiffusalInsuranceFund.sol
Interface: packages/contracts/src/interfaces/IDiffusalInsuranceFund.sol
Testnet: View on MonadVision
Related
- Liquidation (Protocol) — High-level liquidation mechanics
- DiffusalLiquidationEngine — Shortfall triggering
- Protocol Design — Fee system overview