Diffusal

LiquidationLib

Pure calculation and sorting utilities for liquidation operations

The LiquidationLib library provides pure helper functions for liquidation calculations, including price penalization, bounty computation, and array sorting. All functions are internal pure, making them gas-efficient building blocks.


Overview

Function CategoryDescription
Price CalculationsPenalized liquidation prices for longs/shorts
ProceedsCalculate collateral proceeds from position closure
BountyLiquidator reward calculation
SortingSort positions by expiry (longest-dated first)
UtilitiesPrecision conversion (int64 → WAD) and absolute value

Pure Calculation Functions

calculateLiquidationPrice

Calculate the penalized price at which a position is liquidated.

function calculateLiquidationPrice(
    uint256 markPrice,
    uint256 penaltyRate,
    bool isLong
) internal pure returns (uint256 liquidationPrice)
ParameterTypeDescription
markPriceuint256Current mark price (WAD)
penaltyRateuint256Penalty rate (WAD, e.g., 0.01e18 = 1%)
isLongboolWhether position is long

Logic:

  • Long positions: Sold at lower price → markPrice × (1 - penaltyRate)
  • Short positions: Bought back at higher price → markPrice × (1 + penaltyRate)

Example:

// Mark price: $100, Penalty: 5%
// Long liquidation price: $100 × 0.95 = $95 (liquidator gets discount)
// Short liquidation price: $100 × 1.05 = $105 (liquidator gets premium)
uint256 longLiqPrice = LiquidationLib.calculateLiquidationPrice(100e18, 0.05e18, true);
// Returns: 95e18

uint256 shortLiqPrice = LiquidationLib.calculateLiquidationPrice(100e18, 0.05e18, false);
// Returns: 105e18

calculateProceeds

Calculate collateral proceeds from closing a position.

function calculateProceeds(
    int256 positionSize,
    uint256 liquidationPrice
) internal pure returns (uint256 proceeds)
ParameterTypeDescription
positionSizeint256Position size (signed, WAD)
liquidationPriceuint256Liquidation price (WAD)

Returns: |positionSize| × liquidationPrice (WAD)

Note: Uses absolute value, so sign only affects direction (who pays whom), not the amount.


calculateBounty

Calculate liquidator reward.

function calculateBounty(
    uint256 debt,
    uint256 bountyRate
) internal pure returns (uint256 bounty)
ParameterTypeDescription
debtuint256Amount underwater (USDC, 6 decimals)
bountyRateuint256Bounty rate (WAD, default 5% = 0.05e18)

Returns: debt × bountyRate (USDC, 6 decimals)

Example:

// Debt: $10,000, Bounty rate: 5%
uint256 bounty = LiquidationLib.calculateBounty(10_000e6, 0.05e18);
// Returns: 500e6 ($500)

Utility Functions

int64ToWad

Convert int64 with 8 decimals (oracle format) to WAD (18 decimals).

function int64ToWad(int64 value) internal pure returns (uint256 wadValue)
ParameterTypeDescription
valueint64Oracle value (8 decimals)

Returns: Value in WAD. Returns 0 if input is negative.

Example:

// Oracle price: $3000 = 300_000_000_000 (8 decimals)
uint256 wadPrice = LiquidationLib.int64ToWad(300_000_000_000);
// Returns: 3000e18

abs

Get absolute value of int256.

function abs(int256 x) internal pure returns (uint256)

Returns: |x| as uint256.


Sorting Functions

The sorting algorithm ensures positions are processed in optimal order for liquidation - longest-dated positions first to minimize liquidator risk from near-expiry volatility.

┌─────────────────────────────────────────────────────────────────────────┐
│                    QUICKSORT BY EXPIRY (Descending)                     │
└─────────────────────────────────────────────────────────────────────────┘

Purpose: Sort positions so longest-dated expiries come first.

Input:
  seriesIds = [A, B, C, D]       (position identifiers)
  expiries  = [30d, 60d, 7d, 90d] (days to expiry)

Algorithm:
  1. Select pivot (last element's expiry)
  2. Partition: move all items with expiry > pivot to the left
  3. Place pivot in its final sorted position
  4. Recursively sort left and right partitions

Example Trace:
  ┌─────────────────────────────────────────────────────────────────┐
  │ Start:    [A:30d, B:60d, C:7d, D:90d]                           │
  │ Pivot:    D (90d)                                               │
  │ Partition: Nothing > 90d, so D stays at end                     │
  │ Recurse:  Sort [A:30d, B:60d, C:7d]                             │
  │           Pivot: C (7d)                                         │
  │           A:30d > 7d? Yes → move left                           │
  │           B:60d > 7d? Yes → move left                           │
  │ Result:   [D:90d, B:60d, A:30d, C:7d]                           │
  └─────────────────────────────────────────────────────────────────┘

Output:
  seriesIds = [D, B, A, C]       (sorted by expiry descending)
  expiries  = [90d, 60d, 30d, 7d]

sortByExpiryDescending

Sort arrays by expiry descending (longest-dated first).

function sortByExpiryDescending(
    bytes32[] memory seriesIds,
    uint256[] memory expiries
) internal pure
ParameterTypeDescription
seriesIdsbytes32[]Series IDs to sort (modified in-place)
expiriesuint256[]Corresponding expiries (modified in-place)

Algorithm: Quicksort, O(n log n) average case.

Use case: Liquidation processes longest-dated positions first to minimize liquidator risk from near-expiry positions.


swapSeriesAndExpiry

Swap elements at indices i and j in both arrays.

function swapSeriesAndExpiry(
    bytes32[] memory seriesIds,
    uint256[] memory expiries,
    uint256 i,
    uint256 j
) internal pure

Note: Helper function used internally by sorting.


Constants Used

ConstantValueDescription
Constants.WAD1e18Standard DeFi precision
Constants.ORACLE_TO_WAD1e10Convert 8 decimals to 18 decimals

Integration Points

Used By

ContractPurpose
DiffusalLiquidationEngineCore liquidation calculations
DiffusalSettlementReadinessLiquidatorSettlement readiness liquidation

Code Reference

Source: packages/contracts/src/utils/LiquidationLib.sol


On this page