DiffusalMarginCalculator
Margin calculation view functions extracted from CollateralVault
The DiffusalMarginCalculator contract provides all margin-related view functions for the Diffusal protocol. It was extracted from DiffusalCollateralVault to reduce contract size while maintaining the same functionality.
Overview
The margin calculator handles:
| Function | Description |
|---|---|
| Equity Calculation | Computes deposit + unrealized PnL per portfolio |
| Unrealized PnL | Calculates mark-to-market PnL across positions |
| Initial Margin (IM) | Stress-tested margin requirement for new positions |
| Maintenance Margin (MM) | Threshold below which liquidation triggers |
| Health Status | Determines if a user/portfolio is liquidatable |
Margin Architecture
┌─────────────────────────────────────────────────────────────────┐
│ DiffusalMarginCalculator │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ All margin view functions │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Portfolio-aware calculations │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Uses MarginEngine for SPAN-like stress testing │ │
│ └─────────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
│ reads from
▼
┌─────────────────────────────────────────────────────────────────┐
│ Dependencies │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌────────┐ │
│ │CollateralVault│ │PositionManager│ │SeriesRegistry│ │ Quoter │ │
│ │ (deposits) │ │ (positions) │ │ (series info)│ │(prices)│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └────────┘ │
└─────────────────────────────────────────────────────────────────┘Key Concepts
Equity Calculation
Equity represents a user's net worth in the protocol:
Per Portfolio: Each portfolio has independent equity based on its deposit and positions.
Margin Requirements
The calculator uses SPAN-like stress testing via the MarginEngine library:
- Stress Scenarios: Test 4 corners (spot ±30%, IV +50%/-30%)
- Stress Loss: Maximum loss across all scenarios
- Initial Margin (IM) = Stress Loss + Adverse PnL Buffer + Notional Buffer
- Maintenance Margin (MM) = IM × 80%
| Parameter | Value | Description |
|---|---|---|
STRESS_SPOT_DOWN/UP | ±30% | Spot price shocks |
STRESS_IV_UP | +50% | IV up shock |
STRESS_IV_DOWN | -30% | IV down shock |
INITIAL_MARGIN_RATE | 15% | Notional buffer rate |
MAINTENANCE_MARGIN_RATE | 80% | MM as % of IM |
Health Status
A user/portfolio is healthy when Equity >= Maintenance Margin.
A user/portfolio is liquidatable when Equity < Maintenance Margin (unless MMM).
View Functions
Portfolio-Aware Only
All margin functions are portfolio-aware. There are no legacy user-level
functions—you must always specify a portfolioId. Use portfolio 0 for the
default portfolio.
Equity
getPortfolioEquity
Get a user's equity for a specific portfolio.
function getPortfolioEquity(address user, uint256 portfolioId) external view returns (int256 equity)| Parameter | Type | Description |
|---|---|---|
user | address | User address |
portfolioId | uint256 | Portfolio ID |
Returns: Equity value in USDC (6 decimals). Can be negative.
Unrealized PnL
getPortfolioUnrealizedPnL
Get unrealized PnL for a specific portfolio.
function getPortfolioUnrealizedPnL(address user, uint256 portfolioId) external view returns (int256 pnl)Returns: Unrealized PnL in USDC (6 decimals). Positive = profit, negative = loss.
Margin Requirements
getPortfolioInitialMargin
Get initial margin for a specific portfolio.
function getPortfolioInitialMargin(address user, uint256 portfolioId) external view returns (uint256 im)Returns: IM in USDC (6 decimals).
getPortfolioMaintenanceMargin
Get maintenance margin for a specific portfolio.
function getPortfolioMaintenanceMargin(address user, uint256 portfolioId) external view returns (uint256 mm)Returns: MM in USDC (6 decimals). MM = IM × 80%.
Max Withdraw
getPortfolioMaxWithdraw
Get maximum withdrawable amount for a specific portfolio.
function getPortfolioMaxWithdraw(address user, uint256 portfolioId) external view returns (uint256 maxWithdraw)Returns: max(0, Equity - IM) in USDC (6 decimals).
Health Status
isPortfolioHealthy
Check if a specific portfolio is healthy.
function isPortfolioHealthy(address user, uint256 portfolioId) external view returns (bool healthy)Returns: true if Equity >= MM.
isPortfolioLiquidatable
Check if a specific portfolio can be liquidated.
function isPortfolioLiquidatable(address user, uint256 portfolioId) external view returns (bool liquidatable)Returns: true if Equity < MM. MMM portfolios always return false.
Aggregated Info
getPortfolioMarginInfo
Get comprehensive margin information for a specific portfolio.
function getPortfolioMarginInfo(address user, uint256 portfolioId) external view returns (MarginInfo memory info)Returns:
struct MarginInfo {
uint256 deposit; // Raw USDC deposit (6 decimals)
int256 unrealizedPnL; // Sum of position PnL (USDC, 6 decimals)
int256 equity; // deposit + unrealizedPnL (USDC, 6 decimals)
uint256 initialMargin; // Initial margin requirement (USDC, 6 decimals)
uint256 maintenanceMargin; // Maintenance margin threshold (USDC, 6 decimals)
uint256 maxWithdraw; // Maximum withdrawable amount (USDC, 6 decimals)
bool isHealthy; // True if equity >= MM
}External References
vault
Returns the CollateralVault address.
function vault() external view returns (address)positionManager
Returns the PositionManager address.
function positionManager() external view returns (address)seriesRegistry
Returns the SeriesRegistry address.
function seriesRegistry() external view returns (address)quoter
Returns the Quoter address.
function quoter() external view returns (address)Integration Points
Depends On
| Contract | Purpose |
|---|---|
| DiffusalCollateralVault | User deposits |
| DiffusalOptionsPositionManager | Position data |
| DiffusalOptionsSeriesRegistry | Series parameters |
| DiffusalOptionsQuoter | Mark prices |
Used By
| Contract | Purpose |
|---|---|
| DiffusalCollateralVault | Delegates margin calculations |
| DiffusalLiquidationEngine | Liquidation checks |
| DiffusalLiquidationCalculator | Liquidation info |
Example Usage
import {IDiffusalMarginCalculator} from "@diffusal/interfaces/IDiffusalMarginCalculator.sol";
// Get margin info for a user's portfolio
IDiffusalMarginCalculator.MarginInfo memory info = marginCalculator.getPortfolioMarginInfo(user, portfolioId);
// Check if liquidatable
if (marginCalculator.isPortfolioLiquidatable(user, portfolioId)) {
// Portfolio can be liquidated
}
// Check max withdraw for a specific portfolio
uint256 canWithdraw = marginCalculator.getPortfolioMaxWithdraw(user, portfolioId);Code Reference
Source: packages/contracts/src/DiffusalMarginCalculator.sol
Interface: packages/contracts/src/interfaces/IDiffusalMarginCalculator.sol
Related
- Margin System — High-level margin mechanics
- MarginEngine — SPAN-like stress testing library
- DiffusalCollateralVault — Collateral management