Skip to content

Commit

Permalink
Move constants back to constants file
Browse files Browse the repository at this point in the history
  • Loading branch information
haydenshively committed Sep 11, 2023
1 parent 4a6657d commit e5a1a41
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 27 deletions.
16 changes: 2 additions & 14 deletions core/src/libraries/BalanceSheet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ pragma solidity 0.8.17;
import {FixedPointMathLib as SoladyMath} from "solady/utils/FixedPointMathLib.sol";

import {
LTV_MIN,
LTV_MAX,
MAX_LEVERAGE,
LIQUIDATION_INCENTIVE,
PROBE_PERCENT_MIN,
PROBE_PERCENT_MAX,
MANIPULATION_THRESHOLD_DIVISOR
} from "./constants/Constants.sol";
import {square, mulDiv128} from "./MulDiv.sol";
Expand All @@ -32,18 +32,6 @@ struct Prices {
/// @notice Provides functions for computing a `Borrower`'s health
/// @author Aloe Labs, Inc.
library BalanceSheet {
/// @dev The minimum percentage that can be added/subtracted to the TWAP to get probe prices
uint256 internal constant PROBE_PERCENT_MIN =
1e12 -
(LTV_MAX * (LIQUIDATION_INCENTIVE * MAX_LEVERAGE + LIQUIDATION_INCENTIVE + MAX_LEVERAGE)) /
(LIQUIDATION_INCENTIVE * MAX_LEVERAGE);

/// @dev The maximum percentage that can be added/subtracted to the TWAP to get probe prices
uint256 internal constant PROBE_PERCENT_MAX =
1e12 -
(LTV_MIN * (LIQUIDATION_INCENTIVE * MAX_LEVERAGE + LIQUIDATION_INCENTIVE + MAX_LEVERAGE)) /
(LIQUIDATION_INCENTIVE * MAX_LEVERAGE);

function isHealthy(
Prices memory prices,
Assets memory mem,
Expand Down
27 changes: 20 additions & 7 deletions core/src/libraries/constants/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ uint32 constant CONSTRAINT_PAUSE_INTERVAL_MAX = 2 days;
LIQUIDATION
//////////////////////////////////////////////////////////////*/

/// @dev \\( 1 + \frac{1}{\text{MAX_LEVERAGE}} \\) should be greater than the maximum feasible single-block
/// `accrualFactor` so that liquidators have time to respond to interest updates
uint256 constant MAX_LEVERAGE = 200;

/// @dev The discount that liquidators receive when swapping assets. Expressed as reciprocal, e.g. 20 → 5%
uint256 constant LIQUIDATION_INCENTIVE = 20;

/// @dev The minimum time that must pass between `Borrower.warn` and `Borrower.liquidate` for any liquidation that
/// involves the swap callbacks (`swap1For0` and `swap0For1`). There is no grace period for in-kind liquidations.
uint256 constant LIQUIDATION_GRACE_PERIOD = 2 minutes;

/// @dev The minimum loan-to-value ratio. Actual ratio is based on implied volatility; this is just a lower bound.
/// Expressed as a 1e12 percentage, e.g. 0.10e12 → 10%
uint256 constant LTV_MIN = 0.10e12;
Expand All @@ -73,13 +84,15 @@ uint256 constant LTV_MIN = 0.10e12;
/// Expressed as a 1e12 percentage, e.g. 0.90e12 → 90%
uint256 constant LTV_MAX = 0.90e12;

/// @dev \\( 1 + \frac{1}{\text{MAX_LEVERAGE}} \\) should be greater than the maximum feasible single-block
/// `accrualFactor` so that liquidators have time to respond to interest updates
uint256 constant MAX_LEVERAGE = 200;

uint256 constant LIQUIDATION_INCENTIVE = 20; // Expressed as reciprocal, e.g. 20 → 5%
/// @dev The minimum percentage that can be added/subtracted to the TWAP to get probe prices in `BalanceSheet`
uint256 constant PROBE_PERCENT_MIN = 1e12 -
(LTV_MAX * (LIQUIDATION_INCENTIVE * MAX_LEVERAGE + LIQUIDATION_INCENTIVE + MAX_LEVERAGE)) /
(LIQUIDATION_INCENTIVE * MAX_LEVERAGE);

uint256 constant LIQUIDATION_GRACE_PERIOD = 2 minutes;
/// @dev The maximum percentage that can be added/subtracted to the TWAP to get probe prices in `BalanceSheet`
uint256 constant PROBE_PERCENT_MAX = 1e12 -
(LTV_MIN * (LIQUIDATION_INCENTIVE * MAX_LEVERAGE + LIQUIDATION_INCENTIVE + MAX_LEVERAGE)) /
(LIQUIDATION_INCENTIVE * MAX_LEVERAGE);

/*//////////////////////////////////////////////////////////////
IV AND TWAP
Expand All @@ -94,7 +107,7 @@ uint32 constant IV_SCALE = 24 hours;
/// @dev The initial value of implied volatility, used when `VolatilityOracle.prepare` is called for a new pool.
/// Expressed as a 1e12 percentage at `IV_SCALE`, e.g. {0.20e12, 24 hours} → 20% daily → 382% annual. Error on the
/// side of making this too large (resulting in low LTV).
uint128 constant IV_COLD_START = 0.20e12;
uint128 constant IV_COLD_START = uint128(PROBE_PERCENT_MAX / DEFAULT_N_SIGMA);

/// @dev The maximum rate at which (reported) implied volatility can change. Raw samples in `VolatilityOracle.update`
/// are clamped (before being stored) so as not to exceed this rate.
Expand Down
23 changes: 17 additions & 6 deletions core/test/libraries/BalanceSheet.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ pragma solidity 0.8.17;

import "forge-std/Test.sol";

import {CONSTRAINT_N_SIGMA_MIN, CONSTRAINT_N_SIGMA_MAX, LTV_MIN, IV_COLD_START} from "src/libraries/constants/Constants.sol";
import {
DEFAULT_N_SIGMA,
CONSTRAINT_N_SIGMA_MIN,
CONSTRAINT_N_SIGMA_MAX,
LTV_MIN,
PROBE_PERCENT_MIN,
PROBE_PERCENT_MAX,
IV_COLD_START
} from "src/libraries/constants/Constants.sol";
import {BalanceSheet, TickMath, square} from "src/libraries/BalanceSheet.sol";

import {FixedPointMathLib as SoladyMath} from "solady/utils/FixedPointMathLib.sol";
Expand Down Expand Up @@ -128,7 +136,9 @@ contract BalanceSheetTest is Test {
// The upper bound is due to the fact that the result (specifically `b`) must fit in uint160. The maximum
// volatility factor is 1 + IV_AWARE_PROBE_PERCENT_MAX, so we divide `TickMath.MAX_SQRT_RATIO` by
// sqrt(1e12 + IV_AWARE_PROBE_PERCENT_MAX)
sqrtMeanPriceX96 = uint160(bound(sqrtMeanPriceX96, (1 << 40), uint256(TickMath.MAX_SQRT_RATIO) * 1e6 / 1376408));
sqrtMeanPriceX96 = uint160(
bound(sqrtMeanPriceX96, (1 << 40), (uint256(TickMath.MAX_SQRT_RATIO) * 1e6) / 1376408)
);
nSigma = uint160(bound(nSigma, CONSTRAINT_N_SIGMA_MIN, CONSTRAINT_N_SIGMA_MAX));

(uint256 a, uint256 b, ) = BalanceSheet.computeProbePrices(sqrtMeanPriceX96, iv, nSigma, 0);
Expand All @@ -137,16 +147,17 @@ contract BalanceSheetTest is Test {
a = square(uint160(a));
b = square(uint160(b));

if (iv < BalanceSheet.PROBE_PERCENT_MIN / nSigma) iv = BalanceSheet.PROBE_PERCENT_MIN / nSigma;
else if (iv > BalanceSheet.PROBE_PERCENT_MAX / nSigma) iv = BalanceSheet.PROBE_PERCENT_MAX / nSigma;
if (iv < PROBE_PERCENT_MIN / nSigma) iv = PROBE_PERCENT_MIN / nSigma;
else if (iv > PROBE_PERCENT_MAX / nSigma) iv = PROBE_PERCENT_MAX / nSigma;

assertApproxEqRel(a, SoladyMath.fullMulDiv(price, 1e12 - nSigma * iv, 1e12), 0.0001e18);
assertApproxEqRel(b, SoladyMath.fullMulDiv(price, 1e12 + nSigma * iv, 1e12), 0.0001e18);
}

function test_constants() public {
assertEq(BalanceSheet.PROBE_PERCENT_MIN, 50500000000);
assertEq(BalanceSheet.PROBE_PERCENT_MAX, 894500000000);
// Just checking that things are reasonable
assertEqDecimal(PROBE_PERCENT_MIN, 50500000000, 12);
assertEqDecimal(PROBE_PERCENT_MAX, 894500000000, 12);

// Necessary for collateral factor computation to work
assertGt(LTV_MIN, TickMath.MIN_SQRT_RATIO);
Expand Down

0 comments on commit e5a1a41

Please sign in to comment.