Skip to content
Open
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
3,238 changes: 3,238 additions & 0 deletions simulations/vip-473/abi/LegacyPoolComptroller.json

Large diffs are not rendered by default.

1,747 changes: 1,747 additions & 0 deletions simulations/vip-473/abi/LegacyPoolVToken.json

Large diffs are not rendered by default.

750 changes: 750 additions & 0 deletions simulations/vip-473/abi/ResilientOracle.json

Large diffs are not rendered by default.

2,121 changes: 2,121 additions & 0 deletions simulations/vip-473/abi/comptroller.json

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions simulations/vip-473/bscmainnet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { expect } from "chai";
import { BigNumber } from "ethers";
import { parseUnits } from "ethers/lib/utils";
import { ethers } from "hardhat";
import { NETWORK_ADDRESSES } from "src/networkAddresses";
import { setMaxStalePeriodInBinanceOracle } from "src/utils";
import { checkCorePoolComptroller } from "src/vip-framework/checks/checkCorePoolComptroller";
import { checkRiskParameters } from "src/vip-framework/checks/checkRiskParameters";
import { checkVToken } from "src/vip-framework/checks/checkVToken";
import { checkInterestRate } from "src/vip-framework/checks/interestRateModel";
import { forking, testVip } from "src/vip-framework/index";

import vip473, { BURN_AMOUNT, PROTOCOL_SHARE_RESERVE, marketSpec } from "../../vips/vip-473/bscmainnet";
import COMPTROLLER_ABI from "./abi/LegacyPoolComptroller.json";
import VTOKEN_ABI from "./abi/LegacyPoolVToken.json";
import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json";

const BLOCKS_PER_YEAR = BigNumber.from(10512000);

const { RESILIENT_ORACLE, ACCESS_CONTROL_MANAGER, NORMAL_TIMELOCK, BINANCE_ORACLE } = NETWORK_ADDRESSES.bscmainnet;

forking(47809465, async () => {
const resilientOracle = new ethers.Contract(RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, ethers.provider);
const vToken = new ethers.Contract(marketSpec.vToken.address, VTOKEN_ABI, ethers.provider);
const comptroller = new ethers.Contract(marketSpec.vToken.comptroller, COMPTROLLER_ABI, ethers.provider);

before(async () => {
await setMaxStalePeriodInBinanceOracle(BINANCE_ORACLE, "lisUSD");
});

describe("Pre-VIP behavior", () => {
it("has the correct price", async () => {
expect(await resilientOracle.getPrice(marketSpec.vToken.underlying.address)).to.equal(
parseUnits("0.99854774", 18),
);
expect(await resilientOracle.getUnderlyingPrice(marketSpec.vToken.address)).to.equal(
parseUnits("0.99854774", 18),
);
});
it("should have 35 markets in the core pool", async () => {
const markets = await comptroller.getAllMarkets();
expect(markets).to.have.lengthOf(35);
});
});

testVip("lisUSD market VIP", await vip473(), {});

describe("Post-VIP behavior", async () => {
it("should have 36 markets in the core pool", async () => {
const markets = await comptroller.getAllMarkets();
expect(markets).to.have.lengthOf(36);
});

it("has correct owner", async () => {
expect(await vToken.admin()).to.equal(NORMAL_TIMELOCK);
});

it("has correct ACM", async () => {
expect(await vToken.accessControlManager()).to.equal(ACCESS_CONTROL_MANAGER);
});

it("has correct initial supply", async () => {
const expectedSupply = parseUnits("1000000", 8).sub(BURN_AMOUNT);
expect(await vToken.balanceOf(marketSpec.initialSupply.vTokenReceiver)).to.equal(expectedSupply);
expect(await vToken.balanceOf(NORMAL_TIMELOCK)).to.equal(0);
});

it("has correct protocol share reserve", async () => {
expect(await vToken.protocolShareReserve()).equals(PROTOCOL_SHARE_RESERVE);
});

it("checks risk parameters", async () => {
await checkRiskParameters(marketSpec.vToken.address, marketSpec.vToken, marketSpec.riskParameters);
});

it("checks vToken", async () => {
await checkVToken(marketSpec.vToken.address, marketSpec.vToken);
});

it("checks interest rate", async () => {
await checkInterestRate(
marketSpec.interestRateModel.address,
marketSpec.vToken.symbol,
marketSpec.interestRateModel,
BLOCKS_PER_YEAR,
);
});

it("checks core pool comptroller", async () => {
await checkCorePoolComptroller();
});
});
});
84 changes: 84 additions & 0 deletions simulations/vip-473/bsctestnet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { expect } from "chai";
import { BigNumber } from "ethers";
import { parseUnits } from "ethers/lib/utils";
import { ethers } from "hardhat";
import { NETWORK_ADDRESSES } from "src/networkAddresses";
import { checkCorePoolComptroller } from "src/vip-framework/checks/checkCorePoolComptroller";
import { checkRiskParameters } from "src/vip-framework/checks/checkRiskParameters";
import { checkVToken } from "src/vip-framework/checks/checkVToken";
import { checkInterestRate } from "src/vip-framework/checks/interestRateModel";
import { forking, testVip } from "src/vip-framework/index";

