-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #69 from VenusProtocol/feat/force-liquidations-upg…
…rade [VEN-1932]: simulations for forced liquidations VIP
- Loading branch information
Showing
14 changed files
with
8,165 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { TransactionResponse } from "@ethersproject/providers"; | ||
import { expect } from "chai"; | ||
import { Contract } from "ethers"; | ||
import { parseEther, parseUnits } from "ethers/lib/utils"; | ||
import { ethers } from "hardhat"; | ||
|
||
import { expectEvents, initMainnetUser, setMaxStalePeriodInChainlinkOracle } from "../../../src/utils"; | ||
import { forking, testVip } from "../../../src/vip-framework"; | ||
import { vip172Testnet } from "../../../vips/vip-172/vip-172-testnet"; | ||
import COMPTROLLER_ABI from "./abi/comptroller.json"; | ||
import ERC20_ABI from "./abi/erc20.json"; | ||
import LIQUIDATOR_ABI from "./abi/liquidator.json"; | ||
import UNITROLLER_ABI from "./abi/unitroller.json"; | ||
|
||
const COMPTROLLER = "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D"; | ||
const CHAINLINK_ADDRESS = "0xCeA29f1266e880A1482c06eD656cD08C148BaA32"; | ||
const NORMAL_TIMELOCK = "0xce10739590001705F7FF231611ba4A48B2820327"; | ||
const CRITICAL_TIMELOCK = "0x23B893a7C45a5Eb8c8C062b9F32d0D2e43eD286D"; | ||
|
||
const NEW_COMPTROLLER_IMPLEMENTATION = "0xa8A476AD16727CE641f27d7738D2D341Ebad81CC"; | ||
const BUSD = "0x8301F2213c0eeD49a7E28Ae4c3e91722919B8B47"; | ||
const VBUSD = "0x08e0A5575De71037aE36AbfAfb516595fE68e5e4"; | ||
const BUSD_FEED = "0x9331b55D9830EF609A2aBCfAc0FBCE050A52fdEa"; | ||
|
||
const BUSD_BORROWER = "0x3456f6d0bd2484482675068542bBa4FcD13dBac7"; | ||
const BUSD_HOLDER = "0x202963d793C3973aFd14A3B435507Cb4194f3E9A"; | ||
|
||
forking(33246200, () => { | ||
let comptroller: Contract; | ||
const provider = ethers.provider; | ||
|
||
before(async () => { | ||
comptroller = new ethers.Contract(COMPTROLLER, COMPTROLLER_ABI, provider); | ||
await setMaxStalePeriodInChainlinkOracle(CHAINLINK_ADDRESS, BUSD, BUSD_FEED, NORMAL_TIMELOCK); | ||
}); | ||
|
||
testVip("VIP-168 Forced liquidations", vip172Testnet(), { | ||
callbackAfterExecution: async (txResponse: TransactionResponse) => { | ||
await expectEvents( | ||
txResponse, | ||
[UNITROLLER_ABI, COMPTROLLER_ABI], | ||
["NewImplementation", "NewPendingImplementation", "Failure"], | ||
[1, 2, 0], | ||
); | ||
}, | ||
}); | ||
|
||
describe("Post-VIP behavior", async () => { | ||
it("should have the new implementation", async () => { | ||
expect(await comptroller.comptrollerImplementation()).to.equal(NEW_COMPTROLLER_IMPLEMENTATION); | ||
}); | ||
|
||
it("allows critical timelock to enable forced liquidations", async () => { | ||
const timelockSigner = await initMainnetUser(CRITICAL_TIMELOCK, parseEther("1")); | ||
await comptroller.connect(timelockSigner)._setForcedLiquidation(VBUSD, true); | ||
expect(await comptroller.isForcedLiquidationEnabled(VBUSD)).to.equal(true); | ||
}); | ||
|
||
it("liquidates a healthy BUSD borrow, repaying more than close factor allows", async () => { | ||
const timelockSigner = await initMainnetUser(NORMAL_TIMELOCK, parseEther("1")); | ||
const liquidatorSinger = await initMainnetUser(BUSD_HOLDER, parseEther("1")); | ||
const liquidator = await ethers.getContractAt(LIQUIDATOR_ABI, await comptroller.liquidatorContract()); | ||
const busd = await ethers.getContractAt(ERC20_ABI, BUSD); | ||
const repayAmount = parseUnits("1001", 18); | ||
|
||
// Silence the "liquidate VAI first" error | ||
await liquidator.connect(timelockSigner).setMinLiquidatableVAI(parseUnits("1000000", 18)); | ||
await busd.connect(liquidatorSinger).approve(liquidator.address, repayAmount); | ||
const tx = await liquidator.connect(liquidatorSinger).liquidateBorrow(VBUSD, BUSD_BORROWER, repayAmount, VBUSD); | ||
const protocolShare = "246216236448"; | ||
const liquidatorShare = "5170540965408"; | ||
await expect(tx) | ||
.to.emit(liquidator, "LiquidateBorrowedTokens") | ||
.withArgs(BUSD_HOLDER, BUSD_BORROWER, repayAmount, VBUSD, VBUSD, protocolShare, liquidatorShare); | ||
}); | ||
}); | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { TransactionResponse } from "@ethersproject/providers"; | ||
import { expect } from "chai"; | ||
import { Contract } from "ethers"; | ||
import { parseEther, parseUnits } from "ethers/lib/utils"; | ||
import { ethers } from "hardhat"; | ||
|
||
import { expectEvents, initMainnetUser, setMaxStaleCoreAssets } from "../../../src/utils"; | ||
import { forking, testVip } from "../../../src/vip-framework"; | ||
import { vip172 } from "../../../vips/vip-172/vip-172"; | ||
import COMPTROLLER_ABI from "./abi/comptroller.json"; | ||
import ERC20_ABI from "./abi/erc20.json"; | ||
import LIQUIDATOR_ABI from "./abi/liquidator.json"; | ||
import UNITROLLER_ABI from "./abi/unitroller.json"; | ||
|
||
const COMPTROLLER = "0xfD36E2c2a6789Db23113685031d7F16329158384"; | ||
const CHAINLINK_ADDRESS = "0x1B2103441A0A108daD8848D8F5d790e4D402921F"; | ||
const NORMAL_TIMELOCK = "0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396"; | ||
const CRITICAL_TIMELOCK = "0x213c446ec11e45b15a6E29C1C1b402B8897f606d"; | ||
|
||
const NEW_COMPTROLLER_IMPLEMENTATION = "0xb5Cb55cAbC34544C708289D899Dfe2f190794C8D"; | ||
const BUSD = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"; | ||
const VBUSD = "0x95c78222B3D6e262426483D42CfA53685A67Ab9D"; | ||
const VBTC = "0x882C173bC7Ff3b7786CA16dfeD3DFFfb9Ee7847B"; | ||
const BUSD_BORROWER = "0x36D023d3Bb82b3ee3BCa30701f2C61329572b688"; | ||
const BUSD_HOLDER = "0xF977814e90dA44bFA03b6295A0616a897441aceC"; | ||
|
||
forking(31563335, () => { | ||
let comptroller: Contract; | ||
const provider = ethers.provider; | ||
|
||
before(async () => { | ||
comptroller = new ethers.Contract(COMPTROLLER, COMPTROLLER_ABI, provider); | ||
await setMaxStaleCoreAssets(CHAINLINK_ADDRESS, NORMAL_TIMELOCK); | ||
}); | ||
|
||
testVip("VIP-168 Forced liquidations", vip172(), { | ||
callbackAfterExecution: async (txResponse: TransactionResponse) => { | ||
await expectEvents( | ||
txResponse, | ||
[UNITROLLER_ABI, COMPTROLLER_ABI], | ||
["NewImplementation", "NewPendingImplementation", "Failure"], | ||
[1, 2, 0], | ||
); | ||
}, | ||
}); | ||
|
||
describe("Post-VIP behavior", async () => { | ||
it("should have the new implementation", async () => { | ||
expect(await comptroller.comptrollerImplementation()).to.equal(NEW_COMPTROLLER_IMPLEMENTATION); | ||
}); | ||
|
||
it("allows critical timelock to enable forced liquidations", async () => { | ||
const timelockSigner = await initMainnetUser(CRITICAL_TIMELOCK, parseEther("1")); | ||
await comptroller.connect(timelockSigner)._setForcedLiquidation(VBUSD, true); | ||
expect(await comptroller.isForcedLiquidationEnabled(VBUSD)).to.equal(true); | ||
}); | ||
|
||
it("liquidates a healthy BUSD borrow, repaying more than close factor allows", async () => { | ||
const liquidatorSinger = await initMainnetUser(BUSD_HOLDER, parseEther("1")); | ||
const liquidator = await ethers.getContractAt(LIQUIDATOR_ABI, await comptroller.liquidatorContract()); | ||
const busd = await ethers.getContractAt(ERC20_ABI, BUSD); | ||
const repayAmount = parseUnits("4", 18); | ||
|
||
await busd.connect(liquidatorSinger).approve(liquidator.address, repayAmount); | ||
const tx = await liquidator.connect(liquidatorSinger).liquidateBorrow(VBUSD, BUSD_BORROWER, repayAmount, VBTC); | ||
const protocolShare = "38097"; | ||
const liquidatorShare = "800043"; | ||
await expect(tx) | ||
.to.emit(liquidator, "LiquidateBorrowedTokens") | ||
.withArgs(BUSD_HOLDER, BUSD_BORROWER, repayAmount, VBUSD, VBTC, protocolShare, liquidatorShare); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.