Skip to content

Commit

Permalink
WIP: refactor borrow & repay test
Browse files Browse the repository at this point in the history
  • Loading branch information
GitGuru7 committed Sep 3, 2024
1 parent 5c20e1c commit e53d3ee
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 21 deletions.
3 changes: 3 additions & 0 deletions hardhat.config.zksync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ const config: HardhatUserConfig = {
"hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol",
],
},
mocha: {
timeout: 200000000,
},
};

export default config;
41 changes: 25 additions & 16 deletions tests/hardhat/Fork/borrowAndRepayTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
WrappedNative,
WrappedNative__factory,
} from "../../../typechain";
import { getContractAddresses, initMainnetUser, setForkBlock } from "./utils";
import { getContractAddresses, initMainnetUser, mineBlocks, mineOnZksync, setForkBlock } from "./utils";

Check failure on line 23 in tests/hardhat/Fork/borrowAndRepayTest.ts

View workflow job for this annotation

GitHub Actions / Lint

'mineBlocks' is defined but never used. Allowed unused vars must match /_/u

const { expect } = chai;
chai.use(smock.matchers);
Expand Down Expand Up @@ -105,13 +105,17 @@ if (FORK) {
feed: token1Config.feed,
maxStalePeriod: BigNumber.from(1000000000),
};
const token2NewConfig = {
asset: token2Config.asset,
feed: token2Config.feed,
maxStalePeriod: BigNumber.from(1000000000),
};
await ChainlinkOracle.setTokenConfig(token1NewConfig);
await ChainlinkOracle.setTokenConfig(token2NewConfig);

// Direct price is set for ZK token
if (FORKED_NETWORK != "zksyncsepolia") {
const token2NewConfig = {
asset: token2Config.asset,
feed: token2Config.feed,
maxStalePeriod: BigNumber.from(1000000000),
};
await ChainlinkOracle.setTokenConfig(token2NewConfig);
}
}

