SIP-383: Multi-Collateral Margin Support - Perps V3

ProposalLoading status...

Simple Summary

This sip introduces multi-collaterals to Perps V3. Various collateral types, such as snxETH and snxBTC, could be used as margin by either wrapping them with the designated underlying or by purchasing directly from the spot market.


This proposal introduces multi-collateral margining. This functionality enables the inclusion of new collaterals type that back perpetual positions. Governance retains control over the types of accepted collateral and can specify parameters such as haircut calibration and maximum exposure within a given market segment


This enhancement focuses on improving user experience by enabling posting of collaterals of different types to support positions. Additionally, this new functionality facilitates the opening of delta-neutral positions, a sought-after feature particularly useful for farming funding rates.


An important design consideration in this sip was the handling of liquidated collateral: whether to distribute it directly to LPs or utilize the spot market to swap collateral for snxUSD and settle LPs' debts. To bolster the resilience of the perp market amidst spot market implementation, which entails price impact for skew rebalancing, direct collateral distribution to LPs was favored over the fire-sale option.

Technical Specification


    function setCollateralConfiguration(
        uint128 collateralId,
        uint256 maxCollateralAmount,
        uint256 upperLimitDiscount,
        uint256 lowerLimitDiscount,
        uint256 discountScalar
    ) external;

This function enables governance to specify the following parameters for eligible collaterals:

  • collateralId: Identifies the collateral, with 0 representing snxUSD and 1 representing snxETH, for example.
  • maxCollateralAmount: Specifies the maximum amount of the collateral's native currency that can be used as margin within a perp supermarket.
  • upperLimitDiscount: Sets the upper limit of the discount applied on the margin, in order to compute available margin.
  • lowerLimitDiscount: Sets the lower limit of the discount on the margin applied on the margin, in order to compute available margin.
  • discountScalar: A configurable parameter used to calculate the discount on the margin. The expression for the calculation of the discount is as follows:

unboundedDiscountRate = (marginSize * discountScalar) / skewScale

discountRate = min(max(unboundedDiscountRate;lowerLimitDiscount);upperLimitDiscount)

Hence, availableMargin would calculate the the US Dollar value of a given collateral by multiplying the size of the posted margin, by the price obtained directly from pyth, with the relevant staleness tolerance (STRICT for liquidation), with the later multiplied by (1-discountRate).


Distributing margin to the different liquidity providers that hook onto the perp market would be done with the help of the v3 RewardDistributor which is outlined in SIP-305. Note that SIP-369 allows for the configuration of an unlimited number of collaterals as margin on a perp market.


    function liquidateMarginOnly(uint128 accountId) external returns (uint256 liquidationReward);

With the introduction of volatile collateral as margin, scenarios may arise necessitating the liquidation of accounts with no open positions. This could occur if an account accumulates debt from realized losses on closed positions or from outstanding accrued funding. When the post-discount value of collateral falls below the outstanding debt due to price fluctuations, liquidators can trigger the liquidateMarginOnly function. This function distributes both the debt and margin to LPs, while compensating the liquidator with gas fees and a proportionate compensation based on the liquidated collateral's size. Moreover, under this proposal, the flagReward is determined as the maximum between the reward calculated based on the size of outstanding positions and the reward calculated base on the total size of the margin in US Dollar value. This reward is subject to a cap maximumKeeperRewardCap and a floor minimumKeeperRewardCap.

The logic behind liquidations remains the same, an account is subject to liquidation in case his available margin does not satisfy the minimum margin requirements. The margin being the discounted value of all the margins posted as collateral after removing or adding any outstanding debt and accrued interest. The required margin is based on the same maintenance margin calculation specified in SIP-337.


    function payDebt(uint128 accountId, uint256 amount) external;

In case a user has snxETH margin and intended to withdraw it, he would need to repay his outstanding debt. This wasn't an issue before introducing multi-collateral synths, since the margin would be used for settling outstanding debt. However, incorporating multi-margin requires that users settle their USD denominated debt before hand. Hence, this helper function allows a user to repay his debt and integrators would be able to facilitate this by performing the following:

  1. Flash USDC
  2. Wrap USDC to mint snxUSD
  3. Repay Debt
  4. Withdraw snxETH Margin
  5. Unwrap snxETH margin to get wETH
  6. Swap wETH to USDC on the most liquid venue
  7. Repay the flash loan

Test Cases

Relevant tests will be developed during implementation.

Configurable Values (Via SCCP)


Copyright and related rights waived via CC0.