Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VEN-1831]: Multichain fork tests #299

Merged
merged 37 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
228c151
tests: added functionality for multichain forking
Debugger022 Aug 24, 2023
7801b07
tests: added multichain functionality for borrow, rewards and reduce …
Debugger022 Aug 28, 2023
94ecdeb
tests: added multichain functionality for forking
Debugger022 Aug 30, 2023
dc60a00
refactor: moved contract addresses from json to constant ts file
Debugger022 Sep 1, 2023
51b66c9
fix: tests
Debugger022 Sep 2, 2023
d9a280b
merge branch 'develop' into VEN-1831
Debugger022 Sep 25, 2023
dbc5584
fix: resolved conflicts
Debugger022 Oct 30, 2023
3e943c3
fix: tests
Debugger022 Oct 30, 2023
e95be20
tests: added multichain tests for shortfall
Debugger022 Nov 1, 2023
e9f3a63
wip
Debugger022 Nov 1, 2023
6bdb3d5
merge branch 'develop' into VEN-1831
Debugger022 Nov 1, 2023
4f884d6
tests: added multichain for riskFund and shortfall
Debugger022 Nov 2, 2023
932081e
Merge branch 'develop' into VEN-1831
Debugger022 Nov 29, 2023
167b53c
refactor: updated addresses for sepolia to follow same implementation…
Debugger022 Dec 1, 2023
f1143ca
Merge branch 'develop' into VEN-1831
Debugger022 Dec 4, 2023
fd00e09
feat: updating deployment files
Debugger022 Dec 4, 2023
73f9c72
Merge branch 'develop' into VEN-1831
Debugger022 Jan 9, 2024
f6b23d2
feat: updating deployment files
Debugger022 Jan 9, 2024
e816ff2
Merge branch 'develop' into VEN-1831
Debugger022 Jan 10, 2024
1fade86
refactor: import address explicitly
GitGuru7 Jan 10, 2024
d109e32
refactor: function name to lowerCase
Debugger022 Jan 10, 2024
cfdcf00
feat: add ethereum addresses
Debugger022 Jan 29, 2024
9062437
Merge branch 'develop' into VEN-1831
Debugger022 Jan 29, 2024
e3aca15
refactor: pick addresses from npm packages instead of hardcoding
Debugger022 Jan 30, 2024
c0e32f7
refactor: use seplia addresses from npm package and minor refactoring
Debugger022 Jan 30, 2024
c66ea8d
Merge pull request #360 from VenusProtocol/VEN-2353
Debugger022 Jan 31, 2024
25dfd27
Merge branch 'develop' of github.com:VenusProtocol/isolated-pools int…
Debugger022 Mar 4, 2024
967dbbf
chore: add addresses for opBNB testnet and mainnet
Debugger022 Mar 6, 2024
1edf320
Merge branch 'develop' into VEN-1831
Debugger022 Apr 29, 2024
12d8536
chore: import deployments for oracle for arbitrumsepolia
Debugger022 May 2, 2024
e07270c
refactor: remove riskfund tests
Debugger022 May 2, 2024
b022b57
chore: add arbitrumsepolia addresses
Debugger022 May 2, 2024
a47277f
fix: nativeTokenGateway, liquidation and reduceReserves fork tests
Debugger022 May 2, 2024
5beeda7
fix: fork tests for all chains
Debugger022 May 4, 2024
1173de8
Merge branch 'develop' into VEN-1831
Debugger022 Jun 21, 2024
f9144a9
refactor: add imports for arbitrum one
Debugger022 Jun 21, 2024
230e80e
fix: fork tests for all networks
Debugger022 Jun 25, 2024
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ REPORT_GAS=true npx hardhat test