token1 = IERC20__factory.connect(TOKEN1, impersonatedTimelock);
Expand Down Expand Up @@ -146,7 +150,6 @@ if (FORK) {
// Allocate reserves to market from ACC3 to the TOKEN2 market
await token2.connect(token2Holder).approve(vTOKEN2.address, convertToUnit(10000, 18));
await expect(vTOKEN2.connect(token2Holder).mint(convertToUnit(10000, 18))).to.emit(vTOKEN2, "Mint");

// Increase collateral for ACC
await token1.connect(token1Holder).transfer(ACC1, mintAmount);
await token1.connect(acc1Signer).approve(vTOKEN1.address, mintAmount);
Expand All @@ -159,14 +162,12 @@ if (FORK) {
it("Total Borrow Balance with Two Borrowers", async function () {
// common factors
const vTOKEN1CollateralFactor = await comptroller.markets(VTOKEN1);

await expect(vTOKEN1.connect(acc1Signer).mint(mintAmount)).to.emit(vTOKEN1, "Mint");

let exchangeRateCollateral = await vTOKEN1.exchangeRateStored();

let TOKEN1Price = await priceOracle.getUnderlyingPrice(VTOKEN1);
let TOKEN2Price = await priceOracle.getUnderlyingPrice(VTOKEN2);

let vTokenPrice = exchangeRateCollateral.mul(TOKEN1Price).div(convertToUnit(1, 18));

let weightedPriceTOKEN1 = vTokenPrice
Expand Down Expand Up @@ -197,7 +198,6 @@ if (FORK) {
expectedMintAmount = mintAmount.mul(convertToUnit(1, 18)).div(await vTOKEN1.exchangeRateStored());

expectedLiquidityAcc1 = weightedPriceTOKEN1.mul(await vTOKEN1.balanceOf(ACC1)).div(convertToUnit(1, 18));

[err, liquidity, shortfall] = await comptroller.getBorrowingPower(ACC2);

let expectedLiquidityAcc2 = weightedPriceTOKEN1.mul(expectedMintAmount).div(convertToUnit(1, 18));
Expand Down Expand Up @@ -225,7 +225,11 @@ if (FORK) {
expect(shortfall).equals(0);

// ********************************Mine 30000 blocks***********************************/
await mine(30000);
if (FORKED_NETWORK == "zksyncsepolia") {
await mineOnZksync(30000);
} else {
await mine(30000);
}
await vTOKEN2.accrueInterest();
let borrowIndexCurrent = await vTOKEN2.borrowIndex();

Expand All @@ -246,8 +250,14 @@ if (FORK) {
expect(shortfall).equals(0);

// ********************************Mine 300000 blocks***********************************/
await mine(300000);
if (FORKED_NETWORK == "zksyncsepolia") {
await mineOnZksync(30000);
} else {
await mine(300000);
}

await vTOKEN2.accrueInterest();

borrowIndexCurrent = await vTOKEN2.borrowIndex();

// Change borrow balance of ACC1
Expand All @@ -257,17 +267,14 @@ if (FORK) {
// Change borrow balance of ACC2
borrowBalanceStored = await vTOKEN2.borrowBalanceStored(ACC2);
expect(borrowIndexCurrent.mul(TOKEN2BorrowAmount).div(borrowIndexAcc2Prev)).equals(borrowBalanceStored);

// *************************Repay ACC2**************************************************/

// Allocate some funds to repay debt
await vTOKEN2.accrueInterest();
borrowBalanceStored = await vTOKEN2.borrowBalanceStored(ACC2);

await token2.connect(token2Holder).transfer(ACC2, borrowBalanceStored.add(convertToUnit(1, 20)));
await token2.connect(acc2Signer).approve(vTOKEN2.address, borrowBalanceStored.add(convertToUnit(1, 20)));
await vTOKEN2.connect(acc2Signer).repayBorrow(borrowBalanceStored.add(convertToUnit(1, 20)));

// Full debt repaid acc2
borrowBalanceStored = await vTOKEN2.borrowBalanceStored(ACC2);
expect(borrowBalanceStored).equals(0);
Expand All @@ -276,7 +283,9 @@ if (FORK) {
await vTOKEN2.accrueInterest();
borrowIndexCurrent = await vTOKEN2.borrowIndex();
borrowBalanceStored = await vTOKEN2.borrowBalanceStored(ACC1);

expect(borrowIndexCurrent.mul(TOKEN2BorrowAmount).div(borrowIndexAcc1Prev)).equals(borrowBalanceStored);
console.log("end", borrowIndexCurrent.mul(TOKEN2BorrowAmount).div(borrowIndexAcc1Prev), borrowBalanceStored);
});

it("Attempt to borrow over set cap", async function () {
Expand Down
4 changes: 2 additions & 2 deletions tests/hardhat/Fork/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ export const contractAddresses = {
CHAINLINK_ORACLE: OracleZksyncsepolia.contracts.ChainlinkOracle.address,
TOKEN1: "0x53F7e72C7ac55b44c7cd73cC13D4EF4b121678e6", // WETH
TOKEN2: "0x8A2E9048F5d658E88D6eD89DdD1F3B5cA0250B9F", // ZK
TOKEN1_HOLDER: "0xE0B015E54d54fc84a6cB9B666099c46adE9335FF",
TOKEN2_HOLDER: "0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E",
TOKEN1_HOLDER: "0xEF4B807f9442b0EbD8a051C2cAEA81e5e7BAcFBD",
TOKEN2_HOLDER: "0xE8C6Cf867CF962d289305ECE9b139a4116674541",
ACC1: "0x32B701d3957fee432664cFA57FB44b0fE8496659",
ACC2: "0xB09F16F625B363875e39ADa56C03682088471523",
ACC3: "0x4A2339eE9c4fD4c99DE1d3AeB513B53ab42Db5ca",
Expand Down
51 changes: 48 additions & 3 deletions tests/hardhat/Fork/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export const forking = (blockNumber: number, fn: () => Promise<void>) => {
})();
};

export async function setForkBlock(blockNumber: number) {
export async function setForkBlock(_blockNumber: number) {
// const _blockNumber = config.networks.hardhat.zksync ? _blockNumber.toString(16) : _blockNumber;
const blockNumber = _blockNumber.toString(16);
await network.provider.request({
method: "hardhat_reset",
params: [
Expand All @@ -35,7 +37,50 @@ export async function setForkBlock(blockNumber: number) {
}

export const initMainnetUser = async (user: string, balance: NumberLike) => {
await impersonateAccount(user);
await setBalance(user, balance);
await network.provider.send("hardhat_impersonateAccount", [user]);
const balanceHex = toRpcQuantity(balance);
await network.provider.send("hardhat_setBalance", [user, balanceHex]);

return ethers.getSigner(user);
};

const toRpcQuantity = (x: NumberLike): string => {
let hex: string;
if (typeof x === "number" || typeof x === "bigint") {
// TODO: check that number is safe
hex = `0x${x.toString(16)}`;
} else if (typeof x === "string") {
if (!x.startsWith("0x")) {
throw new Error("Only 0x-prefixed hex-encoded strings are accepted");
}
hex = x;
} else if ("toHexString" in x) {
hex = x.toHexString();
} else if ("toString" in x) {
hex = x.toString(16);
} else {
throw new Error(`${x as any} cannot be converted to an RPC quantity`);
}

if (hex === "0x0") return hex;

return hex.startsWith("0x") ? hex.replace(/0x0+/, "0x") : `0x${hex}`;
};

export const mineOnZksync = async (blocks: number) => {
const blockTimestamp = (await ethers.provider.getBlock("latest")).timestamp;
const targetTimestamp = blockTimestamp + blocks;
await ethers.provider.send("evm_setNextBlockTimestamp", [targetTimestamp]);
await mineBlocks();
};

export async function mineBlocks(blocks: NumberLike = 1, options: { interval?: NumberLike } = {}): Promise<void> {
const interval = options.interval ?? 1;
const blocksHex = toRpcQuantity(blocks);
const intervalHex = toRpcQuantity(interval);

await network.provider.request({
method: "hardhat_mine",
params: [blocksHex, intervalHex],
});
}

0 comments on commit e53d3ee

Please sign in to comment.