Skip to content

Commit

Permalink
Add tests for TCR and ICR getters
Browse files Browse the repository at this point in the history
  • Loading branch information
RickGriff committed Mar 26, 2024
1 parent 3afa7aa commit fe2fa1a
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 26 deletions.
2 changes: 1 addition & 1 deletion contracts/src/Dependencies/LiquityMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ library LiquityMath {

return newCollRatio;
}
// Return the maximal value for uint256 if the Trove has a debt of 0. Represents "infinite" CR.
// Return the maximal value for uint256 if the debt is 0. Represents "infinite" CR.
else { // if (_debt == 0)
return 2**256 - 1;
}
Expand Down
21 changes: 21 additions & 0 deletions contracts/src/test/TestContracts/BaseTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,27 @@ contract BaseTest is Test {
GasPool gasPool;
IInterestRouter mockInterestRouter;

// Structs for use in test where we need to bi-pass "stack-too-deep" errors
struct TroveDebtRequests {
uint256 A;
uint256 B;
uint256 C;
}

struct TroveCollAmounts {
uint256 A;
uint256 B;
uint256 C;
}

struct TroveInterestRates {
uint256 A;
uint256 B;
uint256 C;
}

// --- functions ---

function createAccounts() public {
address[10] memory tempAccounts;
for (uint256 i = 0; i < accounts.getAccountsCount(); i++) {
Expand Down
182 changes: 169 additions & 13 deletions contracts/src/test/interestRateAggregate.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ contract InterestRateAggregate is DevTestSetup {
// --- calcTroveAccruedInterest

// returns 0 for non-existent trove
function testCalcPendingTroveInterestReturns0When0AggRecordedDebt() public {
function testCalcTroveAccruedInterestReturns0When0AggRecordedDebt() public {
priceFeed.setPrice(2000e18);

assertEq(troveManager.calcTroveAccruedInterest(A), 0);
Expand All @@ -99,7 +99,7 @@ contract InterestRateAggregate is DevTestSetup {
}
// returns 0 for 0 time passed

function testCalcPendingTroveInterestReturns0For0TimePassed() public {
function testCalcTroveAccruedInterestReturns0For0TimePassed() public {
priceFeed.setPrice(2000e18);

openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 25e16);
Expand All @@ -111,7 +111,7 @@ contract InterestRateAggregate is DevTestSetup {
assertEq(troveManager.calcTroveAccruedInterest(B), 0);
}

function testCalcPendingTroveInterestReturns0For0InterestRate() public {
function testCalcTroveAccruedInterestReturns0For0InterestRate() public {
priceFeed.setPrice(2000e18);

openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 0);
Expand All @@ -124,7 +124,7 @@ contract InterestRateAggregate is DevTestSetup {
}

// TODO: create additional corresponding fuzz test
function testCalcPendingTroveInterestReturnsCorrectInterestForGivenPeriod() public {
function testCalcTroveAccruedInterestReturnsCorrectInterestForGivenPeriod() public {
priceFeed.setPrice(2000e18);

uint256 annualRate_A = 1e18;
Expand Down Expand Up @@ -955,9 +955,6 @@ contract InterestRateAggregate is DevTestSetup {
assertEq(activePool.getRecordedDebtSum(), recordedDebtSum_1 + pendingInterest);
}

// TODO: getEntireDebt and getTCR basic tests


// --- withdrawBold tests ---

function testWithdrawBoldWithNoPendingRewardIncreasesAggRecordedDebtByPendingAggInterestPlusBorrowerDebtChange() public {
Expand Down Expand Up @@ -1872,12 +1869,6 @@ contract InterestRateAggregate is DevTestSetup {
assertEq(activePool.getRecordedDebtSum(), recordedDebt_1 - oldTroveRecordedDebt + newTroveRecordedDebt);
}

// TODO: mixed collateral & debt adjustment opps
// TODO: tests with pending debt redist. gain >0
// TODO: tests that show total debt change under user ops
// TODO: Basic TCR and ICR getter tests
// TODO: Test total debt invariant holds i.e. (D + S * delta_T) == sum_of_all_entire_trove_debts.

// --- batchLiquidateTroves (Normal Mode, offset) ---

function testBatchLiquidateTrovesPureOffsetChangesAggRecordedInterestCorrectly() public {
Expand Down Expand Up @@ -2235,4 +2226,169 @@ contract InterestRateAggregate is DevTestSetup {
// Check recorded debt sum reduced by C and D's entire debts
assertEq(defaultPool.getBoldDebt(), debtInLiq);
}

// --- TCR tests ---

function testGetTCRReturnsMaxUint256ForEmptySystem() public {
uint256 price = priceFeed.fetchPrice();
console.log(price);
uint256 TCR = troveManager.getTCR(price);

assertEq(TCR, MAX_UINT256);
}

function testGetTCRReturnsICRofTroveForSystemWithOneTrove() public {
uint256 price = priceFeed.fetchPrice();
uint256 troveDebtRequest = 2000e18;
uint256 coll = 20 ether;
uint256 interestRate = 25e16;

openTroveNoHints100pctMaxFee(A, coll, troveDebtRequest, interestRate);

uint256 compositeDebt = troveDebtRequest + borrowerOperations.BOLD_GAS_COMPENSATION();
uint256 expectedICR = coll * price / compositeDebt;
assertEq(expectedICR, troveManager.getCurrentICR(A, price));

assertEq(expectedICR,troveManager.getTCR(price));
}

function testGetTCRReturnsSizeWeightedRatioForSystemWithMultipleTroves() public {
uint256 price = priceFeed.fetchPrice();
console.log(price, "price");
uint256 troveDebtRequest_A = 2000e18;
uint256 troveDebtRequest_B = 3000e18;
uint256 troveDebtRequest_C = 5000e18;
uint256 coll_A = 20 ether;
uint256 coll_B = 30 ether;
uint256 coll_C = 40 ether;
uint256 interestRate = 25e16;

openTroveNoHints100pctMaxFee(A, coll_A, troveDebtRequest_A, interestRate);
openTroveNoHints100pctMaxFee(B, coll_B, troveDebtRequest_B, interestRate);
openTroveNoHints100pctMaxFee(C, coll_C, troveDebtRequest_C, interestRate);

uint256 compositeDebt_A = troveDebtRequest_A + borrowerOperations.BOLD_GAS_COMPENSATION();
uint256 compositeDebt_B = troveDebtRequest_B + borrowerOperations.BOLD_GAS_COMPENSATION();
uint256 compositeDebt_C = troveDebtRequest_C + borrowerOperations.BOLD_GAS_COMPENSATION();

uint256 sizeWeightedCR = (coll_A + coll_B + coll_C) * price / (compositeDebt_A + compositeDebt_B + compositeDebt_C);

assertEq(sizeWeightedCR, troveManager.getTCR(price));
}

function testGetTCRIncorporatesTroveInterestForSystemWithSingleTrove() public {
uint256 price = priceFeed.fetchPrice();
uint256 troveDebtRequest = 2000e18;
uint256 coll = 20 ether;
uint256 interestRate = 25e16;

openTroveNoHints100pctMaxFee(A, coll, troveDebtRequest, interestRate);

// Fast-forward time
vm.warp(block.timestamp + 14 days);

uint256 troveInterest = troveManager.calcTroveAccruedInterest(A);
assertGt(troveInterest, 0);

uint256 compositeDebt = troveDebtRequest + borrowerOperations.BOLD_GAS_COMPENSATION() + troveInterest;
uint256 expectedICR = coll * price / compositeDebt;
assertEq(expectedICR, troveManager.getCurrentICR(A, price));

assertEq(expectedICR,troveManager.getTCR(price));
}

function testGetTCRIncorporatesAllTroveInterestForSystemWithMultipleTroves() public {
uint256 price = priceFeed.fetchPrice();
console.log(price, "price");

// Use structs to bi-pass "stack-too-deep" error
TroveDebtRequests memory troveDebtRequests;
TroveCollAmounts memory troveCollAmounts;
TroveInterestRates memory troveInterestRates;

troveDebtRequests.A = 2000e18;
troveDebtRequests.B = 4000e18;
troveDebtRequests.C = 5000e18;
troveCollAmounts.A = 20 ether;
troveCollAmounts.B = 30 ether;
troveCollAmounts.C = 40 ether;

troveInterestRates.A = 25e16;
troveInterestRates.B = 25e16;
troveInterestRates.C = 25e16;

openTroveNoHints100pctMaxFee(A, troveCollAmounts.A, troveDebtRequests.A, troveInterestRates.A);
// Fast-forward time
vm.warp(block.timestamp + 14 days);
openTroveNoHints100pctMaxFee(B, troveCollAmounts.B, troveDebtRequests.B, troveInterestRates.B);
// Fast-forward time
vm.warp(block.timestamp + 14 days);
openTroveNoHints100pctMaxFee(C, troveCollAmounts.C, troveDebtRequests.C, troveInterestRates.C);
// Fast-forward time
vm.warp(block.timestamp + 14 days);

uint256 troveInterest_A = troveManager.calcTroveAccruedInterest(A);
assertGt(troveInterest_A, 0);
uint256 troveInterest_B = troveManager.calcTroveAccruedInterest(B);
assertGt(troveInterest_B, 0);
uint256 troveInterest_C = troveManager.calcTroveAccruedInterest(C);
assertGt(troveInterest_C, 0);

uint256 compositeDebt_A = troveDebtRequests.A + borrowerOperations.BOLD_GAS_COMPENSATION() + troveInterest_A;
uint256 compositeDebt_B = troveDebtRequests.B + borrowerOperations.BOLD_GAS_COMPENSATION() + troveInterest_B;
uint256 compositeDebt_C = troveDebtRequests.C + borrowerOperations.BOLD_GAS_COMPENSATION() + troveInterest_C;

uint256 expectedTCR = (troveCollAmounts.A + troveCollAmounts.B + troveCollAmounts.C) * price / (compositeDebt_A + compositeDebt_B + compositeDebt_C);

assertEq(expectedTCR, troveManager.getTCR(price));
}

// --- ICR tests ---

// - 0 for non-existent Trove

function testGetCurrentICRReturnsInfinityForNonExistentTrove() public {
uint256 price = priceFeed.fetchPrice();
uint256 ICR = troveManager.getCurrentICR(A, price);

assertEq(ICR, MAX_UINT256);
}

function testGetCurrentICRReturnsCorrectValueForNoInterest() public {
uint256 price = priceFeed.fetchPrice();
uint256 troveDebtRequest = 2000e18;
uint256 coll = 20 ether;
uint256 interestRate = 25e16;

openTroveNoHints100pctMaxFee(A, coll, troveDebtRequest, interestRate);

uint256 compositeDebt = troveDebtRequest + borrowerOperations.BOLD_GAS_COMPENSATION();
uint256 expectedICR = coll * price / compositeDebt;
assertEq(expectedICR, troveManager.getCurrentICR(A, price));
}

function testGetCurrentICRReturnsCorrectValueWithAccruedInterest() public {
uint256 price = priceFeed.fetchPrice();
uint256 troveDebtRequest = 2000e18;
uint256 coll = 20 ether;
uint256 interestRate = 25e16;

openTroveNoHints100pctMaxFee(A, coll, troveDebtRequest, interestRate);

// Fast-forward time
vm.warp(block.timestamp + 14 days);

uint256 troveInterest = troveManager.calcTroveAccruedInterest(A);
assertGt(troveInterest, 0);

uint256 compositeDebt = troveDebtRequest + borrowerOperations.BOLD_GAS_COMPENSATION() + troveInterest;
uint256 expectedICR = coll * price / compositeDebt;
assertEq(expectedICR, troveManager.getCurrentICR(A, price));
}

// TODO: mixed collateral & debt adjustment opps
// TODO: tests with pending debt redist. gain >0
// TODO: tests that show total debt change under user ops
// TODO: Test total debt invariant holds i.e. (D + S * delta_T) == sum_of_all_entire_trove_debts in
// more complex sequences of borrower ops and time passing
}
24 changes: 12 additions & 12 deletions contracts/src/test/interestRateBasic.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -713,23 +713,23 @@ contract InterestRateBasic is DevTestSetup {
function testWithdrawETHGainToTroveDoesntChangeEntireTroveDebt() public {
_setupForWithdrawETHGainToTrove();

// // Fast-forward time
// vm.warp(block.timestamp + 90 days);
// Fast-forward time
vm.warp(block.timestamp + 90 days);

// (uint256 entireTroveDebt_1, , , , ) = troveManager.getEntireDebtAndColl(A);
// assertGt(entireTroveDebt_1, 0);
(uint256 entireTroveDebt_1, , , , ) = troveManager.getEntireDebtAndColl(A);
assertGt(entireTroveDebt_1, 0);

// console.log(troveManager.getCurrentICR(A, 1000e18), "A ICR before");
// // A withdraws ETH gain to Trove
// withdrawETHGainToTrove(A);
console.log(troveManager.getCurrentICR(A, 1000e18), "A ICR before");
// A withdraws ETH gain to Trove
withdrawETHGainToTrove(A);

// console.log(troveManager.getCurrentICR(A, 1000e18), "A ICR after");
console.log(troveManager.getCurrentICR(A, 1000e18), "A ICR after");

// (uint256 entireTroveDebt_2, , , , ) = troveManager.getEntireDebtAndColl(A);
// console.log(entireTroveDebt_2, "entireTroveDebt_2");
// console.log(entireTroveDebt_1, "entireTroveDebt_1");
(uint256 entireTroveDebt_2, , , , ) = troveManager.getEntireDebtAndColl(A);
console.log(entireTroveDebt_2, "entireTroveDebt_2");
console.log(entireTroveDebt_1, "entireTroveDebt_1");

// assertEq(entireTroveDebt_2, entireTroveDebt_1);
assertEq(entireTroveDebt_2, entireTroveDebt_1);
}

function testWithdrawETHGainToTroveIncreasesRecordedTroveDebtByAccruedInterest() public {
Expand Down

0 comments on commit fe2fa1a

Please sign in to comment.