Skip to content

Commit

Permalink
Merge pull request #69 from VenusProtocol/feat/force-liquidations-upg…
Browse files Browse the repository at this point in the history
…rade

[VEN-1932]: simulations for forced liquidations VIP
  • Loading branch information
kkirka authored Sep 18, 2023
2 parents 50cfeac + 672c46f commit 2e799a0
Show file tree
Hide file tree
Showing 14 changed files with 8,165 additions and 0 deletions.
77 changes: 77 additions & 0 deletions simulations/vip-172/vip-168-testnet/simulations.ts
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);
});
});
});
73 changes: 73 additions & 0 deletions simulations/vip-172/vip-168/simulations.ts
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);
});
});
});
Loading

0 comments on commit 2e799a0

Please sign in to comment.