mirror of
https://github.com/Instadapp/fluid-contracts-public.git
synced 2024-07-29 21:57:37 +00:00
d7a58e88ff
ARB: deploy protocols
803 lines
33 KiB
Solidity
803 lines
33 KiB
Solidity
//SPDX-License-Identifier: MIT
|
|
pragma solidity 0.8.21;
|
|
|
|
import { LibraryLiquidityCalcsBaseTest } from "./liquidityCalcsBaseTest.t.sol";
|
|
import { AuthInternals } from "../../../../contracts/liquidity/adminModule/main.sol";
|
|
import { Structs as AdminModuleStructs } from "../../../../contracts/liquidity/adminModule/structs.sol";
|
|
import { LiquidityCalcs } from "../../../../contracts/libraries/liquidityCalcs.sol";
|
|
import { LiquiditySlotsLink } from "../../../../contracts/libraries/liquiditySlotsLink.sol";
|
|
import { LibsErrorTypes as ErrorTypes } from "../../../../contracts/libraries/errorTypes.sol";
|
|
|
|
contract LibraryLiquidityBorrowRateFromUtilizationTests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 80 * _DEFAULT_PERCENT_PRECISION; // 80%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 4 * _DEFAULT_PERCENT_PRECISION; // 4%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 10 * _DEFAULT_PERCENT_PRECISION; // 10%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 150 * _DEFAULT_PERCENT_PRECISION; // 150%
|
|
uint256 constant _DEFAULT_KINK2 = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK2 = 80 * _DEFAULT_PERCENT_PRECISION; // 10% + half way to 150% = 80% for data compatibility with v1
|
|
|
|
function test_calcBorrowRateFromUtilization_rateVersion1() public {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
|
|
uint256 rateData = _computeRateDataPackedV1(rataDataV1Params);
|
|
uint256 utilization = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
|
|
uint256 rate = testHelper.calcBorrowRateFromUtilization(rateData, utilization);
|
|
|
|
// rate should be rate at kink + half of 10% to 150% at 100% -> 140% / 2 = 70% + 10% = 80%
|
|
assertEq(rate, 80 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcBorrowRateFromUtilization_rateVersion2() public {
|
|
AdminModuleStructs.RateDataV2Params memory rataDataV2Params = AdminModuleStructs.RateDataV2Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_KINK2,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_KINK2,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
|
|
uint256 rateData = _computeRateDataPackedV2(rataDataV2Params);
|
|
uint256 utilization = 95 * _DEFAULT_PERCENT_PRECISION; // 95%
|
|
|
|
uint256 rate = testHelper.calcBorrowRateFromUtilization(rateData, utilization);
|
|
|
|
// rate should be rate at kink2 + half of 80% to 150% at 100% -> 70% / 2 = 35% + 80% = 115%
|
|
assertEq(rate, 115 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcBorrowRateFromUtilization_rateVersion0() public {
|
|
uint256 rateData = type(uint256).max << 4; // making last 4 bits 0
|
|
|
|
vm.expectRevert(
|
|
abi.encodeWithSelector(
|
|
LiquidityCalcs.FluidLiquidityCalcsError.selector,
|
|
ErrorTypes.LiquidityCalcs__UnsupportedRateVersion
|
|
)
|
|
);
|
|
testHelper.calcBorrowRateFromUtilization(rateData, 10 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcBorrowRateFromUtilization_rateVersion3() public {
|
|
uint256 rateData = (type(uint256).max << 4) | 3; // making last 4 bits value 3
|
|
|
|
vm.expectRevert(
|
|
abi.encodeWithSelector(
|
|
LiquidityCalcs.FluidLiquidityCalcsError.selector,
|
|
ErrorTypes.LiquidityCalcs__UnsupportedRateVersion
|
|
)
|
|
);
|
|
testHelper.calcBorrowRateFromUtilization(rateData, 10 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcBorrowRateFromUtilization_rateAtMaxCap() public {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
65535 // 16 bits max value
|
|
);
|
|
|
|
uint256 rateData = 1 | // version
|
|
(rataDataV1Params.rateAtUtilizationZero << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) |
|
|
(rataDataV1Params.kink << LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationKink << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationMax << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX);
|
|
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcBorrowRateFromUtilization(rateData, utilization);
|
|
assertEq(rate, 65535);
|
|
}
|
|
|
|
function test_calcBorrowRateFromUtilization_rateJustAboveMaxCap() public {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
65535 // 16 bits max value
|
|
);
|
|
|
|
uint256 rateData = 1 | // version
|
|
(rataDataV1Params.rateAtUtilizationZero << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) |
|
|
(rataDataV1Params.kink << LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationKink << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationMax << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX);
|
|
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION + 1;
|
|
|
|
uint256 rate = testHelper.calcBorrowRateFromUtilization(rateData, utilization);
|
|
assertEq(rate, 65535); // rate should be limited to max value
|
|
}
|
|
|
|
function test_calcBorrowRateFromUtilization_rateAboveMaxCap() public {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
65535 // 16 bits max value
|
|
);
|
|
|
|
uint256 rateData = 1 | // version
|
|
(rataDataV1Params.rateAtUtilizationZero << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) |
|
|
(rataDataV1Params.kink << LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationKink << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationMax << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX);
|
|
|
|
uint256 utilization = 150 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcBorrowRateFromUtilization(rateData, utilization);
|
|
assertEq(rate, 65535); // rate should be limited to max value
|
|
}
|
|
|
|
function test_calcBorrowRateFromUtilization_EmitBorrowRateMaxCap() public {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
65535 // 16 bits max value
|
|
);
|
|
|
|
uint256 rateData = 1 | // version
|
|
(rataDataV1Params.rateAtUtilizationZero << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) |
|
|
(rataDataV1Params.kink << LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationKink << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) |
|
|
(rataDataV1Params.rateAtUtilizationMax << LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX);
|
|
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION + 1;
|
|
|
|
vm.expectEmit(true, true, true, true);
|
|
emit LiquidityCalcs.BorrowRateMaxCap();
|
|
testHelper.calcBorrowRateFromUtilization(rateData, utilization);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV1Tests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 80 * _DEFAULT_PERCENT_PRECISION; // 80%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 4 * _DEFAULT_PERCENT_PRECISION; // 4%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 10 * _DEFAULT_PERCENT_PRECISION; // 10%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 150 * _DEFAULT_PERCENT_PRECISION; // 150%
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V1;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V1 = _computeRateDataPackedV1(rataDataV1Params);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be rate at 0 + half of 4% to 10% at 80% -> 7%
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, 7 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveKink1BelowMax() public {
|
|
uint256 utilization = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
|
|
// rate should be rate at kink + half of 10% to 150% at 100% -> 140% / 2 = 70% + 10% = 80%
|
|
assertEq(rate, 80 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
// rate should be rate at kink + double the increase from 80% -> 100% (10% to 150% from kink1 to max)
|
|
// so 140% * 2 + 10% = 290%
|
|
assertEq(rate, 290 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV1DecliningTests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 80 * _DEFAULT_PERCENT_PRECISION; // 80%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 16 * _DEFAULT_PERCENT_PRECISION; // 16%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 4 * _DEFAULT_PERCENT_PRECISION; // 4%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 150 * _DEFAULT_PERCENT_PRECISION; // 150%
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V1;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V1 = _computeRateDataPackedV1(rataDataV1Params);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be rate at 0 + half decline of 16% to 4% at 80% -> 16% - 6% = 10%
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, 10 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveKink1BelowMax() public {
|
|
uint256 utilization = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
|
|
// rate should be rate at kink + half of 4% to 150% at 100% -> 146% / 2 = 73% + 4% = 77%
|
|
assertEq(rate, 77 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
// rate should be rate at kink + double the increase from 80% -> 100% (4% to 150% from kink1 to max)
|
|
// so 146% * 2 + 4% = 296%
|
|
assertEq(rate, 296 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV1FlatTests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 80 * _DEFAULT_PERCENT_PRECISION; // 80%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 4 * _DEFAULT_PERCENT_PRECISION; // 4%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 4 * _DEFAULT_PERCENT_PRECISION; // 4%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 150 * _DEFAULT_PERCENT_PRECISION; // 150%
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V1;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V1 = _computeRateDataPackedV1(rataDataV1Params);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be rate at 0 flat
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, 4 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveKink1BelowMax() public {
|
|
uint256 utilization = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
|
|
// rate should be rate at kink + half of 4% to 150% at 100% -> 146% / 2 = 73% + 4% = 77%
|
|
assertEq(rate, 77 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
// rate should be rate at kink + double the increase from 80% -> 100% (4% to 150% from kink1 to max)
|
|
// so 146% * 2 + 4% = 296%
|
|
assertEq(rate, 296 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV1FlatZeroTests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 80 * _DEFAULT_PERCENT_PRECISION; // 80%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 0 * _DEFAULT_PERCENT_PRECISION; // 0%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 0 * _DEFAULT_PERCENT_PRECISION; // 0%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 150 * _DEFAULT_PERCENT_PRECISION; // 150%
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V1;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV1Params memory rataDataV1Params = AdminModuleStructs.RateDataV1Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V1 = _computeRateDataPackedV1(rataDataV1Params);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be rate at 0 flat
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, 0);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveKink1BelowMax() public {
|
|
uint256 utilization = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
|
|
// rate should be rate at kink + half of 0% to 150% at 100% -> 75%
|
|
assertEq(rate, 75 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV1_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV1(DEFAULT_RATE_DATA_V1, utilization);
|
|
// rate should be rate at kink + double the increase from 80% -> 100% (0% to 150% from kink1 to max)
|
|
// so 150% * 2 + 0 = 300%
|
|
assertEq(rate, 300 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV2Tests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 80 * _DEFAULT_PERCENT_PRECISION; // 80%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 4 * _DEFAULT_PERCENT_PRECISION; // 4%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 10 * _DEFAULT_PERCENT_PRECISION; // 10%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 150 * _DEFAULT_PERCENT_PRECISION; // 150%
|
|
uint256 constant _DEFAULT_KINK2 = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK2 = 80 * _DEFAULT_PERCENT_PRECISION; // 10% + half way to 150% = 80% for data compatibility with v1
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V2;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV2Params memory rataDataV2Params = AdminModuleStructs.RateDataV2Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_KINK2,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_KINK2,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V2 = _computeRateDataPackedV2(rataDataV2Params);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be rate at 0 + half of 4% to 10% at 80% -> 7%
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, 7 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveKink1BelowKink2() public {
|
|
uint256 utilization = 85 * _DEFAULT_PERCENT_PRECISION; // 85%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be rate at kink1 + half of 10% (at kink1) to 80% (at kink2) = 10% + 35% = 45%
|
|
assertEq(rate, 45 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink2() public {
|
|
uint256 utilization = _DEFAULT_KINK2;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK2);
|
|
}
|
|
|
|
function test_calcRateV2_AboveKink2BelowMax() public {
|
|
uint256 utilization = 95 * _DEFAULT_PERCENT_PRECISION; // 95%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be rate at kink2 + half of 80% to 150% at 100% -> 70% / 2 = 35% + 80% = 115%
|
|
assertEq(rate, 115 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
// rate should be rate at max + twice the increase from 90% -> 100% (80% to 150% from kink2 to max)
|
|
// so 70% * 2 + 150% = 290%
|
|
assertEq(rate, 290 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV2DecliningTests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 50 * _DEFAULT_PERCENT_PRECISION; // 50%
|
|
uint256 constant _DEFAULT_KINK2 = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 0 * _DEFAULT_PERCENT_PRECISION; // 0%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 17 * _DEFAULT_PERCENT_PRECISION; // 17%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK2 = 14 * _DEFAULT_PERCENT_PRECISION; // 14%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 100 * _DEFAULT_PERCENT_PRECISION; // 100%
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V2;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV2Params memory rataDataV2Params = AdminModuleStructs.RateDataV2Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_KINK2,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_KINK2,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V2 = _computeRateDataPackedV2(rataDataV2Params);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be rate at 0 + 80% of rate at kink, so 80% of 17 -> 13.6%
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, 1360);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveKink1BelowKink2() public {
|
|
uint256 utilization = 85 * _DEFAULT_PERCENT_PRECISION; // 85%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be rate at kink1 17% MINUS 87.5% decline of 3% = 17% - 2.625% = 14.375%
|
|
assertEq(rate, 1437);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink2() public {
|
|
uint256 utilization = _DEFAULT_KINK2;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK2);
|
|
}
|
|
|
|
function test_calcRateV2_AboveKink2BelowMax() public {
|
|
uint256 utilization = 95 * _DEFAULT_PERCENT_PRECISION; // 95%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be rate at kink2 + half of 14% to 100% at 100% -> 14% + 43% = 57%
|
|
assertEq(rate, 57 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
// rate should be rate at max + twice the increase from 90% -> 100% (14% to 100% from kink2 to max)
|
|
// so 86% * 2 + 100% = 272%
|
|
assertEq(rate, 272 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV2FlatTests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 50 * _DEFAULT_PERCENT_PRECISION; // 50%
|
|
uint256 constant _DEFAULT_KINK2 = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 0 * _DEFAULT_PERCENT_PRECISION; // 0%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 10 * _DEFAULT_PERCENT_PRECISION; // 10%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK2 = 10 * _DEFAULT_PERCENT_PRECISION; // 10%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 100 * _DEFAULT_PERCENT_PRECISION; // 100%
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V2;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV2Params memory rataDataV2Params = AdminModuleStructs.RateDataV2Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_KINK2,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_KINK2,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V2 = _computeRateDataPackedV2(rataDataV2Params);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be rate at 0 + 80% of rate at kink, so 80% of 10 -> 8%
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, 8 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveKink1BelowKink2() public {
|
|
uint256 utilization = 85 * _DEFAULT_PERCENT_PRECISION; // 85%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be flat 10%
|
|
assertEq(rate, 10 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink2() public {
|
|
uint256 utilization = _DEFAULT_KINK2;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK2);
|
|
}
|
|
|
|
function test_calcRateV2_AboveKink2BelowMax() public {
|
|
uint256 utilization = 95 * _DEFAULT_PERCENT_PRECISION; // 95%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be rate at kink2 + half of 10% to 100% at 100% -> 10% + 45% = 55%
|
|
assertEq(rate, 55 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
// rate should be rate at max + twice the increase from 90% -> 100% (10% to 100% from kink2 to max)
|
|
// so 90% * 2 + 100% = 280%
|
|
assertEq(rate, 280 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|
|
|
|
contract LibraryLiquidityCalcsRateV2FlatZeroTests is LibraryLiquidityCalcsBaseTest, AuthInternals {
|
|
uint256 constant _DEFAULT_PERCENT_PRECISION = 1e2;
|
|
uint256 constant _DEFAULT_KINK = 50 * _DEFAULT_PERCENT_PRECISION; // 50%
|
|
uint256 constant _DEFAULT_KINK2 = 90 * _DEFAULT_PERCENT_PRECISION; // 90%
|
|
uint256 constant _DEFAULT_RATE_AT_ZERO = 0 * _DEFAULT_PERCENT_PRECISION; // 0%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK = 0 * _DEFAULT_PERCENT_PRECISION; // 0%
|
|
uint256 constant _DEFAULT_RATE_AT_KINK2 = 0 * _DEFAULT_PERCENT_PRECISION; // 0%
|
|
uint256 constant _DEFAULT_RATE_AT_MAX = 100 * _DEFAULT_PERCENT_PRECISION; // 100%
|
|
|
|
uint256 immutable DEFAULT_RATE_DATA_V2;
|
|
|
|
constructor() {
|
|
AdminModuleStructs.RateDataV2Params memory rataDataV2Params = AdminModuleStructs.RateDataV2Params(
|
|
address(1),
|
|
_DEFAULT_KINK,
|
|
_DEFAULT_KINK2,
|
|
_DEFAULT_RATE_AT_ZERO,
|
|
_DEFAULT_RATE_AT_KINK,
|
|
_DEFAULT_RATE_AT_KINK2,
|
|
_DEFAULT_RATE_AT_MAX
|
|
);
|
|
DEFAULT_RATE_DATA_V2 = _computeRateDataPackedV2(rataDataV2Params);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilization0() public {
|
|
uint256 utilization = 0 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_ZERO);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAbove0BelowKink1() public {
|
|
uint256 utilization = 40 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
// rate should be 0
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, 0);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink1() public {
|
|
uint256 utilization = _DEFAULT_KINK;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveKink1BelowKink2() public {
|
|
uint256 utilization = 85 * _DEFAULT_PERCENT_PRECISION; // 85%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be flat 0%
|
|
assertEq(rate, 0);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationKink2() public {
|
|
uint256 utilization = _DEFAULT_KINK2;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_KINK2);
|
|
}
|
|
|
|
function test_calcRateV2_AboveKink2BelowMax() public {
|
|
uint256 utilization = 95 * _DEFAULT_PERCENT_PRECISION; // 95%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
|
|
// rate should be rate at kink2 + half of 0% to 100% at 100% -> 50%
|
|
assertEq(rate, 50 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationMax() public {
|
|
uint256 utilization = 100 * _DEFAULT_PERCENT_PRECISION;
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
assertEq(rate, _DEFAULT_RATE_AT_MAX);
|
|
}
|
|
|
|
function test_calcRateV2_AtUtilizationAboveMax() public {
|
|
// when above 100% utilization
|
|
uint256 utilization = 120 * _DEFAULT_PERCENT_PRECISION; // utilization at 120%
|
|
|
|
uint256 rate = testHelper.calcRateV2(DEFAULT_RATE_DATA_V2, utilization);
|
|
// rate should be rate at max + twice the increase from 90% -> 100% (0% to 100% from kink2 to max)
|
|
// so 100% * 2 + 100% = 300%
|
|
assertEq(rate, 300 * _DEFAULT_PERCENT_PRECISION);
|
|
}
|
|
}
|