From 847ad3b12a9f008e828530d25e60f6c84482e3f3 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Tue, 3 Nov 2020 15:37:06 -0300 Subject: [PATCH] Add batch swaps unit tests --- .../adapters/UniswapLiquiditySwapAdapter.sol | 2 +- contracts/adapters/UniswapRepayAdapter.sol | 2 +- .../mocks/swap/MockUniswapV2Router02.sol | 30 +- test/uniswapAdapters.spec.ts | 917 +++++++++++++++++- 4 files changed, 905 insertions(+), 46 deletions(-) diff --git a/contracts/adapters/UniswapLiquiditySwapAdapter.sol b/contracts/adapters/UniswapLiquiditySwapAdapter.sol index 5291cb85..365089a8 100644 --- a/contracts/adapters/UniswapLiquiditySwapAdapter.sol +++ b/contracts/adapters/UniswapLiquiditySwapAdapter.sol @@ -159,7 +159,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { * bytes32[] s List of s param for the permit signature * @return SwapParams struct containing decoded params */ - function _decodeParams(bytes memory params) internal returns (SwapParams memory) { + function _decodeParams(bytes memory params) internal pure returns (SwapParams memory) { ( address[] memory assetToSwapToList, uint256[] memory minAmountsToReceive, diff --git a/contracts/adapters/UniswapRepayAdapter.sol b/contracts/adapters/UniswapRepayAdapter.sol index d105cb5c..550241ea 100644 --- a/contracts/adapters/UniswapRepayAdapter.sol +++ b/contracts/adapters/UniswapRepayAdapter.sol @@ -147,7 +147,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver { * bytes32[] s List of s param for the permit signature * @return RepayParams struct containing decoded params */ - function _decodeParams(bytes memory params) internal returns (RepayParams memory) { + function _decodeParams(bytes memory params) internal pure returns (RepayParams memory) { ( address[] memory assetToSwapToList, LeftoverAction leftOverAction, diff --git a/contracts/mocks/swap/MockUniswapV2Router02.sol b/contracts/mocks/swap/MockUniswapV2Router02.sol index ef4c22c4..6d771cda 100644 --- a/contracts/mocks/swap/MockUniswapV2Router02.sol +++ b/contracts/mocks/swap/MockUniswapV2Router02.sol @@ -6,17 +6,17 @@ import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {MintableERC20} from '../tokens/MintableERC20.sol'; contract MockUniswapV2Router02 is IUniswapV2Router02 { - uint256 internal _amountToReturn; - uint256 internal _amountToSwap; + mapping(address => uint256) internal _amountToReturn; + mapping(address => uint256) internal _amountToSwap; mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsIn; mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsOut; - function setAmountToReturn(uint256 amount) public { - _amountToReturn = amount; + function setAmountToReturn(address reserve, uint256 amount) public { + _amountToReturn[reserve] = amount; } - function setAmountToSwap(uint256 amount) public { - _amountToSwap = amount; + function setAmountToSwap(address reserve, uint256 amount) public { + _amountToSwap[reserve] = amount; } function swapExactTokensForTokens( @@ -28,29 +28,29 @@ contract MockUniswapV2Router02 is IUniswapV2Router02 { ) external override returns (uint256[] memory amounts) { IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn); - MintableERC20(path[1]).mint(_amountToReturn); - IERC20(path[1]).transfer(to, _amountToReturn); + MintableERC20(path[1]).mint(_amountToReturn[path[0]]); + IERC20(path[1]).transfer(to, _amountToReturn[path[0]]); amounts = new uint[](path.length); amounts[0] = amountIn; - amounts[1] = _amountToReturn; + amounts[1] = _amountToReturn[path[0]]; } function swapTokensForExactTokens( - uint /* amountOut */, + uint amountOut, uint /* amountInMax */, address[] calldata path, address to, uint /* deadline */ ) external override returns (uint256[] memory amounts) { - IERC20(path[0]).transferFrom(msg.sender, address(this), _amountToSwap); + IERC20(path[0]).transferFrom(msg.sender, address(this), _amountToSwap[path[0]]); - MintableERC20(path[1]).mint(_amountToReturn); - IERC20(path[1]).transfer(to, _amountToReturn); + MintableERC20(path[1]).mint(amountOut); + IERC20(path[1]).transfer(to, amountOut); amounts = new uint[](path.length); - amounts[0] = _amountToSwap; - amounts[1] = _amountToReturn; + amounts[0] = _amountToSwap[path[0]]; + amounts[1] = amountOut; } function setAmountOut(uint amountIn, address reserveIn, address reserveOut, uint amountOut) public { diff --git a/test/uniswapAdapters.spec.ts b/test/uniswapAdapters.spec.ts index 259a4ec3..35803467 100644 --- a/test/uniswapAdapters.spec.ts +++ b/test/uniswapAdapters.spec.ts @@ -89,7 +89,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { describe('executeOperation', () => { beforeEach(async () => { - const {users, weth, dai, pool, deployer} = testEnv; + const {users, weth, dai, usdc, pool, deployer} = testEnv; const userAddress = users[0].address; // Provide liquidity @@ -97,6 +97,11 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { await dai.approve(pool.address, parseEther('20000')); await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + const usdcAmount = await convertToCurrencyDecimals(usdc.address, '10'); + await usdc.mint(usdcAmount); + await usdc.approve(pool.address, usdcAmount); + await pool.deposit(usdc.address, usdcAmount, deployer.address, 0); + // Make a deposit for user await weth.mint(parseEther('100')); await weth.approve(pool.address, parseEther('100')); @@ -116,7 +121,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); // User will swap liquidity 10 aEth to aDai const liquidityToSwap = parseEther('10'); @@ -171,6 +176,281 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap)); }); + it('should correctly swap and deposit multiple tokens', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + usdc, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + // Subtract the FL fee from the amount to be swapped 0,09% + const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) + .div(1.0009) + .toFixed(0); + const usdcFlashloanAmount = new BigNumber(amountUSDCtoSwap.toString()) + .div(1.0009) + .toFixed(0); + + const params = ethers.utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], + [ + [dai.address, dai.address], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [0, 0], + [0, 0], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + ] + ); + + await pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address, usdc.address], + [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], + [0, 0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + }); + + it('should correctly swap and deposit multiple tokens using permit', async () => { + const { + users, + weth, + oracle, + dai, + aDai, + aWETH, + usdc, + pool, + uniswapLiquiditySwapAdapter, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + + const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + // IMPORTANT: Round down to work equal to solidity to get the correct value for permit call + BigNumber.config({ + ROUNDING_MODE: 1, //round down + }); + + const wethFlashloanAmountBN = new BigNumber(amountWETHtoSwap.toString()).div(1.0009); + const wethFlashloanAmount = wethFlashloanAmountBN.toFixed(0); + const wethFlashloanFee = wethFlashloanAmountBN.multipliedBy(9).div(10000); + const wethAmountToPermit = wethFlashloanAmountBN.plus(wethFlashloanFee).toFixed(0); + + const usdcFlashloanAmountBN = new BigNumber(amountUSDCtoSwap.toString()).div(1.0009); + const usdcFlashloanAmount = usdcFlashloanAmountBN.toFixed(0); + const usdcFlashloanFee = usdcFlashloanAmountBN.multipliedBy(9).div(10000); + const usdcAmountToPermit = usdcFlashloanAmountBN.plus(usdcFlashloanFee).toFixed(0); + + const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); + const aWethMsgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aWethNonce, + deadline, + wethAmountToPermit.toString() + ); + const {v: aWETHv, r: aWETHr, s: aWETHs} = getSignatureFromTypedData( + ownerPrivateKey, + aWethMsgParams + ); + + const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); + const aUsdcMsgParams = buildPermitParams( + chainId, + aUsdc.address, + '1', + await aUsdc.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aUsdcNonce, + deadline, + usdcAmountToPermit.toString() + ); + const {v: aUsdcv, r: aUsdcr, s: aUsdcs} = getSignatureFromTypedData( + ownerPrivateKey, + aUsdcMsgParams + ); + + const params = ethers.utils.defaultAbiCoder.encode( + ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], + [ + [dai.address, dai.address], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [deadline, deadline], + [aWETHv, aUsdcv], + [aWETHr, aUsdcr], + [aWETHs, aUsdcs], + ] + ); + + await pool + .connect(user) + .flashLoan( + uniswapLiquiditySwapAdapter.address, + [weth.address, usdc.address], + [wethFlashloanAmount.toString(), usdcFlashloanAmount.toString()], + [0, 0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + + // Restore round up + BigNumber.config({ + ROUNDING_MODE: 0, //round up + }); + }); + it('should correctly swap tokens with permit', async () => { const {users, weth, oracle, dai, aDai, aWETH, pool, uniswapLiquiditySwapAdapter} = testEnv; const user = users[0].signer; @@ -184,7 +464,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); // User will swap liquidity 10 aEth to aDai const liquidityToSwap = parseEther('10'); @@ -279,7 +559,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); // User will swap liquidity 10 aEth to aDai const liquidityToSwap = parseEther('10'); @@ -464,7 +744,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); // User will swap liquidity 10 aEth to aDai const liquidityToSwap = parseEther('10'); @@ -544,7 +824,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { .toFixed(0) ); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToReturn(usdc.address, expectedDaiAmount); const aUsdcData = await pool.getReserveData(usdc.address); const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); @@ -608,7 +888,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); const smallExpectedDaiAmount = expectedDaiAmount.div(2); // User will swap liquidity 10 aEth to aDai @@ -675,7 +955,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); // User will swap liquidity 10 aEth to aDai const liquidityToSwap = parseEther('10'); @@ -731,7 +1011,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); // User will swap liquidity 10 aEth to aDai const liquidityToSwap = parseEther('10'); @@ -899,7 +1179,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) ); - await mockUniswapRouter.setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); const smallExpectedDaiAmount = expectedDaiAmount.div(2); // User will swap liquidity 10 aEth to aDai @@ -923,6 +1203,241 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ) ).to.be.revertedWith('minAmountOut exceed max slippage'); }); + + it('should correctly swap tokens and deposit multiple tokens', async () => { + const { + users, + weth, + usdc, + oracle, + dai, + aDai, + aWETH, + uniswapLiquiditySwapAdapter, + pool, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap); + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, amountUSDCtoSwap); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address, usdc.address], + [dai.address, dai.address], + [amountWETHtoSwap, amountUSDCtoSwap], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [ + { + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + { + deadline: 0, + v: 0, + r: '0x0000000000000000000000000000000000000000000000000000000000000000', + s: '0x0000000000000000000000000000000000000000000000000000000000000000', + }, + ] + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + }); + + it('should correctly swap tokens and deposit multiple tokens using permit', async () => { + const { + users, + weth, + usdc, + oracle, + dai, + aDai, + aWETH, + uniswapLiquiditySwapAdapter, + pool, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + + const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10'); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await usdc.decimals()).toString(); + const principalDecimals = (await dai.decimals()).toString(); + + const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Make a deposit for user + await usdc.connect(user).mint(amountUSDCtoSwap); + await usdc.connect(user).approve(pool.address, amountUSDCtoSwap); + await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0); + + const aUsdcData = await pool.getReserveData(usdc.address); + const aUsdc = await getContract(eContractid.AToken, aUsdcData.aTokenAddress); + + await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmountForEth); + await mockUniswapRouter.setAmountToReturn(usdc.address, expectedDaiAmountForUsdc); + + const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); + const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress); + + const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); + const aWethMsgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aWethNonce, + deadline, + amountWETHtoSwap.toString() + ); + const {v: aWETHv, r: aWETHr, s: aWETHs} = getSignatureFromTypedData( + ownerPrivateKey, + aWethMsgParams + ); + + const aUsdcNonce = (await aUsdc._nonces(userAddress)).toNumber(); + const aUsdcMsgParams = buildPermitParams( + chainId, + aUsdc.address, + '1', + await aUsdc.name(), + userAddress, + uniswapLiquiditySwapAdapter.address, + aUsdcNonce, + deadline, + amountUSDCtoSwap.toString() + ); + const {v: aUsdcv, r: aUsdcr, s: aUsdcs} = getSignatureFromTypedData( + ownerPrivateKey, + aUsdcMsgParams + ); + + await uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( + [weth.address, usdc.address], + [dai.address, dai.address], + [amountWETHtoSwap, amountUSDCtoSwap], + [expectedDaiAmountForEth, expectedDaiAmountForUsdc], + [ + { + deadline, + v: aWETHv, + r: aWETHr, + s: aWETHs, + }, + { + deadline, + v: aUsdcv, + r: aUsdcr, + s: aUsdcs, + }, + ] + ); + + const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address); + const adapterDaiAllowance = await dai.allowance( + uniswapLiquiditySwapAdapter.address, + userAddress + ); + const userADaiBalance = await aDai.balanceOf(userAddress); + const userAEthBalance = await aWETH.balanceOf(userAddress); + const userAUsdcBalance = await aUsdc.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(adapterDaiAllowance).to.be.eq(Zero); + expect(userADaiBalance).to.be.eq(expectedDaiAmountForEth.add(expectedDaiAmountForUsdc)); + expect(userAEthBalance).to.be.lt(userAEthBalanceBefore); + expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(amountWETHtoSwap)); + expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); + expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); + }); }); }); @@ -941,7 +1456,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { describe('executeOperation', () => { beforeEach(async () => { - const {users, weth, dai, pool, deployer} = testEnv; + const {users, weth, dai, usdc, lend, pool, deployer} = testEnv; const userAddress = users[0].address; // Provide liquidity @@ -949,10 +1464,27 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { await dai.approve(pool.address, parseEther('20000')); await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); + const usdcLiquidity = await convertToCurrencyDecimals(usdc.address, '20000'); + await usdc.mint(usdcLiquidity); + await usdc.approve(pool.address, usdcLiquidity); + await pool.deposit(usdc.address, usdcLiquidity, deployer.address, 0); + + await weth.mint(parseEther('100')); + await weth.approve(pool.address, parseEther('100')); + await pool.deposit(weth.address, parseEther('100'), deployer.address, 0); + + await lend.mint(parseEther('1000000')); + await lend.approve(pool.address, parseEther('1000000')); + await pool.deposit(lend.address, parseEther('1000000'), deployer.address, 0); + // Make a deposit for user await weth.mint(parseEther('100')); await weth.approve(pool.address, parseEther('100')); await pool.deposit(weth.address, parseEther('100'), userAddress, 0); + + await lend.mint(parseEther('1000000')); + await lend.approve(pool.address, parseEther('1000000')); + await pool.deposit(lend.address, parseEther('1000000'), userAddress, 0); }); it('should correctly swap tokens and repay debt', async () => { @@ -998,8 +1530,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { // Subtract the FL fee from the amount to be swapped 0,09% const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount); const params = ethers.utils.defaultAbiCoder.encode( [ @@ -1125,8 +1656,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams); - await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount); const params = ethers.utils.defaultAbiCoder.encode( [ @@ -1176,6 +1706,342 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { }); }); + it('should correctly swap tokens and repay debt for multiple tokens', async () => { + const { + users, + pool, + weth, + oracle, + dai, + uniswapRepayAdapter, + lend, + usdc, + helpersContract, + aWETH, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + const amountLendToSwap = await convertToCurrencyDecimals(lend.address, '1'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const lendPrice = await oracle.getAssetPrice(lend.address); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await lend.decimals()).toString(); + const principalDecimals = (await usdc.decimals()).toString(); + + const expectedUsdcAmountForLend = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(amountLendToSwap.toString()) + .times( + new BigNumber(lendPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmountForEth, 1, 0, userAddress); + await pool.connect(user).borrow(usdc.address, expectedUsdcAmountForLend, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const usdcStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(usdc.address) + ).stableDebtTokenAddress; + + const usdcStableDebtContract = await getContract( + eContractid.StableDebtToken, + usdcStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + const userUsdcStableDebtAmountBefore = await usdcStableDebtContract.balanceOf(userAddress); + + // Subtract the FL fee from the amount to be swapped 0,09% + const wethFlashloanAmount = new BigNumber(amountWETHtoSwap.toString()) + .div(1.0009) + .toFixed(0); + const lendFlashloanAmount = new BigNumber(amountLendToSwap.toString()) + .div(1.0009) + .toFixed(0); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, wethFlashloanAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(lend.address, lendFlashloanAmount); + + await aWETH.connect(user).approve(uniswapRepayAdapter.address, amountWETHtoSwap); + + const lendData = await pool.getReserveData(lend.address); + const aLend = await getContract(eContractid.AToken, lendData.aTokenAddress); + await aLend.connect(user).approve(uniswapRepayAdapter.address, amountLendToSwap); + + const aWETHBalanceBefore = await aWETH.balanceOf(userAddress); + const aLendBalanceBefore = await aLend.balanceOf(userAddress); + + const params = ethers.utils.defaultAbiCoder.encode( + [ + 'address[]', + 'uint256', + 'uint256[]', + 'uint256[]', + 'uint256[]', + 'uint8[]', + 'bytes32[]', + 'bytes32[]', + ], + [ + [dai.address, usdc.address], + 0, + [expectedDaiAmountForEth, expectedUsdcAmountForLend], + [1, 1], + [0, 0], + [0, 0], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + [ + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + ] + ); + + await pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [weth.address, lend.address], + [wethFlashloanAmount.toString(), lendFlashloanAmount.toString()], + [0, 0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userUsdcStableDebtAmount = await usdcStableDebtContract.balanceOf(userAddress); + const aWETHBalance = await aWETH.balanceOf(userAddress); + const aLendBalance = await aLend.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmountForEth); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmountForEth); + expect(userUsdcStableDebtAmountBefore).to.be.gte(expectedUsdcAmountForLend); + expect(userUsdcStableDebtAmount).to.be.lt(expectedUsdcAmountForLend); + expect(aWETHBalance).to.be.lt(aWETHBalanceBefore); + expect(aLendBalance).to.be.lt(aLendBalanceBefore); + }); + + it('should swap tokens and repay debt for multiple tokens using permit', async () => { + const { + users, + pool, + weth, + oracle, + dai, + uniswapRepayAdapter, + lend, + usdc, + helpersContract, + aWETH, + } = testEnv; + const user = users[0].signer; + const userAddress = users[0].address; + const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID; + const deadline = MAX_UINT_AMOUNT; + + const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey; + if (!ownerPrivateKey) { + throw new Error('INVALID_OWNER_PK'); + } + + const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10'); + const amountLendToSwap = await convertToCurrencyDecimals(lend.address, '1'); + + const daiPrice = await oracle.getAssetPrice(dai.address); + const expectedDaiAmountForEth = await convertToCurrencyDecimals( + dai.address, + new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) + ); + + const lendPrice = await oracle.getAssetPrice(lend.address); + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const collateralDecimals = (await lend.decimals()).toString(); + const principalDecimals = (await usdc.decimals()).toString(); + + const expectedUsdcAmountForLend = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(amountLendToSwap.toString()) + .times( + new BigNumber(lendPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) + ) + .toFixed(0) + ); + + // Open user Debt + await pool.connect(user).borrow(dai.address, expectedDaiAmountForEth, 1, 0, userAddress); + await pool.connect(user).borrow(usdc.address, expectedUsdcAmountForLend, 1, 0, userAddress); + + const daiStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(dai.address) + ).stableDebtTokenAddress; + + const daiStableDebtContract = await getContract( + eContractid.StableDebtToken, + daiStableDebtTokenAddress + ); + + const usdcStableDebtTokenAddress = ( + await helpersContract.getReserveTokensAddresses(usdc.address) + ).stableDebtTokenAddress; + + const usdcStableDebtContract = await getContract( + eContractid.StableDebtToken, + usdcStableDebtTokenAddress + ); + + const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress); + const userUsdcStableDebtAmountBefore = await usdcStableDebtContract.balanceOf(userAddress); + + const lendData = await pool.getReserveData(lend.address); + const aLend = await getContract(eContractid.AToken, lendData.aTokenAddress); + + const aWETHBalanceBefore = await aWETH.balanceOf(userAddress); + const aLendBalanceBefore = await aLend.balanceOf(userAddress); + + // IMPORTANT: Round down to work equal to solidity to get the correct value for permit call + BigNumber.config({ + ROUNDING_MODE: 1, //round down + }); + + const wethFlashloanAmountBN = new BigNumber(amountWETHtoSwap.toString()).div(1.0009); + const wethFlashloanAmount = wethFlashloanAmountBN.toFixed(0); + const wethFlashloanFee = wethFlashloanAmountBN.multipliedBy(9).div(10000); + const wethAmountToPermit = wethFlashloanAmountBN.plus(wethFlashloanFee).toFixed(0); + + const lendFlashloanAmountBN = new BigNumber(amountLendToSwap.toString()).div(1.0009); + const lendFlashloanAmount = lendFlashloanAmountBN.toFixed(0); + const lendFlashloanFee = lendFlashloanAmountBN.multipliedBy(9).div(10000); + const lendAmountToPermit = lendFlashloanAmountBN.plus(lendFlashloanFee).toFixed(0); + + const aWethNonce = (await aWETH._nonces(userAddress)).toNumber(); + const aWethMsgParams = buildPermitParams( + chainId, + aWETH.address, + '1', + await aWETH.name(), + userAddress, + uniswapRepayAdapter.address, + aWethNonce, + deadline, + wethAmountToPermit.toString() + ); + const {v: aWETHv, r: aWETHr, s: aWETHs} = getSignatureFromTypedData( + ownerPrivateKey, + aWethMsgParams + ); + + const aLendNonce = (await aLend._nonces(userAddress)).toNumber(); + const aLendMsgParams = buildPermitParams( + chainId, + aLend.address, + '1', + await aLend.name(), + userAddress, + uniswapRepayAdapter.address, + aLendNonce, + deadline, + lendAmountToPermit.toString() + ); + const {v: aLendv, r: aLendr, s: aLends} = getSignatureFromTypedData( + ownerPrivateKey, + aLendMsgParams + ); + + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, wethFlashloanAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(lend.address, lendFlashloanAmount); + + const params = ethers.utils.defaultAbiCoder.encode( + [ + 'address[]', + 'uint256', + 'uint256[]', + 'uint256[]', + 'uint256[]', + 'uint8[]', + 'bytes32[]', + 'bytes32[]', + ], + [ + [dai.address, usdc.address], + 0, + [expectedDaiAmountForEth, expectedUsdcAmountForLend], + [1, 1], + [deadline, deadline], + [aWETHv, aLendv], + [aWETHr, aLendr], + [aWETHs, aLends], + ] + ); + + await pool + .connect(user) + .flashLoan( + uniswapRepayAdapter.address, + [weth.address, lend.address], + [wethFlashloanAmount.toString(), lendFlashloanAmount.toString()], + [0, 0], + userAddress, + params, + 0 + ); + + const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address); + const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address); + const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress); + const userUsdcStableDebtAmount = await usdcStableDebtContract.balanceOf(userAddress); + const aWETHBalance = await aWETH.balanceOf(userAddress); + const aLendBalance = await aLend.balanceOf(userAddress); + + expect(adapterWethBalance).to.be.eq(Zero); + expect(adapterDaiBalance).to.be.eq(Zero); + expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmountForEth); + expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmountForEth); + expect(userUsdcStableDebtAmountBefore).to.be.gte(expectedUsdcAmountForLend); + expect(userUsdcStableDebtAmount).to.be.lt(expectedUsdcAmountForLend); + expect(aWETHBalance).to.be.lt(aWETHBalanceBefore); + expect(aLendBalance).to.be.lt(aLendBalanceBefore); + + // Restore round up + BigNumber.config({ + ROUNDING_MODE: 0, //round up + }); + }); + it('should revert if inconsistent params', async () => { const {users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter} = testEnv; const user = users[0].signer; @@ -1198,8 +2064,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { // Subtract the FL fee from the amount to be swapped 0,09% const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount); const params1 = ethers.utils.defaultAbiCoder.encode( [ @@ -1489,8 +2354,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { // Subtract the FL fee from the amount to be swapped 0,09% const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount); const params = ethers.utils.defaultAbiCoder.encode( [ @@ -1553,8 +2417,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { // Subtract the FL fee from the amount to be swapped 0,09% const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount); const params = ethers.utils.defaultAbiCoder.encode( [ @@ -1616,8 +2479,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { // Subtract the FL fee from the amount to be swapped 0,09% const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); - await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount); const params = ethers.utils.defaultAbiCoder.encode( [ @@ -1679,8 +2541,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const bigMaxAmountToSwap = amountWETHtoSwap.mul(2); const flashloanAmount = new BigNumber(bigMaxAmountToSwap.toString()).div(1.0009).toFixed(0); - await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, flashloanAmount); const params = ethers.utils.defaultAbiCoder.encode( [ @@ -1769,8 +2630,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const leftOverWeth = new BigNumber(flashloanAmount).minus(actualWEthSwapped); - await mockUniswapRouter.connect(user).setAmountToSwap(actualWEthSwapped); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); const params = ethers.utils.defaultAbiCoder.encode( [ @@ -1876,8 +2736,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const leftOverWeth = new BigNumber(flashloanAmount).minus(actualWEthSwapped); - await mockUniswapRouter.connect(user).setAmountToSwap(actualWEthSwapped); - await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount); + await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped); const wethBalanceBefore = await weth.balanceOf(userAddress);