diff --git a/hardhat.config.js b/hardhat.config.js index 45b17f9d..a3d99c31 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -52,7 +52,7 @@ module.exports = { hardhat: { forking: { url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, - blockNumber: 12433781, + blockNumber: 12696000, }, blockGasLimit: 12000000, }, diff --git a/scripts/constant/abi/connectors/instapool.json b/scripts/constant/abi/connectors/instapool.json new file mode 100644 index 00000000..75a04f42 --- /dev/null +++ b/scripts/constant/abi/connectors/instapool.json @@ -0,0 +1 @@ +[{"type":"event","name":"LogFlashBorrow","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"tokenAmt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LogFlashMultiBorrow","inputs":[{"type":"address[]","name":"token","internalType":"address[]","indexed":false},{"type":"uint256[]","name":"tokenAmts","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"LogFlashMultiPayback","inputs":[{"type":"address[]","name":"token","internalType":"address[]","indexed":false},{"type":"uint256[]","name":"tokenAmts","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"event","name":"LogFlashPayback","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"tokenAmt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"payable","outputs":[{"type":"string","name":"_eventName","internalType":"string"},{"type":"bytes","name":"_eventParam","internalType":"bytes"}],"name":"flashBorrowAndCast","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amt","internalType":"uint256"},{"type":"uint256","name":"route","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"string","name":"_eventName","internalType":"string"},{"type":"bytes","name":"_eventParam","internalType":"bytes"}],"name":"flashMultiBorrowAndCast","inputs":[{"type":"address[]","name":"tokens","internalType":"address[]"},{"type":"uint256[]","name":"amts","internalType":"uint256[]"},{"type":"uint256","name":"route","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"string","name":"_eventName","internalType":"string"},{"type":"bytes","name":"_eventParam","internalType":"bytes"}],"name":"flashMultiPayback","inputs":[{"type":"address[]","name":"tokens","internalType":"address[]"},{"type":"uint256[]","name":"amts","internalType":"uint256[]"},{"type":"uint256[]","name":"getId","internalType":"uint256[]"},{"type":"uint256[]","name":"setId","internalType":"uint256[]"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"string","name":"_eventName","internalType":"string"},{"type":"bytes","name":"_eventParam","internalType":"bytes"}],"name":"flashPayback","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amt","internalType":"uint256"},{"type":"uint256","name":"getId","internalType":"uint256"},{"type":"uint256","name":"setId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract InstaFlashV2Interface"}],"name":"instaPool","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]}] \ No newline at end of file diff --git a/scripts/constant/abis.js b/scripts/constant/abis.js index c25bd350..3ed03f80 100644 --- a/scripts/constant/abis.js +++ b/scripts/constant/abis.js @@ -6,6 +6,7 @@ module.exports = { connectors: { basic: require("./abi/connectors/basic.json"), auth: require("./abi/connectors/auth.json"), + "INSTAPOOL-A": require("./abi/connectors/instapool.json"), }, basic: { erc20: require("./abi/basics/erc20.json"), diff --git a/scripts/constant/addresses.js b/scripts/constant/addresses.js index ead09c40..a1cb7d45 100644 --- a/scripts/constant/addresses.js +++ b/scripts/constant/addresses.js @@ -2,10 +2,11 @@ module.exports = { connectors: { basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6", auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9", + "INSTAPOOL-A": "0x5806af7ab22e2916fa582ff05731bf7c682387b2" }, core: { - connectorsV2: "0xFE2390DAD597594439f218190fC2De40f9Cf1179", - instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723" + connectorsV2: "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11", + instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723", } }; \ No newline at end of file diff --git a/scripts/encodeFlashcastData.js b/scripts/encodeFlashcastData.js new file mode 100644 index 00000000..a674c1af --- /dev/null +++ b/scripts/encodeFlashcastData.js @@ -0,0 +1,16 @@ +const abis = require("./constant/abis"); +const addresses = require("./constant/addresses"); +const { web3 } = hre; + +const encodeSpells = require("./encodeSpells.js") + + +module.exports = function (spells) { + const encodeSpellsData = encodeSpells(spells); + const targetType = "string[]"; + let argTypes = [targetType, "bytes[]"]; + return web3.eth.abi.encodeParameters(argTypes, [ + encodeSpellsData[0], + encodeSpellsData[1], + ]); +}; diff --git a/test/instapool/instapool.test.js b/test/instapool/instapool.test.js new file mode 100644 index 00000000..c0a0fb81 --- /dev/null +++ b/test/instapool/instapool.test.js @@ -0,0 +1,109 @@ +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 encodeFlashcastData = require("../../scripts/encodeFlashcastData.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 connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/compound/main.sol/ConnectV2Compound.json") + +describe("Instapool", function () { + const connectorName = "COMPOUND-TEST-A" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2CompoundArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + + it("Should deposit ETH in Compound", async function () { + const amount = ethers.utils.parseEther("1") // 1 ETH + const flashloanAmount = ethers.utils.parseEther("100") // 100 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const IdOne = "2878734423" + const IdTwo = "783243246" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: ["ETH-A", flashloanAmount, 0, IdOne] + }, + { + connector: connectorName, + method: "withdraw", + args: ["ETH-A", amount, IdOne, IdTwo] + }, + { + connector: "INSTAPOOL-A", + method: "flashPayback", + args: [ethAddress, flashloanAmount, IdTwo, 0], + } + ] + + const calldata = encodeFlashcastData(spells); + + const spells2 = [ + { + connector: "INSTAPOOL-A", + method: "flashBorrowAndCast", + args: [ + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + flashloanAmount, + 0, // route + calldata, + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells2), wallet1.address) + const receipt = await tx.wait() + }); + }) +})