mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
wip: deposit tests
This commit is contained in:
parent
76ebe50729
commit
67004ca16d
133
test/polygon/mstable/mstable.helpers.ts
Normal file
133
test/polygon/mstable/mstable.helpers.ts
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
import hre, { ethers } from "hardhat";
|
||||||
|
import { IERC20Minimal__factory } from "../../../typechain";
|
||||||
|
import { BigNumber as BN } from "ethers";
|
||||||
|
|
||||||
|
const DEAD_ADDRESS = "0x0000000000000000000000000000000000000001";
|
||||||
|
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
||||||
|
const DEFAULT_DECIMALS = 18;
|
||||||
|
|
||||||
|
interface TokenData {
|
||||||
|
tokenAddress: string;
|
||||||
|
tokenWhaleAddress?: string;
|
||||||
|
feederPool?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getToken = (tokenSymbol: string): TokenData => {
|
||||||
|
switch (tokenSymbol) {
|
||||||
|
case "mUSD":
|
||||||
|
return {
|
||||||
|
tokenAddress: "0xe840b73e5287865eec17d250bfb1536704b43b21",
|
||||||
|
tokenWhaleAddress: "0x4393b9c542bf79e5235180d6da1915c0f9bc02c3"
|
||||||
|
};
|
||||||
|
|
||||||
|
case "DAI":
|
||||||
|
return {
|
||||||
|
tokenAddress: "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063",
|
||||||
|
tokenWhaleAddress: "0x49854708A8c42eEB837A97Dd97D597890CEb1334"
|
||||||
|
};
|
||||||
|
case "imUSD":
|
||||||
|
return {
|
||||||
|
tokenAddress: "0x5290Ad3d83476CA6A2b178Cd9727eE1EF72432af"
|
||||||
|
};
|
||||||
|
|
||||||
|
case "imUSDVault":
|
||||||
|
return {
|
||||||
|
tokenAddress: "0x32aBa856Dc5fFd5A56Bcd182b13380e5C855aa29"
|
||||||
|
};
|
||||||
|
|
||||||
|
case "FRAX":
|
||||||
|
return {
|
||||||
|
tokenAddress: "0x104592a158490a9228070E0A8e5343B499e125D0",
|
||||||
|
tokenWhaleAddress: "0xAE0f77C239f72da36d4dA20a4bBdaAe4Ca48e03F",
|
||||||
|
feederPool: "0xb30a907084ac8a0d25dddab4e364827406fd09f0"
|
||||||
|
};
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error(`Token ${tokenSymbol} not supported`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendToken = async (token: string, amount: any, from: string, to: string): Promise<any> => {
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_impersonateAccount",
|
||||||
|
params: [from]
|
||||||
|
});
|
||||||
|
const [signer] = await ethers.getSigners();
|
||||||
|
const sender = hre.ethers.provider.getSigner(from);
|
||||||
|
|
||||||
|
await signer.sendTransaction({
|
||||||
|
to: from,
|
||||||
|
value: ethers.utils.parseEther("1")
|
||||||
|
});
|
||||||
|
|
||||||
|
return await IERC20Minimal__factory.connect(token, sender).transfer(to, amount);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fundWallet = async (token: string, amount: any, to: string) => {
|
||||||
|
const { tokenAddress, tokenWhaleAddress } = getToken(token);
|
||||||
|
await sendToken(tokenAddress, amount, tokenWhaleAddress!, to);
|
||||||
|
};
|
||||||
|
|
||||||
|
const calcMinOut = (amount: BN, slippage: number): BN => {
|
||||||
|
const value = simpleToExactAmount(1 - slippage);
|
||||||
|
const minOut = amount.mul(value).div(ethers.BigNumber.from(10).pow(DEFAULT_DECIMALS));
|
||||||
|
return minOut;
|
||||||
|
};
|
||||||
|
|
||||||
|
const simpleToExactAmount = (amount: number | string | BN, decimals: number | BN = DEFAULT_DECIMALS): BN => {
|
||||||
|
// Code is largely lifted from the guts of web3 toWei here:
|
||||||
|
// https://github.com/ethjs/ethjs-unit/blob/master/src/index.js
|
||||||
|
let amountString = amount.toString();
|
||||||
|
const decimalsBN = BN.from(decimals);
|
||||||
|
|
||||||
|
if (decimalsBN.gt(100)) {
|
||||||
|
throw new Error(`Invalid decimals amount`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const scale = BN.from(10).pow(decimals);
|
||||||
|
const scaleString = scale.toString();
|
||||||
|
|
||||||
|
// Is it negative?
|
||||||
|
const negative = amountString.substring(0, 1) === "-";
|
||||||
|
if (negative) {
|
||||||
|
amountString = amountString.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amountString === ".") {
|
||||||
|
throw new Error(`Error converting number ${amountString} to precise unit, invalid value`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split it into a whole and fractional part
|
||||||
|
// eslint-disable-next-line prefer-const
|
||||||
|
let [whole, fraction, ...rest] = amountString.split(".");
|
||||||
|
if (rest.length > 0) {
|
||||||
|
throw new Error(`Error converting number ${amountString} to precise unit, too many decimal points`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!whole) {
|
||||||
|
whole = "0";
|
||||||
|
}
|
||||||
|
if (!fraction) {
|
||||||
|
fraction = "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fraction.length > scaleString.length - 1) {
|
||||||
|
throw new Error(`Error converting number ${amountString} to precise unit, too many decimal places`);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fraction.length < scaleString.length - 1) {
|
||||||
|
fraction += "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
const wholeBN = BN.from(whole);
|
||||||
|
const fractionBN = BN.from(fraction);
|
||||||
|
let result = wholeBN.mul(scale).add(fractionBN);
|
||||||
|
|
||||||
|
if (negative) {
|
||||||
|
result = result.mul("-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { fundWallet, getToken, simpleToExactAmount, DEAD_ADDRESS, ZERO_ADDRESS, calcMinOut };
|
197
test/polygon/mstable/mstable.test.ts
Normal file
197
test/polygon/mstable/mstable.test.ts
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
import { expect } from "chai";
|
||||||
|
import hre from "hardhat";
|
||||||
|
const { web3, deployments, waffle, ethers } = hre;
|
||||||
|
const { provider, deployContract } = waffle;
|
||||||
|
|
||||||
|
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||||
|
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||||
|
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||||
|
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||||
|
import { addLiquidity } from "../../../scripts/tests/addLiquidity";
|
||||||
|
|
||||||
|
import { addresses } from "../../../scripts/tests/polygon/addresses";
|
||||||
|
import { abis } from "../../../scripts/constant/abis";
|
||||||
|
import { tokens } from "../../../scripts/tests/polygon/tokens";
|
||||||
|
import type { Signer, Contract, BigNumber } from "ethers";
|
||||||
|
|
||||||
|
import { ConnectV2mStable__factory, IERC20Minimal__factory, IERC20Minimal } from "../../../typechain";
|
||||||
|
|
||||||
|
import { fundWallet, getToken, simpleToExactAmount, DEAD_ADDRESS, calcMinOut } from "./mstable.helpers";
|
||||||
|
|
||||||
|
describe("MStable", async () => {
|
||||||
|
const connectorName = "MStable";
|
||||||
|
|
||||||
|
let dsaWallet0: Contract;
|
||||||
|
let masterSigner: Signer;
|
||||||
|
let instaConnectorsV2: Contract;
|
||||||
|
let connector: Contract;
|
||||||
|
|
||||||
|
let mUsdToken: IERC20Minimal = IERC20Minimal__factory.connect(getToken("mUSD").tokenAddress, provider);
|
||||||
|
let daiToken: IERC20Minimal = IERC20Minimal__factory.connect(getToken("DAI").tokenAddress, provider);
|
||||||
|
let fraxToken: IERC20Minimal = IERC20Minimal__factory.connect(getToken("FRAX").tokenAddress, provider);
|
||||||
|
let imUsdToken: IERC20Minimal = IERC20Minimal__factory.connect(getToken("imUSD").tokenAddress, provider);
|
||||||
|
let imUsdVault: IERC20Minimal = IERC20Minimal__factory.connect(getToken("imUSDVault").tokenAddress, provider);
|
||||||
|
|
||||||
|
const wallets = provider.getWallets();
|
||||||
|
const [wallet0, wallet1, wallet2, wallet3] = wallets;
|
||||||
|
|
||||||
|
const toEther = (amount: BigNumber) => ethers.utils.formatEther(amount);
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await hre.network.provider.request({
|
||||||
|
method: "hardhat_reset",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
forking: {
|
||||||
|
// @ts-ignore
|
||||||
|
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
|
||||||
|
blockNumber: 23059414
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
masterSigner = await getMasterSigner();
|
||||||
|
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||||
|
connector = await deployAndEnableConnector({
|
||||||
|
connectorName,
|
||||||
|
contractArtifact: ConnectV2mStable__factory,
|
||||||
|
signer: masterSigner,
|
||||||
|
connectors: instaConnectorsV2
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Connector address", connector.address);
|
||||||
|
});
|
||||||
|
it("should deploy", async () => {
|
||||||
|
expect(instaConnectorsV2.address).to.be.properAddress;
|
||||||
|
expect(connector.address).to.be.properAddress;
|
||||||
|
expect(await masterSigner.getAddress()).to.be.properAddress;
|
||||||
|
});
|
||||||
|
describe("DSA wallet", async () => {
|
||||||
|
it("Should build DSA v2", async () => {
|
||||||
|
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||||
|
expect(dsaWallet0.address).to.be.properAddress;
|
||||||
|
});
|
||||||
|
it("Deposit ETH and tokens into DSA Wallet", async () => {
|
||||||
|
await wallet0.sendTransaction({
|
||||||
|
to: dsaWallet0.address,
|
||||||
|
value: simpleToExactAmount(10)
|
||||||
|
});
|
||||||
|
|
||||||
|
const fundAmount = simpleToExactAmount(10000);
|
||||||
|
|
||||||
|
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||||
|
|
||||||
|
await fundWallet("mUSD", fundAmount, dsaWallet0.address);
|
||||||
|
await fundWallet("DAI", fundAmount, dsaWallet0.address);
|
||||||
|
await fundWallet("FRAX", fundAmount, dsaWallet0.address);
|
||||||
|
|
||||||
|
expect(await mUsdToken.balanceOf(dsaWallet0.address)).to.be.gte(fundAmount);
|
||||||
|
expect(await daiToken.balanceOf(dsaWallet0.address)).to.be.gte(fundAmount);
|
||||||
|
expect(await fraxToken.balanceOf(dsaWallet0.address)).to.be.gte(fundAmount);
|
||||||
|
|
||||||
|
// No deposits prior
|
||||||
|
expect(await imUsdToken.balanceOf(dsaWallet0.address)).to.be.eq(0);
|
||||||
|
expect(await imUsdVault.balanceOf(dsaWallet0.address)).to.be.eq(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Main", async () => {
|
||||||
|
it("Should deposit mUSD to Vault successfully", async () => {
|
||||||
|
const depositAmount = simpleToExactAmount(100);
|
||||||
|
|
||||||
|
console.log(dsaWallet0.address);
|
||||||
|
|
||||||
|
const mUsdBalanceBefore = await mUsdToken.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("mUSD balance before: ", toEther(mUsdBalanceBefore));
|
||||||
|
|
||||||
|
const imUsdVaultBalanceBefore = await imUsdVault.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("imUSD Vault balance before: ", toEther(imUsdVaultBalanceBefore));
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: [mUsdToken.address, depositAmount]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), DEAD_ADDRESS);
|
||||||
|
|
||||||
|
const mUsdBalanceAfter = await mUsdToken.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("mUSD balance after: ", toEther(mUsdBalanceAfter));
|
||||||
|
|
||||||
|
const imUsdBalance = await imUsdToken.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("imUSD balance: ", toEther(imUsdBalance));
|
||||||
|
|
||||||
|
const imUsdVaultBalance = await imUsdVault.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("imUSD Vault balance: ", toEther(imUsdVaultBalance));
|
||||||
|
|
||||||
|
// Should have something in the vault but no imUSD
|
||||||
|
expect(await imUsdToken.balanceOf(dsaWallet0.address)).to.be.eq(0);
|
||||||
|
expect(await imUsdVault.balanceOf(dsaWallet0.address)).to.be.gt(0);
|
||||||
|
expect(mUsdBalanceAfter).to.eq(mUsdBalanceBefore.sub(depositAmount));
|
||||||
|
});
|
||||||
|
it("Should deposit DAI to Vault successfully (mUSD bAsset)", async () => {
|
||||||
|
const depositAmount = simpleToExactAmount(100);
|
||||||
|
const minOut = calcMinOut(depositAmount, 0.02);
|
||||||
|
|
||||||
|
const daiBalanceBefore = await daiToken.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("DAI balance before: ", toEther(daiBalanceBefore));
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: [daiToken.address, depositAmount, minOut]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const imUsdVaultBalanceBefore = await imUsdVault.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("imUSD Vault balance before: ", toEther(imUsdVaultBalanceBefore));
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), DEAD_ADDRESS);
|
||||||
|
|
||||||
|
const daiBalanceAfter = await daiToken.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("DAI balance after: ", toEther(daiBalanceAfter));
|
||||||
|
|
||||||
|
const imUsdVaultBalanceAfter = await imUsdVault.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("imUSD Vault balance after: ", toEther(imUsdVaultBalanceAfter));
|
||||||
|
|
||||||
|
expect(imUsdVaultBalanceAfter).to.be.gt(imUsdVaultBalanceBefore);
|
||||||
|
expect(await imUsdToken.balanceOf(dsaWallet0.address)).to.be.eq(0);
|
||||||
|
expect(daiBalanceAfter).to.eq(daiBalanceBefore.sub(depositAmount));
|
||||||
|
});
|
||||||
|
it.skip("Should deposit FRAX to Vault successfully (via Feeder Pool)", async () => {
|
||||||
|
const depositAmount = simpleToExactAmount(100);
|
||||||
|
const minOut = calcMinOut(depositAmount, 0.02);
|
||||||
|
|
||||||
|
const fraxBalanceBefore = await fraxToken.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("FRAX balance before: ", toEther(fraxBalanceBefore));
|
||||||
|
|
||||||
|
const spells = [
|
||||||
|
{
|
||||||
|
connector: connectorName,
|
||||||
|
method: "deposit",
|
||||||
|
args: [fraxToken.address, depositAmount, minOut, getToken("FRAX").feederPool]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const imUsdVaultBalanceBefore = await imUsdVault.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("imUSD Vault balance before: ", toEther(imUsdVaultBalanceBefore));
|
||||||
|
|
||||||
|
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), DEAD_ADDRESS);
|
||||||
|
|
||||||
|
const fraxBalanceAfter = await fraxToken.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("FRAX balance after: ", toEther(fraxBalanceAfter));
|
||||||
|
|
||||||
|
const imUsdVaultBalanceAfter = await imUsdVault.balanceOf(dsaWallet0.address);
|
||||||
|
console.log("imUSD Vault balance after: ", toEther(imUsdVaultBalanceAfter));
|
||||||
|
|
||||||
|
expect(imUsdVaultBalanceAfter).to.be.gt(imUsdVaultBalanceBefore);
|
||||||
|
expect(await imUsdToken.balanceOf(dsaWallet0.address)).to.be.eq(0);
|
||||||
|
expect(fraxBalanceAfter).to.eq(fraxBalanceBefore.sub(depositAmount));
|
||||||
|
});
|
||||||
|
it.skip("Should withdraw from Vault to mUSD", async () => {});
|
||||||
|
it.skip("Should withdraw from Vault to DAI (mUSD bAsset)", async () => {});
|
||||||
|
it.skip("Should withdraw from Vault to FRAX (via Feeder Pool)", async () => {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user