Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add some new read-only functions to market and pool #2337

Merged
merged 3 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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 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
20 changes: 20 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,26 @@ contract PoolModule is IPoolModule {
return Pool.load(poolId).name;
}

/**
* @inheritdoc IPoolModule
*/
function getPoolTotalDebt(uint128 poolId) external override returns (int256 totalDebtD18) {
Pool.Data storage pool = Pool.loadExisting(poolId);
pool.distributeDebtToVaults(address(0));
return pool.totalVaultDebtsD18;
}

/**
* @inheritdoc IPoolModule
*/
function getPoolDebtPerShare(
uint128 poolId
) external override returns (int256 debtPerShareD18) {
Pool.Data storage pool = Pool.loadExisting(poolId);
pool.distributeDebtToVaults(address(0));
(, debtPerShareD18) = pool.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 @@ -350,6 +350,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 @@ -402,7 +412,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 @@ -544,10 +554,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
Original file line number Diff line number Diff line change
Expand Up @@ -625,4 +625,31 @@ describe('MarketManagerModule', function () {
assertBn.equal(result.valuePerShareD27, bn(1000000000));
});
});

describe('getMarketPoolMaxDebtPerShare()', () => {
before(restore);

it('returns the correct pool max debt per share', async () => {
const result = await systems().Core.callStatic.getMarketPoolMaxDebtPerShare(
marketId(),
poolId
);

assertBn.equal(result, ethers.utils.parseEther('1'));
});
});

describe('getMarketCapacityContributionFromPool()', () => {
before(restore);

it('returns the correct pool max debt per share', async () => {
const result = await systems().Core.callStatic.getMarketCapacityContributionFromPool(
marketId(),
poolId
);

// there is only one pool so the credit capacity and that returned by the capacity contribution should be the same
assertBn.equal(result, await systems().Core.Market_get_creditCapacityD18(marketId()));
});
});
});
Loading