Skip to content

Commit

Permalink
add some new read-only functions to market and pool
Browse files Browse the repository at this point in the history
should make it much easier to understand the underlying computations
that go behind capacity locked or similar issues in the future
  • Loading branch information
dbeal-eth committed Nov 19, 2024
1 parent 2215a0e commit 659899c
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 9 deletions.
30 changes: 30 additions & 0 deletions protocol/synthetix/contracts/interfaces/IMarketManagerModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,40 @@ interface IMarketManagerModule {
*/
function getMinLiquidityRatio(uint128 marketId) external view returns (uint256 minRatioD18);

/**
* @notice Retrieves a list of pool ids supplying liquidity to the market. Additionally, returns a list of pool ids registered to the market, but not actively providing liquidity
* @param marketId the id of the market
*/
function getMarketPools(
uint128 marketId
) external returns (uint128[] memory inRangePoolIds, uint128[] memory outRangePoolIds);

/**
* @notice Retrieves the maximum value per share tolerated by a pool before it will bumped out of the pool
*/
function getMarketPoolMaxDebtPerShare(
uint128 marketId,
uint128 poolId
) external view returns (int256);

/**
* @notice Retrieves the amount of credit capacity added to the total provided by a single pool attached the market
* @param marketId the id of the market
* @param poolId the id of the specific pool to retrieve capacity contribution for
*/
function getMarketCapacityContributionFromPool(
uint128 marketId,
uint128 poolId
) external view returns (uint256);

/**
* @notice Retrieves internal data about the debt distribution on the market
* @param marketId the id of the market
* @param poolId the id of the specific pool to retrieve sharesD18 for
* @return sharesD18 the number of shares (USD denominated) supplied by the supplied pool in the market
* @return totalSharesD18 the number of shares (USD denominated) supplied by all pools attached to the market
* @return valuePerShareD27 the current value per share of the debt distribution
*/
function getMarketPoolDebtDistribution(
uint128 marketId,
uint128 poolId
Expand Down
14 changes: 14 additions & 0 deletions protocol/synthetix/contracts/interfaces/IPoolModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,20 @@ interface IPoolModule {
*/
function getNominatedPoolOwner(uint128 poolId) external view returns (address nominatedOwner);

/**
* @notice Returns the current pool debt
* @param poolId The id of the pool whose total debt is being queried
* @return totalDebtD18 The total debt of all vaults put together
*/
function getPoolTotalDebt(uint128 poolId) external view returns (int256 totalDebtD18);

/**
* @notice Returns the current pool debt divided by the computed value of the underlying vault liquidity
* @param poolId The id of the pool whose total debt is being queried
* @return debtPerShareD18 The total debt of all vaults put together divided by the computed collateral value of those vaults
*/
function getPoolDebtPerShare(uint128 poolId) external view returns (int256 debtPerShareD18);

/**
* @notice Allows the system owner (not the pool owner) to set the system-wide minimum liquidity ratio.
* @param minLiquidityRatio The new system-wide minimum liquidity ratio, denominated with 18 decimals of precision. (100% is represented by 1 followed by 18 zeros.)
Expand Down
37 changes: 37 additions & 0 deletions protocol/synthetix/contracts/modules/core/MarketManagerModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,43 @@ contract MarketManagerModule is IMarketManagerModule {
}
}

/**
* @inheritdoc IMarketManagerModule
*/
function getMarketPoolMaxDebtPerShare(
uint128 marketId,
uint128 poolId
) external view override returns (int256) {
Market.Data storage market = Market.load(marketId);
return market.getPoolMaxDebtPerShare(poolId);
}

/**
* @inheritdoc IMarketManagerModule
*/
function getMarketCapacityContributionFromPool(
uint128 marketId,
uint128 poolId
) external view override returns (uint256) {
Market.Data storage market = Market.load(marketId);

int256 currentValuePerShare = market.poolsDebtDistribution.getValuePerShare();
int256 poolMaxValuePerShare = market.getPoolMaxDebtPerShare(poolId);

// the getCreditCapacityContribution function could throw a confusing error if the max value per share is less than value per share
if (currentValuePerShare > poolMaxValuePerShare) {
return 0;
}

return
market
.getCreditCapacityContribution(
market.getPoolCreditCapacity(poolId),
poolMaxValuePerShare
)
.toUint();
}

/**
* @inheritdoc IMarketManagerModule
*/
Expand Down
16 changes: 16 additions & 0 deletions protocol/synthetix/contracts/modules/core/PoolModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,22 @@ contract PoolModule is IPoolModule {
return Pool.load(poolId).name;
}

/**
* @inheritdoc IPoolModule
*/
function getPoolTotalDebt(uint128 poolId) external view override returns (int256 totalDebtD18) {
return Pool.load(poolId).totalVaultDebtsD18;
}

/**
* @inheritdoc IPoolModule
*/
function getPoolDebtPerShare(
uint128 poolId
) external view override returns (int256 debtPerShareD18) {
(, debtPerShareD18) = Pool.load(poolId).getCurrentCreditCapacityAndDebtPerShare();
}

/**
* @inheritdoc IPoolModule
*/
Expand Down
18 changes: 14 additions & 4 deletions protocol/synthetix/contracts/storage/Market.sol
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ library Market {

/**
* @dev Returns the amount of credit capacity that a certain pool provides to the market.
*
* This credit capacity is obtained by reading the amount of shares that the pool has in the market's debt distribution, which represents the amount of USD denominated credit capacity that the pool has provided to the market.
*/
function getPoolCreditCapacity(
Expand Down Expand Up @@ -343,6 +343,16 @@ library Market {
return self.poolsDebtDistribution.getValuePerShare();
}

/**
* @dev Returns the debt per share at which a pool will be bumped from a market
*/
function getPoolMaxDebtPerShare(
Data storage self,
uint128 poolId
) internal view returns (int256 maxShareValueD18) {
return -self.inRangePools.getById(poolId).priority;
}

/**
* @dev Determine the amount of debt the pool would assume if its lastValue was updated
* Needed for optimization.
Expand Down Expand Up @@ -395,7 +405,7 @@ library Market {
int256 newPoolMaxShareValueD18
) internal returns (int256 debtChangeD18) {
uint256 oldCreditCapacityD18 = getPoolCreditCapacity(self, poolId);
int256 oldPoolMaxShareValueD18 = -self.inRangePools.getById(poolId).priority;
int256 oldPoolMaxShareValueD18 = getPoolMaxDebtPerShare(self, poolId);

// Sanity checks
// require(oldPoolMaxShareValue == 0, "value is not 0");
Expand Down Expand Up @@ -537,10 +547,10 @@ library Market {
// 2 cases where we want to break out of this loop
if (
// If there is no pool in range, and we are going down
(maxDistributedD18 - actuallyDistributedD18 > 0 &&
self.poolsDebtDistribution.totalSharesD18 == 0) ||
// If there is a pool in ragne, and the lowest max value per share does not hit the limit, exit
// Note: `-edgePool.priority` is actually the max value per share limit of the pool
(maxDistributedD18 - actuallyDistributedD18 > 0 &&
self.poolsDebtDistribution.totalSharesD18 == 0) ||
(self.poolsDebtDistribution.totalSharesD18 > 0 &&
-edgePool.priority >=
k * getTargetValuePerShare(self, (maxDistributedD18 - actuallyDistributedD18)))
Expand Down
18 changes: 13 additions & 5 deletions protocol/synthetix/contracts/storage/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,10 @@ library Pool {

// Read from storage once, before entering the loop below.
// These values should not change while iterating through each market.
uint256 totalCreditCapacityD18 = self.vaultsDebtDistribution.totalSharesD18;
int128 debtPerShareD18 = totalCreditCapacityD18 > 0 // solhint-disable-next-line numcast/safe-cast
? int256(self.totalVaultDebtsD18).divDecimal(totalCreditCapacityD18.toInt()).to128() // solhint-disable-next-line numcast/safe-cast
: int128(0);

(
uint256 totalCreditCapacityD18,
int128 debtPerShareD18
) = getCurrentCreditCapacityAndDebtPerShare(self);
uint256 systemMinLiquidityRatioD18 = SystemPoolConfiguration.load().minLiquidityRatioD18;

// Loop through the pool's markets, applying market weights, and tracking how this changes the amount of debt that this pool is responsible for.
Expand Down Expand Up @@ -245,6 +244,15 @@ library Pool {
}
}

function getCurrentCreditCapacityAndDebtPerShare(
Data storage self
) internal view returns (uint256 totalCreditCapacityD18, int128 debtPerShareD18) {
totalCreditCapacityD18 = self.vaultsDebtDistribution.totalSharesD18;
debtPerShareD18 = totalCreditCapacityD18 > 0 // solhint-disable-next-line numcast/safe-cast
? int256(self.totalVaultDebtsD18).divDecimal(totalCreditCapacityD18.toInt()).to128() // solhint-disable-next-line numcast/safe-cast
: int128(0);
}

/**
* @dev Determines the resulting maximum value per share for a market, according to a system-wide minimum liquidity ratio. This prevents markets from assigning more debt to pools than they have collateral to cover.
*
Expand Down

0 comments on commit 659899c

Please sign in to comment.