import vip473, { BURN_AMOUNT, PROTOCOL_SHARE_RESERVE, marketSpec } from "../../vips/vip-473/bsctestnet";
import COMPTROLLER_ABI from "./abi/LegacyPoolComptroller.json";
import VTOKEN_ABI from "./abi/LegacyPoolVToken.json";
import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json";

const BLOCKS_PER_YEAR = BigNumber.from(10512000);

const { RESILIENT_ORACLE, ACCESS_CONTROL_MANAGER, NORMAL_TIMELOCK } = NETWORK_ADDRESSES.bsctestnet;

forking(49424214, async () => {
const resilientOracle = new ethers.Contract(RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, ethers.provider);
const vToken = new ethers.Contract(marketSpec.vToken.address, VTOKEN_ABI, ethers.provider);
const comptroller = new ethers.Contract(marketSpec.vToken.comptroller, COMPTROLLER_ABI, ethers.provider);

describe("Pre-VIP behavior", () => {
it("has the correct price", async () => {
expect(await resilientOracle.getPrice(marketSpec.vToken.underlying.address)).to.equal(parseUnits("1", 18));
expect(await resilientOracle.getUnderlyingPrice(marketSpec.vToken.address)).to.equal(parseUnits("1", 18));
});
it("should have 28 markets in the core pool", async () => {
const markets = await comptroller.getAllMarkets();
expect(markets).to.have.lengthOf(28);
});
});

testVip("lisUSD market VIP", await vip473(), {});

describe("Post-VIP behavior", async () => {
it("should have 29 markets in the core pool", async () => {
const markets = await comptroller.getAllMarkets();
expect(markets).to.have.lengthOf(29);
});

it("has correct owner", async () => {
expect(await vToken.admin()).to.equal(NORMAL_TIMELOCK);
});

it("has correct ACM", async () => {
expect(await vToken.accessControlManager()).to.equal(ACCESS_CONTROL_MANAGER);
});

it("has correct initial supply", async () => {
const expectedSupply = parseUnits("1000000", 8).sub(BURN_AMOUNT);
expect(await vToken.balanceOf(marketSpec.initialSupply.vTokenReceiver)).to.equal(expectedSupply);
expect(await vToken.balanceOf(NORMAL_TIMELOCK)).to.equal(0);
});

it("has correct protocol share reserve", async () => {
expect(await vToken.protocolShareReserve()).equals(PROTOCOL_SHARE_RESERVE);
});

it("checks risk parameters", async () => {
await checkRiskParameters(marketSpec.vToken.address, marketSpec.vToken, marketSpec.riskParameters);
});

it("checks vToken", async () => {
await checkVToken(marketSpec.vToken.address, marketSpec.vToken);
});

it("checks interest rate", async () => {
await checkInterestRate(
marketSpec.interestRateModel.address,
marketSpec.vToken.symbol,
marketSpec.interestRateModel,
BLOCKS_PER_YEAR,
);
});

it("checks core pool comptroller", async () => {
await checkCorePoolComptroller();
});
});
});
2 changes: 2 additions & 0 deletions src/networkAddresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const NETWORK_ADDRESSES = {
CHAINLINK_ORACLE: oracleBscmainnetContracts.addresses.ChainlinkOracle,
COMPTROLLER_LENS: bscmainnetDeployedContracts.addresses.ComptrollerLens,
GENERIC_TEST_USER_ACCOUNT: "0xF977814e90dA44bFA03b6295A0616a897441aceC",
CORE_COMPTROLLER_GENERIC_TEST_USER_ACCOUNT: "0xF977814e90dA44bFA03b6295A0616a897441aceC",
XVS_VAULT_PROXY: bscmainnetDeployedContracts.addresses.XVSVaultProxy,
XVS: bscmainnetDeployedContracts.addresses.XVS,
VAI_UNITROLLER: bscmainnetDeployedContracts.addresses.VaiUnitroller,
Expand All @@ -62,6 +63,7 @@ export const NETWORK_ADDRESSES = {
CHAINLINK_ORACLE: oracleBsctestnetContracts.addresses.ChainlinkOracle,
COMPTROLLER_LENS: bsctestnetDeployedContracts.addresses.ComptrollerLens,
GENERIC_TEST_USER_ACCOUNT: "0xB7314B8e69DCD32a72aC163679628117E90d3746",
CORE_COMPTROLLER_GENERIC_TEST_USER_ACCOUNT: "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706",
XVS_VAULT_PROXY: bsctestnetDeployedContracts.addresses.XVSVaultProxy,
XVS: bsctestnetDeployedContracts.addresses.XVS,
VAI_UNITROLLER: bsctestnetDeployedContracts.addresses.VaiUnitroller,
Expand Down
37 changes: 27 additions & 10 deletions src/vip-framework/checks/checkCorePoolComptroller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { FORKED_NETWORK, ethers } from "hardhat";

import { NETWORK_ADDRESSES } from "../../networkAddresses";
import { setMaxStalePeriodInChainlinkOracle } from "../../utils";
import CHAINLINK_ABI from "../abi/chainlinkOracle.json";
import COMPTROLLER_ABI from "../abi/comptroller.json";
import ERC20_ABI from "../abi/erc20.json";
import VTOKEN_ABI from "../abi/vToken.json";
Expand All @@ -19,12 +20,11 @@ let vUSDT_ADDRESS = mainnet.addresses.vUSDT;
let USDT = mainnet.addresses.USDT;
let ETH = mainnet.addresses.ETH;
let NORMAL_TIMELOCK = mainnetGovernance.addresses.NormalTimelock;
let XVS = mainnet.addresses.XVS;
let COMPTROLLER = mainnet.addresses.Unitroller;
let LENS = mainnet.addresses.ComptrollerLens;
let ETH_FEED = NETWORK_ADDRESSES.bscmainnet.ETH_CHAINLINK_FEED;
let USDT_FEED = NETWORK_ADDRESSES.bscmainnet.USDT_CHAINLINK_FEED;
let ACCOUNT = NETWORK_ADDRESSES.bscmainnet.GENERIC_TEST_USER_ACCOUNT;
let ACCOUNT = NETWORK_ADDRESSES.bscmainnet.CORE_COMPTROLLER_GENERIC_TEST_USER_ACCOUNT;
let CHAINLINK_ORACLE = NETWORK_ADDRESSES.bscmainnet.CHAINLINK_ORACLE;

if (FORKED_NETWORK === "bsctestnet") {
Expand All @@ -33,11 +33,10 @@ if (FORKED_NETWORK === "bsctestnet") {
USDT = testnet.addresses.USDT;
ETH = testnet.addresses.ETH;
NORMAL_TIMELOCK = testnetGovernance.addresses.NormalTimelock;
XVS = testnet.addresses.XVS;
COMPTROLLER = testnet.addresses.Unitroller;
ETH_FEED = NETWORK_ADDRESSES.bsctestnet.ETH_CHAINLINK_FEED;
USDT_FEED = NETWORK_ADDRESSES.bsctestnet.USDT_CHAINLINK_FEED;
ACCOUNT = NETWORK_ADDRESSES.bsctestnet.GENERIC_TEST_USER_ACCOUNT;
ACCOUNT = NETWORK_ADDRESSES.bsctestnet.CORE_COMPTROLLER_GENERIC_TEST_USER_ACCOUNT;
CHAINLINK_ORACLE = NETWORK_ADDRESSES.bsctestnet.CHAINLINK_ORACLE;

LENS = NETWORK_ADDRESSES[FORKED_NETWORK].COMPTROLLER_LENS;
Expand All @@ -51,7 +50,6 @@ export const checkCorePoolComptroller = () => {
let veth: Contract;
let vusdt: Contract;
let timelockSigner: Signer;
let xvs: Contract;

before(async () => {
await impersonateAccount(ACCOUNT);
Expand All @@ -64,10 +62,26 @@ export const checkCorePoolComptroller = () => {
eth = await ethers.getContractAt(ERC20_ABI, ETH, signer);
veth = await ethers.getContractAt(VTOKEN_ABI, vETH_ADDRESS, signer);
vusdt = await ethers.getContractAt(VTOKEN_ABI, vUSDT_ADDRESS, signer);
xvs = await ethers.getContractAt(ERC20_ABI, XVS, signer);

await setMaxStalePeriodInChainlinkOracle(CHAINLINK_ORACLE, USDT, USDT_FEED, NORMAL_TIMELOCK);
await setMaxStalePeriodInChainlinkOracle(CHAINLINK_ORACLE, ETH, ETH_FEED, NORMAL_TIMELOCK);

const chainlinkOracle = await ethers.getContractAt(CHAINLINK_ABI, CHAINLINK_ORACLE);

for (let i = 0; i < 50; i++) {
try {
const vToken = await comptroller.accountAssets(ACCOUNT, i);
const vTokenContract = await ethers.getContractAt(VTOKEN_ABI, vToken);
const underlying = await vTokenContract.underlying();

const config = await chainlinkOracle.tokenConfigs(underlying);
if (config.feed != ethers.constants.AddressZero) {
await setMaxStalePeriodInChainlinkOracle(CHAINLINK_ORACLE, config.asset, config.feed, NORMAL_TIMELOCK);
}
} catch (e) {
break;
}
}
});

it(`check if comptroller`, async () => {
Expand All @@ -86,13 +100,16 @@ export const checkCorePoolComptroller = () => {

let usdtBalance = await usdt.balanceOf(ACCOUNT);
const usdtDecimals = await usdt.decimals();

if ((await comptroller.borrowCaps(vusdt.address)) == 0) {
await comptroller
.connect(await ethers.getSigner(NORMAL_TIMELOCK))
._setMarketBorrowCaps([vusdt.address], [parseUnits("100000000000", usdtDecimals)]);
}

await vusdt.borrow(parseUnits("100", usdtDecimals));
expect(await usdt.balanceOf(ACCOUNT)).to.gt(usdtBalance);

const originalXVSBalance = await xvs.balanceOf(ACCOUNT);
await expect(comptroller["claimVenus(address)"](ACCOUNT)).to.be.not.reverted;
expect(await xvs.balanceOf(ACCOUNT)).to.be.greaterThanOrEqual(originalXVSBalance);

usdtBalance = await usdt.balanceOf(ACCOUNT);
await usdt.approve(vusdt.address, parseUnits("100", usdtDecimals));
await vusdt.repayBorrow(parseUnits("100", usdtDecimals));
Expand Down
Loading
Loading