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

test: Add test case for switching batch back and forth #520

Merged
merged 3 commits into from
Oct 17, 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ That’s why Troves pay upfront fee when joining even if the interest is the sam

##### Leaving a batch
When a trove leaves a batch, the user's timestamp is again reset to the current time.
No upfront fee is charged, unless the interest rate is changed in the same transaction and the batch changed the interest rate less than the cooldown period ago.
No upfront fee is charged, unless the interest rate is changed in the same transaction and either the batch changed the interest rate, or the trove joined the batch, less than the cooldown period ago.

##### Switching batches
As the function to switch batches is just a wrapper that calls the functions for leaving and joining a batch, this means that switching batches always incurs in upfront fee now (unless user doesn’t use the wrapper and waits for 1 week between leaving and joining).
Expand Down
65 changes: 61 additions & 4 deletions contracts/src/test/interestBatchManagement.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ contract InterestBatchManagementTest is DevTestSetup {
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A");
}

function testSwitchBatchBatchManagerChargesUpfrontFeeIfJoinedOldLessThanCooldownAgo() public {
function testSwitchBatchManagerChargesUpfrontFeeIfJoinedOldLessThanCooldownAgo() public {
// C registers as batch manager
registerBatchManager(C, uint128(MIN_ANNUAL_INTEREST_RATE), 1e18, 5e16, 0, MIN_INTEREST_RATE_CHANGE_PERIOD);
// A opens trove and joins batch manager B (which has the same interest)
Expand All @@ -1057,7 +1057,7 @@ contract InterestBatchManagementTest is DevTestSetup {
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A");
}

function testSwitchBatchBatchManagerChargesUpfrontFeeIfJoinedOldMoreThanCooldownAgo() public {
function testSwitchBatchManagerChargesUpfrontFeeIfJoinedOldMoreThanCooldownAgo() public {
// C registers as batch manager
registerBatchManager(C, uint128(MIN_ANNUAL_INTEREST_RATE), 1e18, 5e16, 0, MIN_INTEREST_RATE_CHANGE_PERIOD);
// A opens trove and joins batch manager B (which has the same interest)
Expand All @@ -1082,7 +1082,7 @@ contract InterestBatchManagementTest is DevTestSetup {
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A");
}

function testSwitchBatchBatchManagerChargesUpfrontFeeIfOldBatchChangedFeeLessThanCooldownAgo() public {
function testSwitchBatchManagerChargesUpfrontFeeIfOldBatchChangedFeeLessThanCooldownAgo() public {
// C registers as batch manager
registerBatchManager(C, uint128(MIN_ANNUAL_INTEREST_RATE), 1e18, 5e16, 0, MIN_INTEREST_RATE_CHANGE_PERIOD);
// A opens trove and joins batch manager B
Expand Down Expand Up @@ -1110,7 +1110,7 @@ contract InterestBatchManagementTest is DevTestSetup {
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A");
}

function testSwitchBatchBatchManagerDoesNotChargeTroveUpfrontFeeIfBatchChangesRateWithoutUpfrontFee() public {
function testSwitchBatchManagerDoesNotChargeTroveUpfrontFeeIfBatchChangesRateWithoutUpfrontFee() public {
// B registers as batch manager
registerBatchManager(B, uint128(MIN_ANNUAL_INTEREST_RATE), 1e18, 5e16, 0, MIN_INTEREST_RATE_CHANGE_PERIOD);

Expand All @@ -1135,6 +1135,63 @@ contract InterestBatchManagementTest is DevTestSetup {
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A");
}

function testSwitchBatchManagerBackAndForthCannotBeUsedToDo2ConsecutiveChangesForFree() public {
// B registers as batch manager, with interest rate 5%
registerBatchManager(B, uint128(MIN_ANNUAL_INTEREST_RATE), 1e18, 5e16, 0, MIN_INTEREST_RATE_CHANGE_PERIOD);

// C registers as batch manager, with interest rate 4%
registerBatchManager(C, uint128(MIN_ANNUAL_INTEREST_RATE), 1e18, 4e16, 0, MIN_INTEREST_RATE_CHANGE_PERIOD);

// A opens trove and joins batch manager B
uint256 troveId = openTroveAndJoinBatchManager(A, 100 ether, 2000e18, B, 5e16);

// Cool down period gone by
vm.warp(block.timestamp + INTEREST_RATE_ADJ_COOLDOWN + 1);

// Switch from B to C
uint256 ADebtBefore = troveManager.getTroveEntireDebt(troveId);
uint256 upfrontFee = forcePredictJoinBatchInterestRateUpfrontFee(troveId, C);
switchBatchManager(A, troveId, C);

// It should trigger upfront fee
assertGt(upfrontFee, 0, "Upfront fee should be > 0");
assertEq(troveManager.getTroveEntireDebt(troveId), ADebtBefore + upfrontFee, "A debt should increase by upfrontfee after first switch");
LatestTroveData memory troveData = troveManager.getLatestTroveData(troveId);
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A after first switch");

// Adjust interest rate of new batch C, to 6%
ADebtBefore = troveManager.getTroveEntireDebt(troveId);
setBatchInterestRate(C, 6e16);

// It shouldn’t trigger upfront fee
assertEq(troveManager.getTroveEntireDebt(troveId), ADebtBefore, "A debt should not increase after first batch adjust");
troveData = troveManager.getLatestTroveData(troveId);
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A after first batch adjust");

// Cool down period gone by
vm.warp(block.timestamp + INTEREST_RATE_ADJ_COOLDOWN + 1);

// Switch from C to B
ADebtBefore = troveManager.getTroveEntireDebt(troveId);
upfrontFee = forcePredictJoinBatchInterestRateUpfrontFee(troveId, B);
switchBatchManager(A, troveId, B);

// It should trigger upfront fee
assertGt(upfrontFee, 0, "Upfront fee should be > 0");
assertEq(troveManager.getTroveEntireDebt(troveId), ADebtBefore + upfrontFee, "A debt should increase by upfrontfee after second switch");
troveData = troveManager.getLatestTroveData(troveId);
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A after second switch");

// Adjust interest rate of batch B, to 3%
ADebtBefore = troveManager.getTroveEntireDebt(troveId);
setBatchInterestRate(B, 3e16);

// It shouldn’t trigger upfront fee
assertEq(troveManager.getTroveEntireDebt(troveId), ADebtBefore, "A debt should not increase after second batch adjust");
troveData = troveManager.getLatestTroveData(troveId);
assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A after second batch adjust");
}

function testAnZombieTroveGoesBackToTheBatch() public {
// A opens trove and joins batch manager B
uint256 troveId = openTroveAndJoinBatchManager(A, 100 ether, 2000e18, B, 5e16);
Expand Down
Loading