marginal price views
This commit is contained in:
@@ -224,6 +224,22 @@ interface IPartyPool is IERC20Metadata {
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountOutUint);
|
||||
|
||||
/// @notice Marginal price of `base` denominated in `quote` as Q64.64.
|
||||
/// @dev Returns the LMSR marginal price p_quote / p_base in ABDK 64.64 fixed-point format.
|
||||
/// Useful for off-chain quoting; raw 64.64 value is returned (no scaling to token units).
|
||||
/// @param baseTokenIndex index of the base asset (e.g., ETH)
|
||||
/// @param quoteTokenIndex index of the quote asset (e.g., USD)
|
||||
/// @return price Q64.64 value equal to quote per base (p_quote / p_base)
|
||||
function price(uint256 baseTokenIndex, uint256 quoteTokenIndex) external view returns (int128);
|
||||
|
||||
/// @notice Price of one LP token denominated in `quote` as Q64.64.
|
||||
/// @dev Computes LMSR poolPrice (quote per unit internal qTotal) and scales it to LP units:
|
||||
/// returns price_per_LP = poolPrice_quote * (totalSupply() / qTotal) in ABDK 64.64 format.
|
||||
/// The returned value is raw Q64.64 and represents quote units per one LP token unit.
|
||||
/// @param quoteTokenIndex index of the quote asset in which to denominate the LP price
|
||||
/// @return price Q64.64 value equal to quote per LP token unit
|
||||
function poolPrice(uint256 quoteTokenIndex) external view returns (int128);
|
||||
|
||||
/// @notice Compute repayment amounts (principal + flash fee) for a proposed flash loan.
|
||||
/// @param loanAmounts array of per-token loan amounts; must match the pool's token ordering.
|
||||
/// @return repaymentAmounts array where repaymentAmounts[i] = loanAmounts[i] + ceil(loanAmounts[i] * flashFeePpm)
|
||||
|
||||
@@ -778,6 +778,51 @@ library LMSRStabilized {
|
||||
return e_i_acc.div(Z);
|
||||
}
|
||||
|
||||
/// @notice Marginal price of `base` in terms of `quote` (p_quote / p_base) as Q64.64
|
||||
/// @dev Returns exp((q_quote - q_base) / b). Indices must be valid and b > 0.
|
||||
function price(State storage s, uint256 baseTokenIndex, uint256 quoteTokenIndex) internal view returns (int128) {
|
||||
require(baseTokenIndex < s.nAssets && quoteTokenIndex < s.nAssets, "LMSR: idx");
|
||||
int128 b = _computeB(s);
|
||||
require(b > int128(0), "LMSR: b<=0");
|
||||
|
||||
// Use reciprocal of b to avoid repeated divisions
|
||||
int128 invB = ABDKMath64x64.div(ONE, b);
|
||||
|
||||
// Marginal price p_quote / p_base = exp((q_quote - q_base) / b)
|
||||
return _exp(s.qInternal[quoteTokenIndex].sub(s.qInternal[baseTokenIndex]).mul(invB));
|
||||
}
|
||||
|
||||
/// @notice Price of one unit of the LP size-metric (S = sum q_i) denominated in `quote` asset (Q64.64)
|
||||
/// @dev Computes: poolPrice_quote = (1 / S) * sum_j q_j * exp((q_j - q_quote) / b)
|
||||
function poolPrice(State storage s, uint256 quoteTokenIndex) internal view returns (int128) {
|
||||
require(quoteTokenIndex < s.nAssets, "LMSR: idx");
|
||||
// Compute b and ensure positivity
|
||||
int128 b = _computeB(s);
|
||||
require(b > int128(0), "LMSR: b<=0");
|
||||
|
||||
// Compute total size metric S = sum q_i
|
||||
int128 S = _computeSizeMetric(s.qInternal);
|
||||
require(S > int128(0), "LMSR: size zero");
|
||||
|
||||
// Precompute reciprocal of b
|
||||
int128 invB = ABDKMath64x64.div(ONE, b);
|
||||
|
||||
// Accumulate weighted exponentials: sum_j q_j * exp((q_j - q_quote) / b)
|
||||
int128 acc = int128(0);
|
||||
uint256 n = s.nAssets;
|
||||
for (uint256 j = 0; j < n; ) {
|
||||
// factor = exp((q_j - q_quote) / b)
|
||||
int128 factor = _exp(s.qInternal[j].sub(s.qInternal[quoteTokenIndex]).mul(invB));
|
||||
// term = q_j * factor
|
||||
int128 term = s.qInternal[j].mul(factor);
|
||||
acc = acc.add(term);
|
||||
unchecked { j++; }
|
||||
}
|
||||
|
||||
// pool price in units of quote = (1 / S) * acc
|
||||
return acc.div(S);
|
||||
}
|
||||
|
||||
/* --------------------
|
||||
Slippage -> b computation & resize-triggered rescale
|
||||
-------------------- */
|
||||
|
||||
@@ -927,6 +927,42 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
return floorValue;
|
||||
}
|
||||
|
||||
/// @notice Marginal price of `base` in terms of `quote` (p_quote / p_base) as Q64.64
|
||||
/// @dev Returns the LMSR marginal price directly (raw 64.64) for use by off-chain quoting logic.
|
||||
function price(uint256 baseTokenIndex, uint256 quoteTokenIndex) external view returns (int128) {
|
||||
uint256 n = tokens.length;
|
||||
require(baseTokenIndex < n && quoteTokenIndex < n, "price: idx");
|
||||
require(lmsr.nAssets > 0, "price: uninit");
|
||||
return lmsr.price(baseTokenIndex, quoteTokenIndex);
|
||||
}
|
||||
|
||||
/// @notice Price of one LP token denominated in `quote` asset as Q64.64
|
||||
/// @dev Computes LMSR poolPrice (quote per unit qTotal) and scales it by totalSupply() / qTotal
|
||||
/// to return price per LP token unit in quote asset (raw 64.64).
|
||||
function poolPrice(uint256 quoteTokenIndex) external view returns (int128) {
|
||||
uint256 n = tokens.length;
|
||||
require(quoteTokenIndex < n, "poolPrice: idx");
|
||||
require(lmsr.nAssets > 0, "poolPrice: uninit");
|
||||
|
||||
// price per unit of qTotal (Q64.64) from LMSR
|
||||
int128 pricePerQ = lmsr.poolPrice(quoteTokenIndex);
|
||||
|
||||
// total internal q (qTotal) as Q64.64
|
||||
int128 qTotal = _computeSizeMetric(lmsr.qInternal);
|
||||
require(qTotal > int128(0), "poolPrice: qTotal zero");
|
||||
|
||||
// totalSupply as Q64.64
|
||||
uint256 supply = totalSupply();
|
||||
require(supply > 0, "poolPrice: zero supply");
|
||||
int128 supplyQ64 = ABDKMath64x64.fromUInt(supply);
|
||||
|
||||
// factor = totalSupply / qTotal (Q64.64)
|
||||
int128 factor = supplyQ64.div(qTotal);
|
||||
|
||||
// price per LP token = pricePerQ * factor (Q64.64)
|
||||
return pricePerQ.mul(factor);
|
||||
}
|
||||
|
||||
/// @notice Helper to compute size metric (sum of all asset quantities) from internal balances
|
||||
/// @dev Returns the sum of all provided qInternal_ entries as a Q64.64 value.
|
||||
function _computeSizeMetric(int128[] memory qInternal_) private pure returns (int128) {
|
||||
|
||||
Reference in New Issue
Block a user