// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
import "forge-std/Test.sol";
import {eBTCBaseInvariants} from "./BaseInvariants.sol";
contract checkSorting is eBTCBaseInvariants {
bytes32 firstNodeBeforeAttack;
bytes32 secondNodeBeforeAttack;
bytes32 thirdNodeBeforeAttack;
bytes32 fourthNodeBeforeAttack;
bytes32 fifthNodeBeforeAttack;
bytes32 sixthNodeBeforeAttack;
bytes32 firstNodeAfterAttack;
bytes32 secondNodeAfterAttack;
bytes32 thirdNodeAfterAttack;
bytes32 fourthNodeAfterAttack;
bytes32 fifthNodeAfterAttack;
bytes32 sixthNodeAfterAttack;
bytes32 firstNodeAfterOpen;
bytes32 secondNodeAfterOpen;
bytes32 thirdNodeAfterOpen;
bytes32 fourthNodeAfterOpen;
bytes32 fifthNodeAfterOpen;
bytes32 sixthNodeAfterOpen;
bytes32 firstNodeAfterRedeem;
bytes32 secondNodeAfterRedeem;
bytes32 thirdNodeAfterRedeem;
bytes32 fourthNodeAfterRedeem;
bytes32 fifthNodeAfterRedeem;
address wallet = address(0xbad455);
function setUp() public override {
super.setUp();
connectCoreContracts();
connectLQTYContractsToCore();
}
function testSorting() public {
uint256 grossColl = 100e18 + cdpManager.LIQUIDATOR_REWARD();
uint256 price = priceFeedMock.fetchPrice();
uint256 debtMCR = _utils.calculateBorrowAmount(
100e18,
price,
MINIMAL_COLLATERAL_RATIO
);
uint256 debtColl = _utils.calculateBorrowAmount(
100e18,
price,
COLLATERAL_RATIO
);
_openTestCDP(wallet, grossColl, debtColl - 10000);
_openTestCDP(wallet, grossColl, debtColl - 7500);
_openTestCDP(wallet, grossColl, debtColl - 5000);
_openTestCDP(wallet, grossColl, debtColl);
_openTestCDP(wallet, grossColl, debtColl);
_openTestCDP(wallet, grossColl, debtMCR);
vm.startPrank(wallet);
priceFeedMock.setPrice(price - 1e1);
uint256 entireDebt = cdpManager.getSyncedCdpDebt(fourthNodeBeforeAttack);
uint256 redeemAmount = debtColl + (debtColl - 100000);
(bytes32 hint, uint256 partialNICR, , ) = hintHelpers.getRedemptionHints(redeemAmount, priceFeedMock.fetchPrice(), 0);
eBTCToken.approve(address(cdpManager), eBTCToken.balanceOf(wallet));
firstNodeBeforeAttack = sortedCdps.getFirst();
secondNodeBeforeAttack = sortedCdps.getNext(firstNodeBeforeAttack);
thirdNodeBeforeAttack = sortedCdps.getNext(secondNodeBeforeAttack);
fourthNodeBeforeAttack = sortedCdps.getNext(thirdNodeBeforeAttack);
fifthNodeBeforeAttack = sortedCdps.getNext(fourthNodeBeforeAttack);
sixthNodeBeforeAttack = sortedCdps.getNext(fifthNodeBeforeAttack);
uint256 firstNICRBeforeAttack = cdpManager.getCachedNominalICR(firstNodeBeforeAttack);
uint256 secondNICRBeforeAttack = cdpManager.getCachedNominalICR(secondNodeBeforeAttack);
uint256 thirdNICRBeforeAttack = cdpManager.getCachedNominalICR(thirdNodeBeforeAttack);
uint256 fourthNICRBeforeAttack = cdpManager.getCachedNominalICR(fourthNodeBeforeAttack);
uint256 fifthNICRBeforeAttack = cdpManager.getCachedNominalICR(fifthNodeBeforeAttack);
uint256 sixthNICRBeforeAttack = cdpManager.getCachedNominalICR(sixthNodeBeforeAttack);
console.log("---------------------------------- NICR Before Attack");
console.log("First Node NICR : ", firstNICRBeforeAttack);
console.log("Second Node NICR : ", secondNICRBeforeAttack);
console.log("Third Node NICR : ", thirdNICRBeforeAttack);
console.log("Fifth Node NICR : ", fifthNICRBeforeAttack);
console.log("Sixth Node NICR : ", sixthNICRBeforeAttack);
cdpManager.redeemCollateral(redeemAmount, hint, fourthNodeBeforeAttack, sixthNodeBeforeAttack, partialNICR, 0, 1e18);
firstNodeAfterAttack = sortedCdps.getFirst();
secondNodeAfterAttack = sortedCdps.getNext(firstNodeBeforeAttack);
thirdNodeAfterAttack = sortedCdps.getNext(secondNodeBeforeAttack);
fourthNodeAfterAttack = sortedCdps.getNext(thirdNodeBeforeAttack);
fifthNodeAfterAttack = sortedCdps.getNext(fourthNodeBeforeAttack);
uint256 firstNICRAfterAttack = cdpManager.getCachedNominalICR(firstNodeAfterAttack);
uint256 secondNICRAfterAttack = cdpManager.getCachedNominalICR(secondNodeAfterAttack);
uint256 thirdNICRAfterAttack = cdpManager.getCachedNominalICR(thirdNodeAfterAttack);
uint256 fourthNICRAfterAttack = cdpManager.getCachedNominalICR(fourthNodeAfterAttack);
uint256 fifthNICRAfterAttack = cdpManager.getCachedNominalICR(fifthNodeAfterAttack);
console.log("---------------------------------- NICR After Attack");
console.log("First Node NICR : ", firstNICRAfterAttack);
console.log("Second Node NICR : ", secondNICRAfterAttack);
console.log("Third Node NICR : ", thirdNICRAfterAttack);
console.log("Fourth Node NICR : ", fourthNICRAfterAttack);
console.log("Fifth Node NICR : ", fifthNICRAfterAttack);
uint256 priceReduced = priceFeedMock.fetchPrice();
borrowerOperations.openCdp(((10e18 * priceReduced) / 250e16), fourthNodeAfterAttack, bytes32(0), 10e18 + 2e17);
firstNodeAfterOpen = sortedCdps.getFirst();
secondNodeAfterOpen = sortedCdps.getNext(firstNodeAfterOpen);
thirdNodeAfterOpen = sortedCdps.getNext(secondNodeAfterOpen);
fourthNodeAfterOpen = sortedCdps.getNext(thirdNodeAfterOpen);
fifthNodeAfterOpen = sortedCdps.getNext(fourthNodeAfterOpen);
sixthNodeAfterOpen = sortedCdps.getNext(fifthNodeAfterOpen);
uint256 firstNICRAfterOpen = cdpManager.getCachedNominalICR(firstNodeAfterOpen);
uint256 secondNICRAfterOpen = cdpManager.getCachedNominalICR(secondNodeAfterOpen);
uint256 thirdNICRAfterOpen = cdpManager.getCachedNominalICR(thirdNodeAfterOpen);
uint256 fourthNICRAfterOpen = cdpManager.getCachedNominalICR(fourthNodeAfterOpen);
uint256 fifthNICRAfterOpen = cdpManager.getCachedNominalICR(fifthNodeAfterOpen);
uint256 sixthNICRAfterOpen = cdpManager.getCachedNominalICR(sixthNodeAfterOpen);
console.log("---------------------------------- NICR After Opening");
console.log("First Node NICR : ", firstNICRAfterOpen);
console.log("Second Node NICR : ", secondNICRAfterOpen);
console.log("Third Node NICR : ", thirdNICRAfterOpen);
console.log("Fourth Node NICR : ", fourthNICRAfterOpen);
console.log("Fifth Node NICR : ", fifthNICRAfterOpen);
console.log("Sixth Node NICR : ", sixthNICRAfterOpen);
// Confirm first redeemable is the newly opened Cdp
_confirmFirstRedeem(fifthNodeAfterOpen, priceReduced);
uint256 debtFive = cdpManager.getSyncedCdpDebt(fifthNodeAfterOpen);
cdpManager.redeemCollateral(debtFive, fifthNodeAfterOpen, bytes32(0), bytes32(0), 0, 0, 1e18);
firstNodeAfterRedeem = sortedCdps.getFirst();
secondNodeAfterRedeem = sortedCdps.getNext(firstNodeAfterRedeem);
thirdNodeAfterRedeem = sortedCdps.getNext(secondNodeAfterRedeem);
fourthNodeAfterRedeem = sortedCdps.getNext(thirdNodeAfterRedeem);
fifthNodeAfterRedeem = sortedCdps.getNext(fourthNodeAfterRedeem);
uint256 firstNICRAfterRedeem = cdpManager.getCachedNominalICR(firstNodeAfterRedeem);
uint256 secondNICRAfterRedeem = cdpManager.getCachedNominalICR(secondNodeAfterRedeem);
uint256 thirdNICRAfterRedeem = cdpManager.getCachedNominalICR(thirdNodeAfterRedeem);
uint256 fourthNICRAfterRedeem = cdpManager.getCachedNominalICR(fourthNodeAfterRedeem);
uint256 fifthNICRAfterRedeem = cdpManager.getCachedNominalICR(fifthNodeAfterRedeem);
console.log("---------------------------------- NICR After Redeem");
console.log("First Node NICR : ", firstNICRAfterRedeem);
console.log("Second Node NICR : ", secondNICRAfterRedeem);
console.log("Third Node NICR : ", thirdNICRAfterRedeem);
console.log("Fourth Node NICR : ", fourthNICRAfterRedeem);
console.log("Fifth Node NICR : ", fifthNICRAfterRedeem);
vm.stopPrank();
}
function _confirmFirstRedeem(bytes32 _firstHint, uint256 _price) public{
bool checkOne;
bytes32 nextCdp = sortedCdps.getNext(_firstHint);
checkOne = nextCdp == sortedCdps.nonExistId() || cdpManager.getSyncedICR(nextCdp, _price) < 110e16;
// Will be both true if there are underwater Cdps or not
assert(checkOne == true);
}
}