DiffusalCollateralVault
Central collateral management with portfolio margin enforcement
The DiffusalCollateralVault contract is the central custodian for user collateral in the Diffusal protocol. It holds USDC deposits, calculates portfolio margin requirements, and enforces health checks on withdrawals and trades. This is a high-risk contract as it directly holds user funds.
Overview
The vault provides three core functions:
| Function | Description |
|---|---|
| Custody | Holds USDC collateral for all users |
| Margin Calculation | Computes equity, unrealized PnL, IM, and MM |
| Health Enforcement | Enforces margin requirements on withdrawals and trades |
Margin Hierarchy
┌────────────────────────┐
│ Deposit │ Raw USDC in vault
└────────────────────────┘
+
┌────────────────────────┐
│ Unrealized PnL │ Sum of position PnL
└────────────────────────┘
=
┌────────────────────────┐
│ Equity │ Total account value
└────────────────────────┘
≥
┌────────────────────────┐
MUST │ Initial Margin (IM) │ Required for trading
└────────────────────────┘
>
┌────────────────────────┐
MUST │ Maintenance Margin (MM)│ Required to avoid liquidation
(or liquidatable) └────────────────────────┘Key Concepts
Equity Calculation
Unrealized PnL is the sum of mark-to-market gains/losses across all positions.
Initial Margin (IM)
Initial margin is calculated using SPAN-like stress testing via the MarginEngine. See Margin Calculations for the complete formula.
Maintenance Margin (MM)
MM is 80% of IM. See Margin System for margin mechanics.
Health Check
A user is healthy if:
A user is liquidatable if:
Storage & State
The contract uses ERC-7201 namespaced storage for upgradeability:
/// @custom:storage-location erc7201:diffusal.storage.CollateralVault
struct CollateralVaultStorage {
address owner;
bool paused;
address positionManager;
address quoter;
address oracle;
mapping(address => bool) operators;
mapping(address => uint256) deposits; // User balances (USDC, 6 decimals)
}
// Immutable
IERC20 public immutable collateralToken;
address private immutable _SERIES_REGISTRY;MarginInfo Struct
struct MarginInfo {
uint256 deposit; // Raw USDC deposit (6 decimals)
int256 unrealizedPnL; // Mark-to-market PnL (6 decimals)
int256 equity; // deposit + unrealizedPnL
uint256 initialMargin; // IM requirement (6 decimals)
uint256 maintenanceMargin; // MM = IM × 80%
uint256 maxWithdraw; // max(0, equity - IM)
bool isHealthy; // equity >= MM
}User Functions
deposit
Deposits USDC collateral into the vault.
function deposit(uint256 amount) external nonReentrant whenNotPausedRequirements:
amount > 0- User must have approved vault to spend USDC
Emits: Deposited
withdraw
Withdraws USDC collateral from the vault.
function withdraw(uint256 amount) external nonReentrant whenNotPausedRequirements:
amount > 0amount <= depositamount <= maxWithdraw(post-withdrawal equity must cover IM)
Emits: Withdrawn
View Functions
getDeposit
Returns the user's raw USDC deposit.
function getDeposit(address user) external view returns (uint256)getEquity
Returns the user's total equity (deposit + unrealized PnL).
function getEquity(address user) external view returns (int256 equity)Note: Can be negative if unrealized losses exceed deposit.
getUnrealizedPnL
Returns the user's mark-to-market PnL across all positions.
function getUnrealizedPnL(address user) public view returns (int256 pnl)Uses MarginEngine.calculateUnrealizedPnL internally.
getInitialMargin
Returns the user's initial margin requirement.
function getInitialMargin(address user) public view returns (uint256 im)Uses MarginEngine.calculateInitialMargin internally.
getMaintenanceMargin
Returns the user's maintenance margin (IM × 80%).
function getMaintenanceMargin(address user) public view returns (uint256 mm)getMaxWithdraw
Returns the maximum amount a user can withdraw.
function getMaxWithdraw(address user) public view returns (uint256 maxWithdraw)isHealthy
Checks if a user's margin is above maintenance level.
function isHealthy(address user) public view returns (bool healthy)isLiquidatable
Checks if a user can be liquidated.
function isLiquidatable(address user) external view returns (bool liquidatable)Returns true if:
- User is not healthy (equity < MM), AND
- User is not a Main Market Maker
getMarginInfo
Returns comprehensive margin information.
function getMarginInfo(address user) external view returns (MarginInfo memory info)Operator Functions
These functions can only be called by authorized operators (OrderBook, RFQ, Settlement, Liquidation).
transferCollateral
Transfers collateral between users (for premium payments).
function transferCollateral(address from, address to, uint256 amount) external onlyOperatorRequirements:
amount > 0fromandtonot zerofromhas sufficient deposit
Emits: CollateralTransferred
debitCollateral
Debits collateral from a user (for settlement/liquidation).
function debitCollateral(address user, uint256 amount) external onlyOperator returns (uint256 actualDebit)Returns: The actual amount debited (may be less than requested if user has insufficient deposit).
Note: Caps at user's available deposit (won't revert if insufficient).
Emits: CollateralDebited
creditCollateral
Credits collateral to a user (for settlement).
function creditCollateral(address user, uint256 amount) external onlyOperatorEmits: CollateralCredited
Owner Functions
setOperator
Authorizes or deauthorizes an operator.
function setOperator(address operator, bool authorized) external onlyOwnerEmits: OperatorUpdated
setPositionManager / setQuoter / setOracle
Updates contract references.
function setPositionManager(address manager) external onlyOwner
function setQuoter(address _newQuoter) external onlyOwner
function setOracle(address _newOracle) external onlyOwnerpause / unpause
Emergency pause controls.
function pause() external onlyOwner
function unpause() external onlyOwnerWhen paused: deposits and withdrawals are disabled.
Emits: PausedStateChanged
transferOwnership
Transfers contract ownership.
function transferOwnership(address newOwner) external onlyOwnerEmits: OwnershipTransferred
Events
| Event | Parameters | Description |
|---|---|---|
Deposited | user, amount | USDC deposited |
Withdrawn | user, amount | USDC withdrawn |
CollateralTransferred | from, to, amount | Premium transfer |
CollateralDebited | user, amount | Settlement/liquidation debit |
CollateralCredited | user, amount | Settlement credit |
OperatorUpdated | operator, authorized | Operator status changed |
PositionManagerUpdated | manager | Position manager changed |
QuoterUpdated | quoter | Quoter changed |
OracleUpdated | oracle | Oracle changed |
PausedStateChanged | paused | Pause state toggled |
OwnershipTransferred | previousOwner, newOwner | Ownership changed |
Integration Points
Depends On
| Contract | Purpose |
|---|---|
| DiffusalOptionsPositionManager | Position queries for PnL/margin |
| DiffusalOptionsSeriesRegistry | Series info for margin calculations |
| DiffusalOptionsQuoter | Mark prices for unrealized PnL |
| MarginEngine | SPAN-like margin calculations |
| USDC (ERC20) | Collateral token |
Used By
| Contract | Purpose |
|---|---|
| DiffusalOptionsOrderBook | Premium transfers, health checks |
| DiffusalOptionsRFQ | Premium transfers, health checks |
| DiffusalSettlementEngine | Credit/debit on settlement |
| DiffusalLiquidationEngine | Liquidation proceeds |
| DiffusalInsuranceFund | Stores insurance fund balance |
Security Considerations
Reentrancy Protection
All user-facing functions use nonReentrant modifier to prevent callback attacks.
Withdrawal Margin Check
Users can only withdraw excess collateral:
uint256 maxWithdraw = getMaxWithdraw(msg.sender);
if (amount > maxWithdraw) revert Errors.WithdrawExceedsMaximum();This ensures post-withdrawal equity still covers initial margin.
Post-Trade Health Checks
Trading contracts check health after every trade:
if (!vault.isHealthy(maker)) revert Errors.InsufficientMargin();
if (!vault.isHealthy(taker)) revert Errors.InsufficientMargin();Operator Trust
Operators can transfer collateral between users. Only trusted contracts should be authorized:
- DiffusalOptionsOrderBook
- DiffusalOptionsRFQ
- DiffusalSettlementEngine
- DiffusalLiquidationEngine
Emergency Pause
Owner can pause the vault to prevent deposits/withdrawals during emergencies. Operator functions remain active to allow settlement and liquidation.
Code Reference
Source: packages/contracts/src/DiffusalCollateralVault.sol
Interface: packages/contracts/src/interfaces/IDiffusalCollateralVault.sol
Testnet: View on MonadVision
Key Constants
// From Constants.sol
uint256 constant WAD = 1e18;
uint256 constant WAD_TO_USDC = 1e12; // WAD (18 dec) to USDC (6 dec)
uint256 constant MAINTENANCE_MARGIN_RATE = 0.8e18; // 80%Related
- Margin System (Protocol) — High-level margin mechanics
- MarginEngine — SPAN-like stress testing
- Liquidation (Protocol) — When margin falls below MM
- Protocol Design — Collateral model overview