```

- To run fork tests add FORK_MAINNET=true and QUICK_NODE_KEY in the .env file.
- To run fork tests add FORK=true, FORKED_NETWORK and one ARCHIVE_NODE var in the .env file.

## Deployment

Expand Down
16 changes: 16 additions & 0 deletions contracts/test/Mocks/MockPriceOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ import { ProtocolShareReserve } from "@venusprotocol/protocol-reserve/contracts/
import { VToken } from "../../VToken.sol";

contract MockPriceOracle is ResilientOracleInterface {
struct TokenConfig {
/// @notice asset address
address asset;
/// @notice `oracles` stores the oracles based on their role in the following order:
/// [main, pivot, fallback],
/// It can be indexed with the corresponding enum OracleRole value
address[3] oracles;
/// @notice `enableFlagsForOracles` stores the enabled state
/// for each oracle in the same order as `oracles`
bool[3] enableFlagsForOracles;
}

mapping(address => uint256) public assetPrices;

//set price in 6 decimal precision
Expand All @@ -28,6 +40,10 @@ contract MockPriceOracle is ResilientOracleInterface {
return assetPrices[asset];
}

function getTokenConfig(address asset) external view returns (TokenConfig memory) {}

function setTokenConfig(TokenConfig memory tokenConfig) public {}

//https://compound.finance/docs/prices
function getUnderlyingPrice(address vToken) public view override returns (uint256) {
return assetPrices[VToken(vToken).underlying()];
Expand Down
52 changes: 28 additions & 24 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ extendConfig((config: HardhatConfig) => {
"node_modules/@venusprotocol/venus-protocol/deployments/sepolia",
"node_modules/@venusprotocol/protocol-reserve/deployments/sepolia",
],
bscmainnet: ["node_modules/@venusprotocol/protocol-reserve/deployments/bscmainnet"],
bscmainnet: [
"node_modules/@venusprotocol/oracle/deployments/bscmainnet",
"node_modules/@venusprotocol/venus-protocol/deployments/bscmainnet",
"node_modules/@venusprotocol/protocol-reserve/deployments/bscmainnet",
],
},
};
}
Expand Down Expand Up @@ -190,7 +194,11 @@ const config: HardhatUserConfig = {
],
},
networks: {
hardhat: isFork(),
hardhat: {
allowUnlimitedContractSize: true,
loggingEnabled: false,
live: false,
},
development: {
url: "http://127.0.0.1:8545/",
chainId: 31337,
Expand Down Expand Up @@ -259,6 +267,22 @@ const config: HardhatUserConfig = {
browserURL: "https://bscscan.com",
},
},
{
network: "sepolia",
chainId: 11155111,
urls: {
apiURL: "https://api-sepolia.etherscan.io/api",
browserURL: "https://sepolia.etherscan.io",
},
},
{
network: "ethereum",
chainId: 1,
urls: {
apiURL: "https://api.etherscan.io/api",
browserURL: "https://etherscan.io",
},
},
{
network: "opbnbtestnet",
chainId: 5611,
Expand All @@ -280,6 +304,8 @@ const config: HardhatUserConfig = {
bscmainnet: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY",
bsctestnet: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY",
opbnbtestnet: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY",
sepolia: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY",
ethereum: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY",
opbnbmainnet: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY",
},
},
Expand Down Expand Up @@ -311,26 +337,4 @@ const config: HardhatUserConfig = {
},
};

function isFork() {
return process.env.FORK === "true"
? {
allowUnlimitedContractSize: false,
loggingEnabled: false,
forking: {
url:
process.env[`ARCHIVE_NODE_${process.env.FORKED_NETWORK}`] ||
"https://data-seed-prebsc-1-s1.binance.org:8545",
blockNumber: 26349263,
},
accounts: {
accountsBalance: "1000000000000000000",
},
live: false,
}
: {
allowUnlimitedContractSize: true,
loggingEnabled: false,
live: false,
};
}
export default config;
143 changes: 67 additions & 76 deletions tests/hardhat/Fork/RewardsForkTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,62 +13,50 @@ import {
BinanceOracle__factory,
Comptroller,
Comptroller__factory,
MockToken,
MockToken__factory,
IERC20,
IERC20__factory,
RewardsDistributor,
RewardsDistributor__factory,
VToken,
VToken__factory,
} from "../../../typechain";
import { initMainnetUser, setForkBlock } from "./utils";
import { getContractAddresses, initMainnetUser, setForkBlock } from "./utils";

const { expect } = chai;
chai.use(smock.matchers);

const FORK_TESTNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bsctestnet";
const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet";
const MANTISSA_ONE = convertToUnit(1, 18);

let ADMIN: string;
let ACM: string;
let acc1: string;
let acc2: string;
let HAY: string;
let COMPTROLLER: string;
let VHAY: string;
let REWARD_DISTRIBUTOR1: string;
let BLOCK_NUMBER: number;
let BINANCE_ORACLE: string;

if (FORK_TESTNET) {
ADMIN = "0xce10739590001705f7ff231611ba4a48b2820327";
ACM = "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA";
acc1 = "0xe70898180a366F204AA529708fB8f5052ea5723c";
acc2 = "0xA4a04C2D661bB514bB8B478CaCB61145894563ef";
HAY = "0xe73774DfCD551BF75650772dC2cC56a2B6323453";
COMPTROLLER = "0x10b57706AD2345e590c2eA4DC02faef0d9f5b08B";
VHAY = "0x170d3b2da05cc2124334240fB34ad1359e34C562";
REWARD_DISTRIBUTOR1 = "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b";
BINANCE_ORACLE = "0xB58BFDCE610042311Dc0e034a80Cc7776c1D68f5";
BLOCK_NUMBER = 30908163;
}
const FORK = process.env.FORK === "true";
const FORKED_NETWORK = process.env.FORKED_NETWORK || "bscmainnet";

const {
ACM,
ACC1,
ACC2,
ADMIN,
TOKEN2,
VTOKEN2,
COMPTROLLER,
TOKEN2_HOLDER,
BINANCE_ORACLE,
REWARD_DISTRIBUTOR1,
BLOCK_NUMBER,
} = getContractAddresses(FORKED_NETWORK as string);

if (FORK_MAINNET) {
// Mainnet addresses
}
const MANTISSA_ONE = convertToUnit(1, 18);

let impersonatedTimelock: Signer;
let accessControlManager: AccessControlManager;
let token2: IERC20;
let vTOKEN2: VToken;
let comptroller: Comptroller;
let vHAY: VToken;
let hay: MockToken;
let rewardDistributor1: RewardsDistributor;
let acc1Signer: Signer;
let acc2Signer: Signer;
let token2Holder: Signer;
let comptrollerSigner: Signer;
let impersonatedTimelock: Signer;
let binanceOracle: BinanceOracle;
let mintAmount: BigNumberish;
let bswBorrowAmount: BigNumberish;
let binanceOracle: BinanceOracle;
let rewardDistributor1: RewardsDistributor;
let accessControlManager: AccessControlManager;

async function configureTimelock() {
impersonatedTimelock = await initMainnetUser(ADMIN, ethers.utils.parseUnits("2"));
Expand All @@ -92,38 +80,41 @@ async function grantPermissions() {
await tx.wait();
}

if (FORK_TESTNET || FORK_MAINNET) {
if (FORK) {
chechu marked this conversation as resolved.
Show resolved Hide resolved
describe("Rewards distributions", async () => {
mintAmount = convertToUnit("100000000", 18);
mintAmount = convertToUnit("10000", 18);
bswBorrowAmount = convertToUnit("100", 18);

async function setup() {
await setForkBlock(BLOCK_NUMBER);
await configureTimelock();

acc1Signer = await initMainnetUser(acc1, ethers.utils.parseUnits("2"));
acc2Signer = await initMainnetUser(acc2, ethers.utils.parseUnits("2"));
acc1Signer = await initMainnetUser(ACC1, ethers.utils.parseUnits("2"));
acc2Signer = await initMainnetUser(ACC2, ethers.utils.parseUnits("2"));
token2Holder = await initMainnetUser(TOKEN2_HOLDER, ethers.utils.parseUnits("2"));
comptrollerSigner = await initMainnetUser(COMPTROLLER, ethers.utils.parseUnits("2"));

hay = MockToken__factory.connect(HAY, impersonatedTimelock);
vHAY = await configureVToken(VHAY);
token2 = IERC20__factory.connect(TOKEN2, impersonatedTimelock);
vTOKEN2 = await configureVToken(VTOKEN2);
comptroller = Comptroller__factory.connect(COMPTROLLER, impersonatedTimelock);
rewardDistributor1 = RewardsDistributor__factory.connect(REWARD_DISTRIBUTOR1, impersonatedTimelock);

await grantPermissions();

await comptroller.connect(acc1Signer).enterMarkets([vHAY.address]);
await comptroller.connect(acc2Signer).enterMarkets([vHAY.address]);
await comptroller.connect(acc1Signer).enterMarkets([vTOKEN2.address]);
await comptroller.connect(acc2Signer).enterMarkets([vTOKEN2.address]);

await comptroller.setMarketSupplyCaps([vHAY.address], [convertToUnit(1, 50)]);
await comptroller.setMarketBorrowCaps([vHAY.address], [convertToUnit(1, 50)]);
await comptroller.setMarketSupplyCaps([vTOKEN2.address], [convertToUnit(1, 50)]);
await comptroller.setMarketBorrowCaps([vTOKEN2.address], [convertToUnit(1, 50)]);

binanceOracle = BinanceOracle__factory.connect(BINANCE_ORACLE, impersonatedTimelock);
await binanceOracle.connect(impersonatedTimelock).setMaxStalePeriod("HAY", 31536000);
if (FORKED_NETWORK != "sepolia") {
binanceOracle = BinanceOracle__factory.connect(BINANCE_ORACLE, impersonatedTimelock);
await binanceOracle.connect(impersonatedTimelock).setMaxStalePeriod("HAY", 31536000);
}
}

async function mintVTokens(signer: Signer, token: MockToken, vToken: VToken, amount: BigNumberish) {
await token.connect(signer).faucet(amount);
async function mintVTokens(signer: Signer, token: IERC20, vToken: VToken, amount: BigNumberish) {
await token.connect(token2Holder).transfer(await signer.getAddress(), amount);
await token.connect(signer).approve(vToken.address, amount);
await expect(vToken.connect(signer).mint(amount)).to.emit(vToken, "Mint");
}
Expand Down Expand Up @@ -159,7 +150,7 @@ if (FORK_TESTNET || FORK_MAINNET) {
vToken: VToken,
user: string,
) {
await vHAY.accrueInterest();
await vTOKEN2.accrueInterest();
const marketBorrowIndex = await vToken.borrowIndex();
const borrowerAccruedOld = await rewardDistributor.rewardTokenAccrued(user);

Expand Down Expand Up @@ -192,51 +183,51 @@ if (FORK_TESTNET || FORK_MAINNET) {
});

it("Rewards for suppliers", async function () {
await mintVTokens(acc1Signer, hay, vHAY, mintAmount);
await mintVTokens(acc1Signer, token2, vTOKEN2, mintAmount);
await mine(3000000);
await vHAY.accrueInterest();
await vTOKEN2.accrueInterest();

// Reward1 calculations for user 1
let supplierAccruedExpected = await computeSupplyRewards(rewardDistributor1, VHAY, vHAY, acc1);
let supplierAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(acc1);
let supplierAccruedExpected = await computeSupplyRewards(rewardDistributor1, VTOKEN2, vTOKEN2, ACC1);
let supplierAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(ACC1);
expect(supplierAccruedExpected).equals(supplierAccruedCurrent);

// Transfer vTokens to user 2 from user 1
const acc1Balance = await vHAY.balanceOf(acc1);
await vHAY.connect(acc1Signer).transfer(acc2, acc1Balance);
await vHAY.accrueInterest();
const acc1Balance = await vTOKEN2.balanceOf(ACC1);
await vTOKEN2.connect(acc1Signer).transfer(ACC2, acc1Balance);
await vTOKEN2.accrueInterest();

// Reward1 calculations for user 1
supplierAccruedExpected = await computeSupplyRewards(rewardDistributor1, VHAY, vHAY, acc1);
supplierAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(acc1);
supplierAccruedExpected = await computeSupplyRewards(rewardDistributor1, VTOKEN2, vTOKEN2, ACC1);
supplierAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(ACC1);
expect(supplierAccruedExpected).equals(supplierAccruedCurrent);

// Reward1 calculations for user 2
supplierAccruedExpected = await computeSupplyRewards(rewardDistributor1, VHAY, vHAY, acc2);
supplierAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(acc2);
supplierAccruedExpected = await computeSupplyRewards(rewardDistributor1, VTOKEN2, vTOKEN2, ACC2);
supplierAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(ACC2);
expect(supplierAccruedExpected).equals(supplierAccruedCurrent);
});

it("Rewards for borrowers", async function () {
await mintVTokens(acc1Signer, hay, vHAY, mintAmount);
await vHAY.connect(acc1Signer).borrow(bswBorrowAmount);
await mintVTokens(acc1Signer, token2, vTOKEN2, mintAmount);
await vTOKEN2.connect(acc1Signer).borrow(bswBorrowAmount);
await mine(3000000);
await vHAY.accrueInterest();
await vTOKEN2.accrueInterest();

// Reward1 calculations for user 1
let borrowerAccruedExpected = await computeBorrowRewards(rewardDistributor1, VHAY, vHAY, acc1);
let borrowerAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(acc1);
let borrowerAccruedExpected = await computeBorrowRewards(rewardDistributor1, VTOKEN2, vTOKEN2, ACC1);
let borrowerAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(ACC1);
expect(borrowerAccruedExpected).to.closeTo(borrowerAccruedCurrent, parseUnits("0.000000000000000079", 18));

// Repay
const borrowBalanceStored = await vHAY.borrowBalanceStored(acc1);
await hay.connect(acc1Signer).faucet(borrowBalanceStored);
await hay.connect(acc1Signer).approve(VHAY, borrowBalanceStored);
await expect(vHAY.connect(acc1Signer).repayBorrow(borrowBalanceStored)).to.emit(vHAY, "RepayBorrow");
const borrowBalanceStored = await vTOKEN2.borrowBalanceStored(ACC1);
await token2.connect(token2Holder).transfer(ACC1, borrowBalanceStored);
await token2.connect(acc1Signer).approve(VTOKEN2, borrowBalanceStored);
await expect(vTOKEN2.connect(acc1Signer).repayBorrow(borrowBalanceStored)).to.emit(vTOKEN2, "RepayBorrow");

// Reward1 calculations for user 1
borrowerAccruedExpected = await computeBorrowRewards(rewardDistributor1, VHAY, vHAY, acc1);
borrowerAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(acc1);
borrowerAccruedExpected = await computeBorrowRewards(rewardDistributor1, VTOKEN2, vTOKEN2, ACC1);
borrowerAccruedCurrent = await rewardDistributor1.rewardTokenAccrued(ACC1);
expect(borrowerAccruedExpected).to.closeTo(borrowerAccruedCurrent, parseUnits("0.000000000000000006", 18));
});
});
Expand Down
Loading
Loading