mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
395 lines
20 KiB
JavaScript
395 lines
20 KiB
JavaScript
const { expect } = require("chai");
|
|
const hre = require("hardhat");
|
|
const { web3, deployments, waffle, ethers } = hre;
|
|
const { provider, deployContract } = waffle
|
|
|
|
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
|
|
const buildDSAv2 = require("../../scripts/buildDSAv2")
|
|
const encodeSpells = require("../../scripts/encodeSpells.js")
|
|
const getMasterSigner = require("../../scripts/getMasterSigner")
|
|
|
|
const addresses = require("../../scripts/constant/addresses");
|
|
const abis = require("../../scripts/constant/abis");
|
|
const constants = require("../../scripts/constant/constant");
|
|
const tokens = require("../../scripts/constant/tokens");
|
|
|
|
const contracts = require("./notional.contracts");
|
|
const helpers = require("./notional.helpers");
|
|
|
|
const connectV2NotionalArtifacts = require("../../artifacts/contracts/mainnet/connectors/notional/main.sol/ConnectV2Notional.json");
|
|
const { BigNumber } = require("ethers");
|
|
|
|
const DAI_WHALE = "0x6dfaf865a93d3b0b5cfd1b4db192d1505676645b";
|
|
const CDAI_WHALE = "0x33b890d6574172e93e58528cd99123a88c0756e9";
|
|
const ETH_WHALE = "0x7D24796f7dDB17d73e8B1d0A3bbD103FBA2cb2FE";
|
|
const CETH_WHALE = "0x1a1cd9c606727a7400bb2da6e4d5c70db5b4cade";
|
|
const MaxUint96 = BigNumber.from("0xffffffffffffffffffffffff");
|
|
const DEPOSIT_ASSET = 1;
|
|
const DEPOSIT_UNDERLYING = 2;
|
|
const DEPOSIT_ASSET_MINT_NTOKEN = 3;
|
|
const DEPOSIT_UNDERLYING_MINT_NTOKEN = 4;
|
|
const ETH_ID = 1;
|
|
const DAI_ID = 2;
|
|
const MARKET_3M = 1;
|
|
|
|
describe("Notional", function () {
|
|
const connectorName = "NOTIONAL-TEST-A"
|
|
|
|
let dsaWallet0
|
|
let masterSigner;
|
|
let instaConnectorsV2;
|
|
let connector;
|
|
let notional;
|
|
let daiToken;
|
|
let cdaiToken;
|
|
let cethToken;
|
|
let daiWhale;
|
|
let cdaiWhale;
|
|
let cethWhale;
|
|
|
|
const wallets = provider.getWallets()
|
|
const [wallet0, wallet1, wallet2, wallet3] = wallets
|
|
beforeEach(async () => {
|
|
await hre.network.provider.request({
|
|
method: "hardhat_reset",
|
|
params: [
|
|
{
|
|
forking: {
|
|
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
|
|
blockNumber: 13798624,
|
|
},
|
|
},
|
|
],
|
|
});
|
|
await hre.network.provider.request({
|
|
method: "hardhat_impersonateAccount",
|
|
params: [DAI_WHALE]
|
|
})
|
|
await hre.network.provider.request({
|
|
method: "hardhat_impersonateAccount",
|
|
params: [CDAI_WHALE]
|
|
})
|
|
await hre.network.provider.request({
|
|
method: "hardhat_impersonateAccount",
|
|
params: [ETH_WHALE]
|
|
})
|
|
await hre.network.provider.request({
|
|
method: "hardhat_impersonateAccount",
|
|
params: [CETH_WHALE]
|
|
})
|
|
|
|
masterSigner = await getMasterSigner(wallet3)
|
|
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
|
connector = await deployAndEnableConnector({
|
|
connectorName,
|
|
contractArtifact: connectV2NotionalArtifacts,
|
|
signer: masterSigner,
|
|
connectors: instaConnectorsV2
|
|
})
|
|
notional = new ethers.Contract(
|
|
contracts.NOTIONAL_CONTRACT_ADDRESS,
|
|
contracts.NOTIONAL_CONTRACT_ABI,
|
|
ethers.provider
|
|
);
|
|
daiToken = new ethers.Contract(
|
|
contracts.DAI_TOKEN_ADDRESS,
|
|
contracts.ERC20_TOKEN_ABI,
|
|
ethers.provider
|
|
);
|
|
daiWhale = await ethers.getSigner(DAI_WHALE);
|
|
cdaiToken = new ethers.Contract(
|
|
contracts.CDAI_TOKEN_ADDRESS,
|
|
contracts.ERC20_TOKEN_ABI,
|
|
ethers.provider
|
|
);
|
|
cdaiWhale = await ethers.getSigner(CDAI_WHALE);
|
|
cethToken = new ethers.Contract(
|
|
contracts.CETH_TOKEN_ADDRESS,
|
|
contracts.ERC20_TOKEN_ABI,
|
|
ethers.provider
|
|
);
|
|
cethWhale = await ethers.getSigner(CETH_WHALE);
|
|
weth = new ethers.Contract(
|
|
contracts.WETH_TOKEN_ADDRESS,
|
|
contracts.ERC20_TOKEN_ABI,
|
|
ethers.provider
|
|
);
|
|
dsaWallet0 = await buildDSAv2(wallet0.address)
|
|
});
|
|
|
|
describe("Deposit Tests", function () {
|
|
it("test_deposit_ETH_underlying", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("1");
|
|
await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, ETH_ID, depositAmount, true);
|
|
const bal = await notional.callStatic.getAccountBalance(ETH_ID, dsaWallet0.address);
|
|
// balance in internal asset precision
|
|
expect(bal[0], "expect at least 49 cETH").to.be.gte(ethers.utils.parseUnits("4900000000", 0));
|
|
expect(bal[1], "expect 0 nETH").to.be.equal(ethers.utils.parseUnits("0", 0));
|
|
});
|
|
|
|
it("test_deposit_ETH_asset", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1", 8);
|
|
await cethToken.connect(cethWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, ETH_ID, depositAmount, false);
|
|
const bal = await notional.callStatic.getAccountBalance(ETH_ID, dsaWallet0.address);
|
|
// balance in internal asset precision
|
|
expect(bal[0], "expect at least 1 cETH").to.be.gte(ethers.utils.parseUnits("100000000", 0));
|
|
expect(bal[1], "expect 0 nETH").to.be.equal(ethers.utils.parseUnits("0", 0));
|
|
});
|
|
|
|
it("test_deposit_DAI_underlying", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000", 18);
|
|
await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, true);
|
|
const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address);
|
|
// balance in internal asset precision
|
|
expect(bal[0], "expect at least 45000 cDAI").to.be.gte(ethers.utils.parseUnits("4500000000000", 0));
|
|
expect(bal[1], "expect 0 nDAI").to.be.equal(ethers.utils.parseUnits("0", 0));
|
|
});
|
|
|
|
it("test_deposit_DAI_asset", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000", 8);
|
|
await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false);
|
|
const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address);
|
|
// balance in internal asset precision
|
|
expect(bal[0], "expect at least 1000 cDAI").to.be.gte(ethers.utils.parseUnits("100000000000", 0));
|
|
expect(bal[1], "expect 0 nDAI").to.be.equal(ethers.utils.parseUnits("0", 0));
|
|
});
|
|
|
|
it("test_deposit_ETH_underlying_and_mint_ntoken", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("1");
|
|
await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, ETH_ID, depositAmount, true);
|
|
const bal = await notional.callStatic.getAccountBalance(ETH_ID, dsaWallet0.address);
|
|
expect(bal[0], "expect 0 balance").to.be.equal(ethers.utils.parseUnits("0", 0));
|
|
expect(bal[1], "expect at least 49 nETH").to.be.gte(ethers.utils.parseUnits("4900000000", 0));
|
|
});
|
|
});
|
|
|
|
describe("Lend Tests", function () {
|
|
it("test_deposit_ETH_underlying_and_lend", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("10");
|
|
await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, ETH_ID, true, depositAmount, MARKET_3M, 9e8, 0);
|
|
const portfolio = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(portfolio.length, "expect 1 lending position").to.be.equal(1);
|
|
expect(portfolio[0][3], "expect 9 fETH").to.be.gte(ethers.utils.parseUnits("900000000", 0));
|
|
});
|
|
|
|
it("test_deposit_ETH_asset_and_lend", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1", 8);
|
|
await cethToken.connect(cethWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, ETH_ID, false, depositAmount, MARKET_3M, 0.01e8, 0);
|
|
const portfolio = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(portfolio.length, "expect 1 lending position").to.be.equal(1);
|
|
expect(portfolio[0][3], "expect 0.01 fETH").to.be.gte(ethers.utils.parseUnits("1000000", 0));
|
|
});
|
|
|
|
it("test_deposit_DAI_underlying_and_lend", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000", 18);
|
|
await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, DAI_ID, true, depositAmount, MARKET_3M, 100e8, 0);
|
|
const portfolio = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(portfolio.length, "expect 1 lending position").to.be.equal(1);
|
|
expect(portfolio[0][3], "expect 100 fDAI").to.be.gte(ethers.utils.parseUnits("10000000000", 0));
|
|
});
|
|
|
|
it("test_deposit_DAI_asset_and_lend", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000", 8);
|
|
await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, DAI_ID, false, depositAmount, MARKET_3M, 10e8, 0);
|
|
const portfolio = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(portfolio.length, "expect 1 lending position").to.be.equal(1);
|
|
expect(portfolio[0][3], "expect 10 fDAI").to.be.gte(ethers.utils.parseUnits("1000000000", 0));
|
|
});
|
|
|
|
it("test_withdraw_lend_ETH", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("10");
|
|
await helpers.depositAndLend(dsaWallet0, wallet0, wallet1, ETH_ID, true, depositAmount, MARKET_3M, 9e8, 0);
|
|
const before = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(before.length, "expect 1 lending position").to.be.equal(1);
|
|
expect(before[0][3], "expect 9 fETH").to.be.gte(ethers.utils.parseUnits("900000000", 0));
|
|
await helpers.withdrawLend(dsaWallet0, wallet0, wallet1, ETH_ID, MARKET_3M, 9e8, 0);
|
|
const after = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(after.length, "expect lending position to be closed out").to.be.equal(0);
|
|
});
|
|
});
|
|
|
|
describe("Borrow Tests", function () {
|
|
it("test_deposit_ETH_and_borrow_DAI_underlying", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("10");
|
|
await helpers.depositCollateralBorrowAndWithdraw(
|
|
dsaWallet0, wallet0, wallet1, ETH_ID, DEPOSIT_UNDERLYING, depositAmount, DAI_ID, MARKET_3M, 1000e8, 0, true
|
|
);
|
|
expect(
|
|
await daiToken.balanceOf(dsaWallet0.address),
|
|
"expect DSA wallet to contain borrowed balance minus fees"
|
|
).to.be.gte(ethers.utils.parseEther("990"));
|
|
});
|
|
|
|
it("test_deposit_ETH_and_borrow_DAI_asset", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("10");
|
|
await helpers.depositCollateralBorrowAndWithdraw(
|
|
dsaWallet0, wallet0, wallet1, ETH_ID, DEPOSIT_UNDERLYING, depositAmount, DAI_ID, MARKET_3M, 1000e8, 0, false
|
|
);
|
|
expect(
|
|
await cdaiToken.balanceOf(dsaWallet0.address),
|
|
"expect DSA wallet to contain borrowed balance minus fees"
|
|
).to.be.gte(ethers.utils.parseUnits("4500000000000", 0));
|
|
});
|
|
|
|
it("test_deposit_DAI_underlying_and_borrow_ETH", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("20000", 18);
|
|
await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollateralBorrowAndWithdraw(
|
|
dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_UNDERLYING, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true
|
|
);
|
|
expect(
|
|
await ethers.provider.getBalance(dsaWallet0.address),
|
|
"expect DSA wallet to contain borrowed balance minus fees"
|
|
).to.be.gte(ethers.utils.parseEther("0.99"));
|
|
});
|
|
|
|
it("test_deposit_DAI_asset_and_borrow_ETH", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000000", 8);
|
|
await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollateralBorrowAndWithdraw(
|
|
dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_ASSET, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true
|
|
);
|
|
expect(
|
|
await ethers.provider.getBalance(dsaWallet0.address),
|
|
"expect DSA wallet to contain borrowed balance minus fees"
|
|
).to.be.gte(ethers.utils.parseEther("0.99"));
|
|
});
|
|
|
|
it("test_mint_nDAI_underlying_and_borrow_ETH", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("20000", 18);
|
|
await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollateralBorrowAndWithdraw(
|
|
dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_UNDERLYING_MINT_NTOKEN, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true
|
|
);
|
|
expect(
|
|
await ethers.provider.getBalance(dsaWallet0.address),
|
|
"expect DSA wallet to contain borrowed balance minus fees"
|
|
).to.be.gte(ethers.utils.parseEther("0.99"));
|
|
});
|
|
|
|
it("test_mint_nDAI_asset_and_borrow_ETH", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000000", 8);
|
|
await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollateralBorrowAndWithdraw(
|
|
dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_ASSET_MINT_NTOKEN, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true
|
|
);
|
|
expect(
|
|
await ethers.provider.getBalance(dsaWallet0.address),
|
|
"expect DSA wallet to contain borrowed balance minus fees"
|
|
).to.be.gte(ethers.utils.parseEther("0.99"));
|
|
});
|
|
});
|
|
|
|
describe("Withdraw Tests", function () {
|
|
it("test_withdraw_ETH_underlying", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("1");
|
|
await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, 1, depositAmount, true);
|
|
await helpers.withdrawCollateral(dsaWallet0, wallet0, wallet1, 1, ethers.constants.MaxUint256, true);
|
|
expect(
|
|
await ethers.provider.getBalance(dsaWallet0.address),
|
|
"expect DSA wallet to contain underlying funds"
|
|
).to.be.gte(ethers.utils.parseEther("10"));
|
|
});
|
|
|
|
it("test_withdraw_ETH_asset", async function () {
|
|
await wallet0.sendTransaction({
|
|
to: dsaWallet0.address,
|
|
value: ethers.utils.parseEther("10")
|
|
});
|
|
const depositAmount = ethers.utils.parseEther("1");
|
|
await helpers.depositCollteral(dsaWallet0, wallet0, wallet1, ETH_ID, depositAmount, true);
|
|
await helpers.withdrawCollateral(dsaWallet0, wallet0, wallet1, ETH_ID, ethers.constants.MaxUint256, false);
|
|
expect(
|
|
await cethToken.balanceOf(dsaWallet0.address),
|
|
"expect DSA wallet to contain cToken funds"
|
|
).to.be.gte(ethers.utils.parseUnits("4900000000", 0));
|
|
});
|
|
|
|
it("test_redeem_DAI_raw", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000", 8);
|
|
await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false);
|
|
await helpers.redeemNTokenRaw(dsaWallet0, wallet0, wallet1, DAI_ID, true, MaxUint96)
|
|
const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address);
|
|
expect(bal[0], "expect cDAI balance after redemption").to.be.gte(ethers.utils.parseUnits("99000000000", 0));
|
|
expect(bal[1], "expect 0 nDAI").to.be.equal(ethers.utils.parseEther("0"));
|
|
});
|
|
|
|
it("test_redeem_DAI_and_withdraw_redeem", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000", 8);
|
|
await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false);
|
|
await helpers.redeemNTokenAndWithdraw(dsaWallet0, wallet0, wallet1, DAI_ID, MaxUint96, ethers.constants.MaxUint256, true);
|
|
const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address);
|
|
expect(bal[0], "expect 0 cDAI balance").to.be.equal(ethers.utils.parseEther("0"));
|
|
expect(bal[1], "expect 0 nDAI balance").to.be.equal(ethers.utils.parseEther("0"));
|
|
});
|
|
|
|
it("test_redeem_DAI_and_withdraw_no_redeem", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("1000", 8);
|
|
await cdaiToken.connect(cdaiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, DAI_ID, depositAmount, false);
|
|
expect(await cdaiToken.balanceOf(dsaWallet0.address)).to.be.equal(ethers.utils.parseEther("0"));
|
|
await helpers.redeemNTokenAndWithdraw(dsaWallet0, wallet0, wallet1, DAI_ID, MaxUint96, ethers.constants.MaxUint256, false);
|
|
const bal = await notional.callStatic.getAccountBalance(DAI_ID, dsaWallet0.address);
|
|
expect(bal[0], "expect 0 cDAI balance").to.be.equal(ethers.utils.parseEther("0"));
|
|
expect(bal[1], "expect 0 nDAI balance").to.be.equal(ethers.utils.parseEther("0"));
|
|
expect(
|
|
await cdaiToken.balanceOf(dsaWallet0.address),
|
|
"expect DSA wallet to contain cToken funds"
|
|
).to.be.gte(ethers.utils.parseUnits("99000000000", 0));
|
|
});
|
|
|
|
it("test_redeem_DAI_and_deleverage", async function () {
|
|
const depositAmount = ethers.utils.parseUnits("20000", 18);
|
|
await daiToken.connect(daiWhale).transfer(dsaWallet0.address, depositAmount);
|
|
await helpers.depositCollateralBorrowAndWithdraw(
|
|
dsaWallet0, wallet0, wallet1, DAI_ID, DEPOSIT_UNDERLYING, depositAmount, ETH_ID, MARKET_3M, 1e8, 0, true
|
|
);
|
|
const bal = await ethers.provider.getBalance(dsaWallet0.address);
|
|
await helpers.depositAndMintNToken(dsaWallet0, wallet0, wallet1, ETH_ID, bal, true);
|
|
const before = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(before.length, "expect 1 fDAI debt position").to.be.equal(1);
|
|
expect(before[0][3], "expect fDAI debt position to equal borrow amount").to.be.lte(ethers.utils.parseUnits("-100000000", 0));
|
|
await helpers.redeemNTokenAndDeleverage(dsaWallet0, wallet0, wallet1, ETH_ID, MaxUint96, MARKET_3M, 0.98e8, 0);
|
|
const after = await notional.getAccountPortfolio(dsaWallet0.address);
|
|
expect(after.length, "expect 1 fDAI debt position after deleverage").to.be.equal(1);
|
|
expect(after[0][3], "expect fDAI debt balance to go down after deleverage").to.be.lte(ethers.utils.parseUnits("-2000000", 0));
|
|
});
|
|
});
|
|
});
|