diff --git a/constants/addresses.ts b/constants/addresses.ts index f3ee2103..cac725dd 100644 --- a/constants/addresses.ts +++ b/constants/addresses.ts @@ -80,3 +80,5 @@ export const DODOV2Proxy = { Heco: "0xAc7cC7d2374492De2D1ce21e2FEcA26EB0d113e7", Arbitrum: "0x88CBf433471A0CD8240D2a12354362988b4593E5", }; + +export const CurveSwapsAddress = "0x1d8b86e3D88cDb2d34688e87E72F388Cb541B7C8"; diff --git a/contracts/Flashloan.sol b/contracts/Flashloan.sol index 0ca1dab1..7a07012d 100644 --- a/contracts/Flashloan.sol +++ b/contracts/Flashloan.sol @@ -7,6 +7,8 @@ import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "./uniswap/IUniswapV2Router.sol"; import "./uniswap/v3/ISwapRouter.sol"; +import "./curve/ICurveFiSwaps.sol"; + import "./dodo/IDODO.sol"; import "./interfaces/IFlashloan.sol"; @@ -135,8 +137,10 @@ contract Flashloan is IFlashloan, DodoBase, FlashloanValidation, Withdraw { amountOut = uniswapV3(swap.data, amountIn, path); } else if (swap.protocol < 8) { amountOut = uniswapV2(swap.data, amountIn, path); - } else { + } else if (swap.protocol == 8) { amountOut = dodoV2Swap(swap.data, amountIn, path); + } else { + amountOut = curveFiSwap(swap.data, amountIn, path); } } @@ -181,6 +185,21 @@ contract Flashloan is IFlashloan, DodoBase, FlashloanValidation, Withdraw { )[1]; } + function curveFiSwap( + bytes memory data, + uint256 amountIn, + address[] memory path + ) internal returns (uint256 amountOut) { + (uint256 i, uint256 j, address router) = abi.decode( + data, + (uint256, uint256, address) + ); + uint256 initialBalance = IERC20(path[1]).balanceOf(address(this)); + approveToken(path[0], router, amountIn); + ICurveFiSwaps(router).exchange_underlying(i, j, amountIn, 0); + return IERC20(path[1]).balanceOf(address(this)) - initialBalance; + } + function dodoV2Swap( bytes memory data, uint256 amountIn, diff --git a/contracts/base/FlashloanValidation.sol b/contracts/base/FlashloanValidation.sol index 3b30d28f..3e8fd9b5 100644 --- a/contracts/base/FlashloanValidation.sol +++ b/contracts/base/FlashloanValidation.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import "../interfaces/IFlashloan.sol"; abstract contract FlashloanValidation { - uint256 constant MAX_PROTOCOL = 8; + uint256 constant MAX_PROTOCOL = 9; modifier checkTotalRoutePart(IFlashloan.Route[] memory routes) { uint16 totalPart = 0; diff --git a/contracts/curve/CurveFiSwaps.sol b/contracts/curve/CurveFiSwaps.sol new file mode 100644 index 00000000..3ffe6093 --- /dev/null +++ b/contracts/curve/CurveFiSwaps.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract CurveFiSwaps { + function get_dy_underlying( + uint256 i, + uint256 j, + uint256 _dx + ) external view returns (uint256) {} + + function exchange_underlying( + uint256 i, + uint256 j, + uint256 _dx, + uint256 _min_dy + ) external {} +} diff --git a/contracts/curve/CurveSwap.sol b/contracts/curve/CurveSwap.sol new file mode 100644 index 00000000..f1961205 --- /dev/null +++ b/contracts/curve/CurveSwap.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./ICurveFiSwaps.sol"; + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; + +contract CurveSwap { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + function curveFiSwap( + bytes memory data, + uint256 amountIn, + address[] memory path + ) external returns (uint256 amountOut) { + (uint256 i, uint256 j, address router) = abi.decode( + data, + (uint256, uint256, address) + ); + uint256 initialBalance = IERC20(path[1]).balanceOf(address(this)); + approveToken(path[0], router, amountIn); + ICurveFiSwaps(router).exchange_underlying(i, j, amountIn, 0); + return IERC20(path[1]).balanceOf(address(this)) - initialBalance; + } + + function approveToken( + address token, + address to, + uint256 amountIn + ) internal { + require(IERC20(token).approve(to, amountIn), "approve failed."); + } +} diff --git a/contracts/curve/ICurveFiSwaps.sol b/contracts/curve/ICurveFiSwaps.sol new file mode 100644 index 00000000..227259e6 --- /dev/null +++ b/contracts/curve/ICurveFiSwaps.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ICurveFiSwaps { + function get_dy_underlying( + uint256 i, + uint256 j, + uint256 _dx + ) external view returns (uint256); + + function exchange_underlying( + uint256 i, + uint256 j, + uint256 _dx, + uint256 _min_dy + ) external; +} diff --git a/contracts/dodo/IDODOV2.sol b/contracts/dodo/IDODOV2.sol index ae1680f7..4e4e4a73 100644 --- a/contracts/dodo/IDODOV2.sol +++ b/contracts/dodo/IDODOV2.sol @@ -5,6 +5,7 @@ */ pragma solidity ^0.8; + // pragma solidity 0.6.9; // import {IERC20} from "../interfaces/IERC20.sol"; @@ -21,4 +22,8 @@ interface IDODOV2 { external view returns (uint256 receiveBaseAmount, uint256 mtFee); -} \ No newline at end of file + + function _BASE_TOKEN_() external view returns (address); + + function _QUOTE_TOKEN_() external view returns (address); +} diff --git a/test/curve.test.ts b/test/curve.test.ts new file mode 100644 index 00000000..160954f3 --- /dev/null +++ b/test/curve.test.ts @@ -0,0 +1,110 @@ +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { ERC20Mock, CurveFiSwaps, CurveFiSwaps__factory } from "../typechain"; +import { USDC_WHALE, CurveSwapsAddress } from "../constants/addresses"; +import { getErc20Balance, impersonateFundErc20 } from "../utils/token"; +import { getBigNumber, getERC20ContractFromAddress } from "../utils"; +import { ERC20Token } from "../constants/token"; + +describe("Curve fi", () => { + let Curve: CurveFiSwaps; + let owner: SignerWithAddress; + let addr1: SignerWithAddress; + let addr2: SignerWithAddress; + let addrs: SignerWithAddress[]; + let USDC: ERC20Mock; + let DAI: ERC20Mock; + let WBTC: ERC20Mock; + + let fixture: any; + + before(async () => { + USDC = await getERC20ContractFromAddress(ERC20Token.USDC.address); + DAI = await getERC20ContractFromAddress(ERC20Token.DAI.address); + WBTC = await getERC20ContractFromAddress(ERC20Token.WBTC.address); + fixture = async () => { + [owner, addr1, addr2, ...addrs] = await ethers.getSigners(); + + const factory = (await ethers.getContractFactory( + "CurveFiSwaps" + )) as CurveFiSwaps__factory; + Curve = factory.attach(CurveSwapsAddress); + }; + }); + + beforeEach(async () => { + await fixture(); + }); + + describe("get price", async () => { + it("DAI - USDC", async () => { + const amountOut = await Curve.get_dy_underlying(0, 1, getBigNumber(1000)); + expect(amountOut.gt(getBigNumber(0))).to.be.true; + }); + + it("USDC - WBTC", async () => { + const amountOut = await Curve.get_dy_underlying( + 1, + 3, + getBigNumber(1000, 6) + ); + expect(amountOut.gt(getBigNumber(0))).to.be.true; + }); + + it("WBTC - WETH", async () => { + const amountOut = await Curve.get_dy_underlying(3, 4, getBigNumber(1, 8)); + expect(amountOut.gt(getBigNumber(0))).to.be.true; + }); + }); + + describe("exchange", async () => { + it("USDC - DAI", async () => { + await impersonateFundErc20(USDC, USDC_WHALE, owner.address, "1000.0", 6); + await USDC.approve(Curve.address, getBigNumber(10, 6)); + await Curve.exchange_underlying( + 1, + 0, + getBigNumber(10, 6), + getBigNumber(9) + ); + const balance = await DAI.balanceOf(owner.address); + expect(balance.gt(getBigNumber(9))).to.be.true; + }); + + it("USDC - DAI - USDC", async () => { + await impersonateFundErc20(USDC, USDC_WHALE, owner.address, "1000.0", 6); + await USDC.approve(Curve.address, getBigNumber(1000, 6)); + await Curve.exchange_underlying( + 1, + 0, + getBigNumber(1000, 6), + getBigNumber(9) + ); + const daiBalance = await DAI.balanceOf(owner.address); + await DAI.approve(Curve.address, daiBalance); + await Curve.exchange_underlying(0, 1, daiBalance, getBigNumber(9, 6)); + const balance = await USDC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(900, 6))).to.be.true; + }); + + it("USDC - WBTC", async () => { + await impersonateFundErc20(USDC, USDC_WHALE, owner.address, "1000.0", 6); + await USDC.approve(Curve.address, getBigNumber(1000, 6)); + await Curve.exchange_underlying(1, 3, getBigNumber(1000, 6), 0); + const balance = await WBTC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(0))).to.be.true; + }); + + it("USDC - WBTC - USDC", async () => { + await impersonateFundErc20(USDC, USDC_WHALE, owner.address, "1000.0", 6); + await USDC.approve(Curve.address, getBigNumber(1000, 6)); + await Curve.exchange_underlying(1, 3, getBigNumber(1000, 6), 0); + const wbtcBalance = await WBTC.balanceOf(owner.address); + await WBTC.approve(Curve.address, wbtcBalance); + await Curve.exchange_underlying(3, 1, wbtcBalance, 0); + const balance = await USDC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(0))).to.be.true; + }); + }); +}); diff --git a/test/curveflashloan.test.ts b/test/curveflashloan.test.ts new file mode 100644 index 00000000..b0d6cda7 --- /dev/null +++ b/test/curveflashloan.test.ts @@ -0,0 +1,227 @@ +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { + CurveSwapsAddress, + DODOApprove, + dodoV2Pool, + DODOV2Proxy, + erc20Address, + USDC_WHALE, +} from "../constants/addresses"; +import { ERC20Token } from "../constants/token"; +import { ERC20Mock, Flashloan, Flashloan__factory } from "../typechain"; +import { + deployContractFromName, + findRouterFromProtocol, + getBigNumber, + getERC20ContractFromAddress, +} from "../utils"; +import { impersonateFundErc20 } from "../utils/token"; + +describe("Flashloan", () => { + let Flashloan: Flashloan; + let owner: SignerWithAddress; + let addr1: SignerWithAddress; + let addr2: SignerWithAddress; + let addrs: SignerWithAddress[]; + let DAI: ERC20Mock; + let USDC: ERC20Mock; + let WMATIC: ERC20Mock; + let WETH: ERC20Mock; + let USDT: ERC20Mock; + + before(async () => { + USDC = await getERC20ContractFromAddress(erc20Address.USDC); + USDT = await getERC20ContractFromAddress(erc20Address.USDT); + DAI = await getERC20ContractFromAddress(erc20Address.DAI); + WETH = await getERC20ContractFromAddress(erc20Address.WETH); + WMATIC = await getERC20ContractFromAddress(erc20Address.WMATIC); + }); + + beforeEach(async () => { + [owner, addr1, addr2, ...addrs] = await ethers.getSigners(); + Flashloan = await deployContractFromName("Flashloan", Flashloan__factory); + await Flashloan.deployed(); + await impersonateFundErc20( + USDC, + USDC_WHALE, + Flashloan.address, + "1000.0", + 6 + ); + }); + + describe("Curve", () => { + it("USDC - DAI", async () => { + await expect( + Flashloan.dodoFlashLoan( + { + flashLoanPool: dodoV2Pool.WETH_USDC, + loanAmount: getBigNumber(1000, 6), + firstRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 9, + part: 10000, + + data: ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "address"], + [1, 0, CurveSwapsAddress] + ), + }, + ], + path: [ERC20Token.USDC.address, ERC20Token.DAI.address], + }, + ], + part: 10000, + }, + ], + secondRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 0, + part: 10000, + data: ethers.utils.defaultAbiCoder.encode( + ["address", "uint24"], + [findRouterFromProtocol(0), 500] + ), + }, + ], + path: [ERC20Token.DAI.address, ERC20Token.USDC.address], + }, + ], + part: 10000, + }, + ], + }, + { gasLimit: 1000000 } + ) + ) + .emit(Flashloan, "SwapFinished") + .emit(Flashloan, "SentProfit"); + const balance = await USDC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(0))).to.be.true; + }); + + it("USDC - DAI", async () => { + await expect( + Flashloan.dodoFlashLoan( + { + flashLoanPool: dodoV2Pool.WETH_USDC, + loanAmount: getBigNumber(1000, 6), + firstRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 0, + part: 10000, + data: ethers.utils.defaultAbiCoder.encode( + ["address", "uint24"], + [findRouterFromProtocol(0), 500] + ), + }, + ], + path: [ERC20Token.USDC.address, ERC20Token.DAI.address], + }, + ], + part: 10000, + }, + ], + secondRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 9, + part: 10000, + + data: ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "address"], + [0, 1, CurveSwapsAddress] + ), + }, + ], + path: [ERC20Token.DAI.address, ERC20Token.USDC.address], + }, + ], + part: 10000, + }, + ], + }, + { gasLimit: 1000000 } + ) + ) + .emit(Flashloan, "SwapFinished") + .emit(Flashloan, "SentProfit"); + const balance = await USDC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(0))).to.be.true; + }); + + it("USDC - WBTC", async () => { + await expect( + Flashloan.dodoFlashLoan( + { + flashLoanPool: dodoV2Pool.WETH_USDC, + loanAmount: getBigNumber(1000, 6), + firstRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 0, + part: 10000, + data: ethers.utils.defaultAbiCoder.encode( + ["address", "uint24"], + [findRouterFromProtocol(0), 3000] + ), + }, + ], + path: [ERC20Token.USDC.address, ERC20Token.WBTC.address], + }, + ], + part: 10000, + }, + ], + secondRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 9, + part: 10000, + + data: ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "address"], + [3, 1, CurveSwapsAddress] + ), + }, + ], + path: [ERC20Token.WBTC.address, ERC20Token.USDC.address], + }, + ], + part: 10000, + }, + ], + }, + { gasLimit: 1000000 } + ) + ) + .emit(Flashloan, "SwapFinished") + .emit(Flashloan, "SentProfit"); + const balance = await USDC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(0))).to.be.true; + }); + }); +}); diff --git a/test/curveswap.test.ts b/test/curveswap.test.ts new file mode 100644 index 00000000..3c91e1db --- /dev/null +++ b/test/curveswap.test.ts @@ -0,0 +1,71 @@ +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { ERC20Mock, CurveSwap, CurveSwap__factory } from "../typechain"; +import { USDC_WHALE, CurveSwapsAddress } from "../constants/addresses"; +import { getErc20Balance, impersonateFundErc20 } from "../utils/token"; +import { + deployContractFromName, + getBigNumber, + getERC20ContractFromAddress, +} from "../utils"; +import { ERC20Token } from "../constants/token"; + +describe("Curve fi", () => { + let Curve: CurveSwap; + let owner: SignerWithAddress; + let addr1: SignerWithAddress; + let addr2: SignerWithAddress; + let addrs: SignerWithAddress[]; + let USDC: ERC20Mock; + let DAI: ERC20Mock; + let WBTC: ERC20Mock; + + let fixture: any; + + before(async () => { + USDC = await getERC20ContractFromAddress(ERC20Token.USDC.address); + DAI = await getERC20ContractFromAddress(ERC20Token.DAI.address); + WBTC = await getERC20ContractFromAddress(ERC20Token.WBTC.address); + fixture = async () => { + [owner, addr1, addr2, ...addrs] = await ethers.getSigners(); + + Curve = await deployContractFromName("CurveSwap", CurveSwap__factory); + await Curve.deployed(); + await impersonateFundErc20(USDC, USDC_WHALE, Curve.address, "1000.0", 6); + await impersonateFundErc20(DAI, USDC_WHALE, Curve.address, "1000.0", 18); + }; + }); + + beforeEach(async () => { + await fixture(); + }); + + describe("exchange", async () => { + it("USDC - DAI", async () => { + await Curve.curveFiSwap( + ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "address"], + [1, 0, CurveSwapsAddress] + ), + getBigNumber(1000, 6), + [ERC20Token.USDC.address, ERC20Token.DAI.address] + ); + const balance = await DAI.balanceOf(Curve.address); + expect(balance.gt(getBigNumber(9))).to.be.true; + }); + + it("DAI - USDC", async () => { + await Curve.curveFiSwap( + ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "address"], + [0, 1, CurveSwapsAddress] + ), + getBigNumber(1000), + [ERC20Token.DAI.address, ERC20Token.USDC.address] + ); + const balance = await USDC.balanceOf(Curve.address); + expect(balance.gt(getBigNumber(9, 6))).to.be.true; + }); + }); +}); diff --git a/test/dodoflash.test.ts b/test/dodoflash.test.ts index 1fa7694b..1aaf7734 100644 --- a/test/dodoflash.test.ts +++ b/test/dodoflash.test.ts @@ -2,62 +2,52 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; import { ethers } from "hardhat"; import * as IERC20 from "../artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.json"; -import { - DODOFlashloan, - DODOFlashloan__factory, -} from "../typechain"; -import { dodoV2Pool, erc20Address } from "../constants/addresses" +import { DODOFlashloan, DODOFlashloan__factory } from "../typechain"; +import { dodoV2Pool, erc20Address } from "../constants/addresses"; import { Contract } from "@ethersproject/contracts"; -import { getBigNumber } from "../utils" +import { getBigNumber } from "../utils"; describe("dodo flashloan", () => { - let Sample: DODOFlashloan; - let owner: SignerWithAddress; - let addr1: SignerWithAddress; - let addr2: SignerWithAddress; - let addrs: SignerWithAddress[]; - let DAI: Contract; - - const provider = ethers.provider; - let fixture: any; - - before(async () => { - fixture = async () => { - [owner, addr1, addr2, ...addrs] = await ethers.getSigners(); - - const factory = (await ethers.getContractFactory( - "DODOFlashloan" - )) as DODOFlashloan__factory; - Sample = await factory.deploy(); - - await Sample.deployed() - - DAI = new ethers.Contract( - erc20Address.DAI, IERC20.abi, provider - ) - }; - }); - - beforeEach(async () => { - await fixture(); - }); - - describe("DODO flashloan", async () => { - - it("should execute flashloan", async () => { - // borrowing 1000 DAI from DODOs USDC/DAI pool - await expect( - Sample.dodoFlashLoan( - dodoV2Pool.USDC_DAI, - getBigNumber(1000), - erc20Address.DAI - ) - ) - .emit(Sample, "checkBorrowedAmount") - .withArgs(erc20Address.DAI, getBigNumber(1000)) - .emit(Sample, "payBackLoan") - .withArgs(erc20Address.DAI, getBigNumber(1000)); - }); - - }); -}); \ No newline at end of file + let Sample: DODOFlashloan; + let owner: SignerWithAddress; + let addr1: SignerWithAddress; + let addr2: SignerWithAddress; + let addrs: SignerWithAddress[]; + let DAI: Contract; + + const provider = ethers.provider; + let fixture: any; + + before(async () => { + fixture = async () => { + [owner, addr1, addr2, ...addrs] = await ethers.getSigners(); + + const factory = (await ethers.getContractFactory( + "DODOFlashloan" + )) as DODOFlashloan__factory; + Sample = await factory.deploy(); + + await Sample.deployed(); + + DAI = new ethers.Contract(erc20Address.DAI, IERC20.abi, provider); + }; + }); + + beforeEach(async () => { + await fixture(); + }); + + describe("DODO flashloan", async () => { + it("should execute flashloan", async () => { + // borrowing 1000 DAI from DODOs USDC/DAI pool + const loanAmount = getBigNumber(1000); + await expect( + Sample.dodoFlashLoan(dodoV2Pool.USDC_DAI, loanAmount, erc20Address.DAI) + ) + .emit(Sample, "checkBorrowedAmount") + .withArgs(erc20Address.DAI, loanAmount) + .emit(Sample, "payBackLoan") + .withArgs(erc20Address.DAI, loanAmount); + }); + }); +}); diff --git a/test/flashloan.test.ts b/test/flashloan.test.ts index 2067bdc0..733725d2 100644 --- a/test/flashloan.test.ts +++ b/test/flashloan.test.ts @@ -2,6 +2,7 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; import { ethers } from "hardhat"; import { + CurveSwapsAddress, DODOApprove, dodoV2Pool, DODOV2Proxy, @@ -858,6 +859,122 @@ describe("Flashloan", () => { }); }); + describe("Curve", () => { + it("USDC - DAI", async () => { + await expect( + Flashloan.dodoFlashLoan( + { + flashLoanPool: dodoV2Pool.WETH_USDC, + loanAmount: getBigNumber(1000, 6), + firstRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 0, + part: 10000, + data: ethers.utils.defaultAbiCoder.encode( + ["address", "uint24"], + [findRouterFromProtocol(0), 500] + ), + }, + ], + path: [ERC20Token.USDC.address, ERC20Token.DAI.address], + }, + ], + part: 10000, + }, + ], + secondRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 9, + part: 10000, + + data: ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "address"], + [0, 1, CurveSwapsAddress] + ), + }, + ], + path: [ERC20Token.DAI.address, ERC20Token.USDC.address], + }, + ], + part: 10000, + }, + ], + }, + { gasLimit: 1000000 } + ) + ) + .emit(Flashloan, "SwapFinished") + .emit(Flashloan, "SentProfit"); + const balance = await USDC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(0))).to.be.true; + }); + + it("USDC - WBTC", async () => { + await expect( + Flashloan.dodoFlashLoan( + { + flashLoanPool: dodoV2Pool.WETH_USDC, + loanAmount: getBigNumber(1000, 6), + firstRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 0, + part: 10000, + data: ethers.utils.defaultAbiCoder.encode( + ["address", "uint24"], + [findRouterFromProtocol(0), 3000] + ), + }, + ], + path: [ERC20Token.USDC.address, ERC20Token.WBTC.address], + }, + ], + part: 10000, + }, + ], + secondRoutes: [ + { + hops: [ + { + swaps: [ + { + protocol: 9, + part: 10000, + + data: ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint256", "address"], + [3, 1, CurveSwapsAddress] + ), + }, + ], + path: [ERC20Token.WBTC.address, ERC20Token.USDC.address], + }, + ], + part: 10000, + }, + ], + }, + { gasLimit: 1000000 } + ) + ) + .emit(Flashloan, "SwapFinished") + .emit(Flashloan, "SentProfit"); + const balance = await USDC.balanceOf(owner.address); + expect(balance.gt(getBigNumber(0))).to.be.true; + }); + }); + describe("Withdraw", () => { it("should withdraw tokens", async () => { await expect( diff --git a/test/uniswap.test.ts b/test/uniswap.test.ts index 1034757a..369fad46 100644 --- a/test/uniswap.test.ts +++ b/test/uniswap.test.ts @@ -34,7 +34,7 @@ describe("Swap on uniswap fork on polygon", () => { WMATIC = await getERC20ContractFromAddress(erc20Address.WMATIC); fixture = async () => { - [owner, addr2, addr2, ...addrs] = await ethers.getSigners(); + [owner, addr1, addr2, ...addrs] = await ethers.getSigners(); const factory = (await ethers.getContractFactory( "UniswapFork",