SIP-328: Debt Distribution View Functions
Author | |
---|---|
Status | Implemented |
Type | Governance |
Network | Ethereum & Optimism |
Implementor | TBD |
Release | TBD |
Proposal | Loading status... |
Created | 2023-06-16 |
Simple Summary
This proposal entails adding two functions to the Market Manager Module of the Synthetix Core System which will make it significantly easier for integrators to retrieve data pertaining to pools’ market exposure.
Abstract
A getMarketPoolDebtDistribution(uint128 marketId, uint128 poolId)
function will return the shares of a market’s debt distribution for a given pool and the total number of shares. A getMarketPools(uint marketId)
function will return the pools backing a giving market. (It is already possible to retrieve the markets that a pool is backing with the getPoolConfiguration
function.)
Motivation
In the Synthetix V3 system, derivatives markets rely on pools of liquidity such that they can always fill orders for traders. When markets accrue debt (by paying out stablecoins to traders or having the value of their issued derivatives increase) or reduce debt (by depositing stablecoins from traders or having the value of their issued derivatives decrease), this change is distributed pro-rata across the vaults of collateral in all the pools backing it. The debt associated with liquidity providers’ positions are adjusted according to their share of the collateral they’ve provided to the vault.
Being able to more easily retrieve the relative exposure of pools to markets has a variety of use cases. If a market is consistently profitable, this value can signal what share of profits would be distributed to which pools. Also—although we anticipate spot markets which enable the skew fee and perpetual futures markets will be generally neutral to price action for liquidity providers—it could be used to create a product that automatically hedges liquidity provider exposure to any price action as necessary.
Specification
Overview
The two functions expose existing data structures in the Synthetix V3 core system. This should be a relatively low-risk system upgrade.
Rationale
The function implementations are not technically view functions, as we call distributeDebtToPools
to ensure that the distribution has taken into account any pending updates to the debt distribution chain. This function can be called with callStatic
by a client application if the information needs to be retrieved in a context where chain state is not being updated.
Also, the getMarketPools
function returns two arrays of pools IDs: inRangePools
are those which are currently subject to debt distributions from the specified market, while outRangePools
are those temporarily exempt because of their maxDebtShareValue
setting.
Technical Specification
The getMarketPoolDebtDistribution
function could be implemented as follows:
function getMarketPoolDebtDistribution(
uint128 marketId,
uint128 poolId
)
external
override
returns (uint128 sharesD18, uint128 totalSharesD18, int128 valuePerShareD27)
{
Market.Data storage market = Market.load(marketId);
market.distributeDebtToPools(999999999);
DistributionActor.Data pool = market.poolsDebtDistribution.actorInfo(poolId);
sharesD18 = pool.sharesD18;
totalSharesD18 = market.poolsDebtDistribution.totalSharesD18;
valuePerShareD27 = market.poolsDebtDistribution.valuePerShareD27;
}
The getMarketPools
function could be implemented as follows:
function getMarketPools(
uint128 marketId
) external override returns (uint128[] inRangePoolIds, uint128[] outRangePoolIds) {
Market.Data storage market = Market.load(marketId);
market.distributeDebtToPools(999999999);
HeapUtil.Data storage inRangePools = market.inRangePools;
for (uint i = 1; i <= heapSize; i++) {
HeapUtil.Node memory node = inRangePools.getByIndex(i);
inRangePoolIds[i - 1] = node.id;
}
HeapUtil.Data storage outRangePools = market.outRangePools;
for (uint i = 1; i <= heapSize; i++) {
HeapUtil.Node memory node = outRangePools.getByIndex(i);
outRangePoolIds[i - 1] = node.id;
}
}
Test Case
An application could take all of the market IDs for a given pool using the getPoolConfiguration
function. For each of them, it could query getMarketPoolDebtDistribution
and calculate sharesD18.divDecimal(totalSharesD18)
from the return values. This would result in the percentage of the market's PnL adjustments that would be distributed to the given pool.
Take the following example scenario:
- 75% of the liquidity provisioning for a spot synthetic ETH market, with a
reportedDebt
of $100 (i.e. $100 of issued synthetic ETH) - 25% of the liquidity provisioning for spot synthetic BTC market, with a
reportedDebt
of $200 (i.e. $200 of issued synthetic BTC)
To fully hedge the exposure to ETH and BTC price action for this pool, it would need $75 of ETH and $50 of BTC. Accordingly, a hedging product would allocate 60% (75/125) to ETH and 40% (50/125) to BTC.
Configurable Values (Via SCCP)
N/A
Copyright
Copyright and related rights waived via CC0.