mirror of
				https://github.com/Instadapp/aave-protocol-v2.git
				synced 2024-07-29 21:47:30 +00:00 
			
		
		
		
	Add swapAllBalance parameter for liquidity swap
This commit is contained in:
		
							parent
							
								
									48b9a603a7
								
							
						
					
					
						commit
						20bbae88d3
					
				|  | @ -124,7 +124,7 @@ contract BaseUniswapAdapter { | |||
|    * @param minAmountOut the min amount of `assetToSwapTo` to be received from the swap | ||||
|    * @return the amount received from the swap | ||||
|    */ | ||||
|   function swapExactTokensForTokens( | ||||
|   function _swapExactTokensForTokens( | ||||
|     address assetToSwapFrom, | ||||
|     address assetToSwapTo, | ||||
|     uint256 amountToSwap, | ||||
|  | @ -167,7 +167,7 @@ contract BaseUniswapAdapter { | |||
|    * @param amountToReceive Exact amount of `assetToSwapTo` to receive | ||||
|    * @return the amount swapped | ||||
|    */ | ||||
|   function swapTokensForExactTokens( | ||||
|   function _swapTokensForExactTokens( | ||||
|     address assetToSwapFrom, | ||||
|     address assetToSwapTo, | ||||
|     uint256 maxAmountToSwap, | ||||
|  | @ -222,7 +222,7 @@ contract BaseUniswapAdapter { | |||
|    * @dev Get the aToken associated to the asset | ||||
|    * @return address of the aToken | ||||
|    */ | ||||
|   function getAToken(address asset) internal view returns (address) { | ||||
|   function _getAToken(address asset) internal view returns (address) { | ||||
|     ReserveLogic.ReserveData memory reserve = POOL.getReserveData(asset); | ||||
|     return reserve.aTokenAddress; | ||||
|   } | ||||
|  | @ -236,7 +236,7 @@ contract BaseUniswapAdapter { | |||
|    *     (1) Direct transfer to user | ||||
|    * @param user address | ||||
|    */ | ||||
|   function sendLeftovers(address asset, uint256 reservedAmount, LeftoverAction leftOverAction, address user) internal { | ||||
|   function _sendLeftovers(address asset, uint256 reservedAmount, LeftoverAction leftOverAction, address user) internal { | ||||
|     uint256 balance = IERC20(asset).balanceOf(address(this)); | ||||
|     uint256 assetLeftOver = balance.sub(reservedAmount); | ||||
| 
 | ||||
|  | @ -253,18 +253,18 @@ contract BaseUniswapAdapter { | |||
|   /** | ||||
|    * @dev Pull the ATokens from the user | ||||
|    * @param reserve address of the asset | ||||
|    * @param reserveAToken address of the aToken of the reserve | ||||
|    * @param user address | ||||
|    * @param amount of tokens to be transferred to the contract | ||||
|    * @param permitSignature struct containing the permit signature | ||||
|    */ | ||||
|   function pullAToken( | ||||
|   function _pullAToken( | ||||
|     address reserve, | ||||
|     address reserveAToken, | ||||
|     address user, | ||||
|     uint256 amount, | ||||
|     PermitSignature memory permitSignature | ||||
|   ) internal { | ||||
|     address reserveAToken = getAToken(reserve); | ||||
| 
 | ||||
|     if (_usePermit(permitSignature)) { | ||||
|       IERC20WithPermit(reserveAToken).permit( | ||||
|         user, | ||||
|  | @ -284,25 +284,6 @@ contract BaseUniswapAdapter { | |||
|     POOL.withdraw(reserve, amount, address(this)); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @dev Pull the ATokens from the user and use them to repay the flashloan | ||||
|    * @param reserve address of the asset | ||||
|    * @param user address | ||||
|    * @param flashLoanDebt need to be repaid | ||||
|    * @param permitSignature struct containing the permit signature | ||||
|    */ | ||||
|   function pullATokenAndRepayFlashLoan( | ||||
|     address reserve, | ||||
|     address user, | ||||
|     uint256 flashLoanDebt, | ||||
|     PermitSignature memory permitSignature | ||||
|   ) internal { | ||||
|     pullAToken(reserve, user, flashLoanDebt, permitSignature); | ||||
| 
 | ||||
|     // Repay flashloan | ||||
|     IERC20(reserve).approve(address(POOL), flashLoanDebt); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @dev Tells if the permit method should be called by inspecting if there is a valid signature. | ||||
|    * If signature params are set to 0, then permit won't be called. | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|   struct SwapParams { | ||||
|     address[] assetToSwapToList; | ||||
|     uint256[] minAmountsToReceive; | ||||
|     bool[] swapAllBalance; | ||||
|     PermitParams permitParams; | ||||
|   } | ||||
| 
 | ||||
|  | @ -41,6 +42,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|    * @param params Additional variadic field to include extra params. Expected parameters: | ||||
|    *   address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited | ||||
|    *   uint256[] minAmountsToReceive List of min amounts to be received from the swap | ||||
|    *   bool[] swapAllBalance Flag indicating if all the user balance should be swapped | ||||
|    *   uint256[] deadline List of deadlines for the permit signature | ||||
|    *   uint8[] v List of v param for the permit signature | ||||
|    *   bytes32[] r List of r param for the permit signature | ||||
|  | @ -60,6 +62,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|     require( | ||||
|       assets.length == decodedParams.assetToSwapToList.length | ||||
|       && assets.length == decodedParams.minAmountsToReceive.length | ||||
|       && assets.length == decodedParams.swapAllBalance.length | ||||
|       && assets.length == decodedParams.permitParams.deadline.length | ||||
|       && assets.length == decodedParams.permitParams.v.length | ||||
|       && assets.length == decodedParams.permitParams.r.length | ||||
|  | @ -68,22 +71,14 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|     ); | ||||
| 
 | ||||
|     for (uint256 i = 0; i < assets.length; i++) { | ||||
|       uint256 receivedAmount = swapExactTokensForTokens( | ||||
|       _swapLiquidity( | ||||
|         assets[i], | ||||
|         decodedParams.assetToSwapToList[i], | ||||
|         amounts[i], | ||||
|         decodedParams.minAmountsToReceive[i] | ||||
|       ); | ||||
| 
 | ||||
|       // Deposit new reserve | ||||
|       IERC20(decodedParams.assetToSwapToList[i]).approve(address(POOL), receivedAmount); | ||||
|       POOL.deposit(decodedParams.assetToSwapToList[i], receivedAmount, initiator, 0); | ||||
| 
 | ||||
|       uint256 flashLoanDebt = amounts[i].add(premiums[i]); | ||||
|       pullATokenAndRepayFlashLoan( | ||||
|         assets[i], | ||||
|         premiums[i], | ||||
|         initiator, | ||||
|         flashLoanDebt, | ||||
|         decodedParams.minAmountsToReceive[i], | ||||
|         decodedParams.swapAllBalance[i], | ||||
|         PermitSignature( | ||||
|           decodedParams.permitParams.deadline[i], | ||||
|           decodedParams.permitParams.v[i], | ||||
|  | @ -103,7 +98,7 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|    * perform the swap. | ||||
|    * @param assetToSwapFromList List of addresses of the underlying asset to be swap from | ||||
|    * @param assetToSwapToList List of addresses of the underlying asset to be swap to and deposited | ||||
|    * @param amountToSwapList List of amounts to be swapped | ||||
|    * @param amountToSwapList List of amounts to be swapped. If the amount exceeds the balance, the total balance is used for the swap | ||||
|    * @param minAmountsToReceive List of min amounts to be received from the swap | ||||
|    * @param permitParams List of struct containing the permit signatures | ||||
|    *   uint256[] deadline List of deadlines for the permit signature | ||||
|  | @ -127,17 +122,23 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|     ); | ||||
| 
 | ||||
|     for (uint256 i = 0; i < assetToSwapFromList.length; i++) { | ||||
|       pullAToken( | ||||
|       address aToken = _getAToken(assetToSwapFromList[i]); | ||||
| 
 | ||||
|       uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(msg.sender); | ||||
|       uint256 amountToSwap = amountToSwapList[i] > aTokenInitiatorBalance ? aTokenInitiatorBalance : amountToSwapList[i]; | ||||
| 
 | ||||
|       _pullAToken( | ||||
|         assetToSwapFromList[i], | ||||
|         aToken, | ||||
|         msg.sender, | ||||
|         amountToSwapList[i], | ||||
|         amountToSwap, | ||||
|         permitParams[i] | ||||
|       ); | ||||
| 
 | ||||
|       uint256 receivedAmount = swapExactTokensForTokens( | ||||
|       uint256 receivedAmount = _swapExactTokensForTokens( | ||||
|         assetToSwapFromList[i], | ||||
|         assetToSwapToList[i], | ||||
|         amountToSwapList[i], | ||||
|         amountToSwap, | ||||
|         minAmountsToReceive[i] | ||||
|       ); | ||||
| 
 | ||||
|  | @ -147,12 +148,61 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @dev Swaps an `amountToSwap` of an asset to another and deposits the funds on behalf of the initiator. | ||||
|    * @param assetFrom Address of the underlying asset to be swap from | ||||
|    * @param assetTo Address of the underlying asset to be swap to and deposited | ||||
|    * @param amount Amount from flashloan | ||||
|    * @param premium Premium of the flashloan | ||||
|    * @param minAmountToReceive Min amount to be received from the swap | ||||
|    * @param swapAllBalance Flag indicating if all the user balance should be swapped | ||||
|    * @param permitSignature List of struct containing the permit signature | ||||
|    */ | ||||
|   function _swapLiquidity( | ||||
|     address assetFrom, | ||||
|     address assetTo, | ||||
|     uint256 amount, | ||||
|     uint256 premium, | ||||
|     address initiator, | ||||
|     uint256 minAmountToReceive, | ||||
|     bool swapAllBalance, | ||||
|     PermitSignature memory permitSignature | ||||
|   ) internal { | ||||
|     address aToken = _getAToken(assetFrom); | ||||
| 
 | ||||
|     uint256 aTokenInitiatorBalance = IERC20(aToken).balanceOf(initiator); | ||||
|     uint256 amountToSwap = swapAllBalance ? aTokenInitiatorBalance.sub(premium) : amount; | ||||
| 
 | ||||
|     uint256 receivedAmount = _swapExactTokensForTokens( | ||||
|       assetFrom, | ||||
|       assetTo, | ||||
|       amountToSwap, | ||||
|       minAmountToReceive | ||||
|     ); | ||||
| 
 | ||||
|     // Deposit new reserve | ||||
|     IERC20(assetTo).approve(address(POOL), receivedAmount); | ||||
|     POOL.deposit(assetTo, receivedAmount, initiator, 0); | ||||
| 
 | ||||
|     uint256 flashLoanDebt = amount.add(premium); | ||||
|     uint256 amountToPull = swapAllBalance ? aTokenInitiatorBalance : flashLoanDebt; | ||||
| 
 | ||||
|     _pullATokenAndRepayFlashLoan( | ||||
|       assetFrom, | ||||
|       aToken, | ||||
|       initiator, | ||||
|       amountToPull, | ||||
|       flashLoanDebt, | ||||
|       permitSignature | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  * @dev Decodes debt information encoded in flashloan params | ||||
|  * @param params Additional variadic field to include extra params. Expected parameters: | ||||
|    *   address[] assetToSwapToList List of the addresses of the reserve to be swapped to and deposited | ||||
|    *   uint256[] minAmountsToReceive List of min amounts to be received from the swap | ||||
|    *   uint256[] deadline List of deadlines for the permit signature | ||||
|    *   bool[] swapAllBalance Flag indicating if all the user balance should be swapped | ||||
|    *   uint256[] deadline List of deadlines for the permit signature | ||||
|    *   uint8[] v List of v param for the permit signature | ||||
|    *   bytes32[] r List of r param for the permit signature | ||||
|  | @ -163,12 +213,36 @@ contract UniswapLiquiditySwapAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|     ( | ||||
|       address[] memory assetToSwapToList, | ||||
|       uint256[] memory minAmountsToReceive, | ||||
|       bool[] memory swapAllBalance, | ||||
|       uint256[] memory deadline, | ||||
|       uint8[] memory v, | ||||
|       bytes32[] memory r, | ||||
|       bytes32[] memory s | ||||
|     ) = abi.decode(params, (address[], uint256[], uint256[], uint8[], bytes32[], bytes32[])); | ||||
|     ) = abi.decode(params, (address[], uint256[], bool[], uint256[], uint8[], bytes32[], bytes32[])); | ||||
| 
 | ||||
|     return SwapParams(assetToSwapToList, minAmountsToReceive, PermitParams(deadline, v, r, s)); | ||||
|     return SwapParams(assetToSwapToList, minAmountsToReceive, swapAllBalance, PermitParams(deadline, v, r, s)); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|   * @dev Pull the ATokens from the user and use them to repay the flashloan | ||||
|   * @param reserve address of the asset | ||||
|   * @param reserveAToken address of the aToken of the reserve | ||||
|   * @param user address | ||||
|   * @param amountToPull amount to be pulled from the user | ||||
|   * @param flashLoanDebt need to be repaid | ||||
|   * @param permitSignature struct containing the permit signature | ||||
|   */ | ||||
|   function _pullATokenAndRepayFlashLoan( | ||||
|     address reserve, | ||||
|     address reserveAToken, | ||||
|     address user, | ||||
|     uint256 amountToPull, | ||||
|     uint256 flashLoanDebt, | ||||
|     PermitSignature memory permitSignature | ||||
|   ) internal { | ||||
|     _pullAToken(reserve, reserveAToken, user, amountToPull, permitSignature); | ||||
| 
 | ||||
|     // Repay flashloan | ||||
|     IERC20(reserve).approve(address(POOL), flashLoanDebt); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -119,17 +119,17 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
|     uint256 premium, | ||||
|     PermitSignature memory permitSignature | ||||
|   ) internal { | ||||
|     swapTokensForExactTokens(assetFrom, assetTo, amount, repayAmount); | ||||
|     _swapTokensForExactTokens(assetFrom, assetTo, amount, repayAmount); | ||||
| 
 | ||||
|     // Repay debt | ||||
|     IERC20(assetTo).approve(address(POOL), repayAmount); | ||||
|     POOL.repay(assetTo, repayAmount, rateMode, initiator); | ||||
| 
 | ||||
|     uint256 flashLoanDebt = amount.add(premium); | ||||
|     pullATokenAndRepayFlashLoan(assetFrom, initiator, flashLoanDebt, permitSignature); | ||||
|     _pullATokenAndRepayFlashLoan(assetFrom, initiator, flashLoanDebt, permitSignature); | ||||
| 
 | ||||
|     // Take care of reserve leftover from the swap | ||||
|     sendLeftovers(assetFrom, flashLoanDebt, leftOverAction, initiator); | ||||
|     _sendLeftovers(assetFrom, flashLoanDebt, leftOverAction, initiator); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -161,15 +161,35 @@ contract UniswapRepayAdapter is BaseUniswapAdapter, IFlashLoanReceiver { | |||
| 
 | ||||
|     return RepayParams( | ||||
|       assetToSwapToList, | ||||
|         leftOverAction, | ||||
|         repayAmounts, | ||||
|         rateModes, | ||||
|         PermitParams( | ||||
|           deadline, | ||||
|           v, | ||||
|           r, | ||||
|           s | ||||
|         ) | ||||
|       leftOverAction, | ||||
|       repayAmounts, | ||||
|       rateModes, | ||||
|       PermitParams( | ||||
|         deadline, | ||||
|         v, | ||||
|         r, | ||||
|         s | ||||
|       ) | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @dev Pull the ATokens from the user and use them to repay the flashloan | ||||
|    * @param reserve address of the asset | ||||
|    * @param user address | ||||
|    * @param flashLoanDebt need to be repaid | ||||
|    * @param permitSignature struct containing the permit signature | ||||
|    */ | ||||
|   function _pullATokenAndRepayFlashLoan( | ||||
|     address reserve, | ||||
|     address user, | ||||
|     uint256 flashLoanDebt, | ||||
|     PermitSignature memory permitSignature | ||||
|   ) internal { | ||||
|     address reserveAToken = _getAToken(reserve); | ||||
|     _pullAToken(reserve, reserveAToken, user, flashLoanDebt, permitSignature); | ||||
| 
 | ||||
|     // Repay flashloan | ||||
|     IERC20(reserve).approve(address(POOL), flashLoanDebt); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -301,12 +301,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|  | @ -411,12 +412,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|           .toFixed(0); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, dai.address], | ||||
|             [expectedDaiAmountForEth, expectedDaiAmountForUsdc], | ||||
|             [0, 0], | ||||
|             [0, 0], | ||||
|             [0, 0], | ||||
|             [ | ||||
|               '0x0000000000000000000000000000000000000000000000000000000000000000', | ||||
|               '0x0000000000000000000000000000000000000000000000000000000000000000', | ||||
|  | @ -572,10 +574,11 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         ); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, dai.address], | ||||
|             [expectedDaiAmountForEth, expectedDaiAmountForUsdc], | ||||
|             [0, 0], | ||||
|             [deadline, deadline], | ||||
|             [aWETHv, aUsdcv], | ||||
|             [aWETHr, aUsdcr], | ||||
|  | @ -673,8 +676,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         const {v, r, s} = getSignatureFromTypedData(ownerPrivateKey, msgParams); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [[dai.address], [expectedDaiAmount], [deadline], [v], [r], [s]] | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [[dai.address], [expectedDaiAmount], [0], [deadline], [v], [r], [s]] | ||||
|         ); | ||||
| 
 | ||||
|         await expect( | ||||
|  | @ -738,12 +741,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, weth.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|  | @ -764,11 +768,12 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         ).to.be.revertedWith('INCONSISTENT_PARAMS'); | ||||
| 
 | ||||
|         const params2 = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, weth.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0, 0], | ||||
|             [0, 0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|  | @ -790,10 +795,11 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         ).to.be.revertedWith('INCONSISTENT_PARAMS'); | ||||
| 
 | ||||
|         const params3 = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, weth.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0, 0], | ||||
|             [0], | ||||
|             [0, 0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|  | @ -816,12 +822,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         ).to.be.revertedWith('INCONSISTENT_PARAMS'); | ||||
| 
 | ||||
|         const params4 = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, weth.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             [ | ||||
|               '0x0000000000000000000000000000000000000000000000000000000000000000', | ||||
|               '0x0000000000000000000000000000000000000000000000000000000000000000', | ||||
|  | @ -845,12 +852,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         ).to.be.revertedWith('INCONSISTENT_PARAMS'); | ||||
| 
 | ||||
|         const params5 = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, weth.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             [ | ||||
|               '0x0000000000000000000000000000000000000000000000000000000000000000', | ||||
|  | @ -874,12 +882,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         ).to.be.revertedWith('INCONSISTENT_PARAMS'); | ||||
| 
 | ||||
|         const params6 = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address, weth.address], | ||||
|             [expectedDaiAmount, expectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|  | @ -898,6 +907,33 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|               0 | ||||
|             ) | ||||
|         ).to.be.revertedWith('INCONSISTENT_PARAMS'); | ||||
| 
 | ||||
|         const params7 = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0, 0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|         ); | ||||
| 
 | ||||
|         await expect( | ||||
|           pool | ||||
|             .connect(user) | ||||
|             .flashLoan( | ||||
|               uniswapLiquiditySwapAdapter.address, | ||||
|               [weth.address], | ||||
|               [flashloanAmount.toString()], | ||||
|               [0], | ||||
|               userAddress, | ||||
|               params7, | ||||
|               0 | ||||
|             ) | ||||
|         ).to.be.revertedWith('INCONSISTENT_PARAMS'); | ||||
|       }); | ||||
| 
 | ||||
|       it('should revert if caller not lending pool', async () => { | ||||
|  | @ -923,12 +959,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|  | @ -1003,12 +1040,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         const flashloanAmount = new BigNumber(amountUSDCtoSwap.toString()).div(1.0009).toFixed(0); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address], | ||||
|             [expectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|  | @ -1068,12 +1106,13 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address], | ||||
|             [smallExpectedDaiAmount], | ||||
|             [0], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|  | @ -1093,6 +1132,81 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|             ) | ||||
|         ).to.be.revertedWith('minAmountOut exceed max slippage'); | ||||
|       }); | ||||
| 
 | ||||
|       it('should correctly swap tokens all the balance', async () => { | ||||
|         const {users, weth, oracle, dai, aDai, aWETH, 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 expectedDaiAmount = await convertToCurrencyDecimals( | ||||
|           dai.address, | ||||
|           new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) | ||||
|         ); | ||||
| 
 | ||||
|         await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); | ||||
| 
 | ||||
|         // Remove other balance
 | ||||
|         await aWETH.connect(user).transfer(users[1].address, parseEther('90')); | ||||
|         const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); | ||||
| 
 | ||||
|         // User will swap liquidity 10 aEth to aDai
 | ||||
|         const liquidityToSwap = parseEther('10'); | ||||
|         expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); | ||||
|         await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); | ||||
| 
 | ||||
|         const params = ethers.utils.defaultAbiCoder.encode( | ||||
|           ['address[]', 'uint256[]', 'bool[]', 'uint256[]', 'uint8[]', 'bytes32[]', 'bytes32[]'], | ||||
|           [ | ||||
|             [dai.address], | ||||
|             [expectedDaiAmount], | ||||
|             [1], | ||||
|             [0], | ||||
|             [0], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|             ['0x0000000000000000000000000000000000000000000000000000000000000000'], | ||||
|           ] | ||||
|         ); | ||||
| 
 | ||||
|         // Flashloan + premium > aToken balance. Then it will only swap the balance
 | ||||
|         const flashloanFee = liquidityToSwap.mul(9).div(10000); | ||||
|         const swappedAmount = liquidityToSwap.sub(flashloanFee); | ||||
| 
 | ||||
|         await expect( | ||||
|           pool | ||||
|             .connect(user) | ||||
|             .flashLoan( | ||||
|               uniswapLiquiditySwapAdapter.address, | ||||
|               [weth.address], | ||||
|               [liquidityToSwap.toString()], | ||||
|               [0], | ||||
|               userAddress, | ||||
|               params, | ||||
|               0 | ||||
|             ) | ||||
|         ) | ||||
|           .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') | ||||
|           .withArgs(weth.address, dai.address, swappedAmount.toString(), expectedDaiAmount); | ||||
| 
 | ||||
|         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 adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); | ||||
| 
 | ||||
|         expect(adapterWethBalance).to.be.eq(Zero); | ||||
|         expect(adapterDaiBalance).to.be.eq(Zero); | ||||
|         expect(adapterDaiAllowance).to.be.eq(Zero); | ||||
|         expect(userADaiBalance).to.be.eq(expectedDaiAmount); | ||||
|         expect(userAEthBalance).to.be.eq(Zero); | ||||
|         expect(adapterAEthBalance).to.be.eq(Zero); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     describe('swapAndDeposit', () => { | ||||
|  | @ -1607,6 +1721,72 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { | |||
|         expect(userAUsdcBalance).to.be.lt(userAUsdcBalanceBefore); | ||||
|         expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap)); | ||||
|       }); | ||||
| 
 | ||||
|       it('should correctly swap all the balance when using a bigger amount', async () => { | ||||
|         const {users, weth, oracle, dai, aDai, aWETH, 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 expectedDaiAmount = await convertToCurrencyDecimals( | ||||
|           dai.address, | ||||
|           new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0) | ||||
|         ); | ||||
| 
 | ||||
|         await mockUniswapRouter.setAmountToReturn(weth.address, expectedDaiAmount); | ||||
| 
 | ||||
|         // Remove other balance
 | ||||
|         await aWETH.connect(user).transfer(users[1].address, parseEther('90')); | ||||
|         const userAEthBalanceBefore = await aWETH.balanceOf(userAddress); | ||||
| 
 | ||||
|         // User will swap liquidity 10 aEth to aDai
 | ||||
|         const liquidityToSwap = parseEther('10'); | ||||
|         expect(userAEthBalanceBefore).to.be.eq(liquidityToSwap); | ||||
| 
 | ||||
|         // User will swap liquidity 10 aEth to aDai
 | ||||
|         await aWETH.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap); | ||||
| 
 | ||||
|         // Only has 10 atokens, so all the balance will be swapped
 | ||||
|         const bigAmountToSwap = parseEther('100'); | ||||
| 
 | ||||
|         await expect( | ||||
|           uniswapLiquiditySwapAdapter.connect(user).swapAndDeposit( | ||||
|             [weth.address], | ||||
|             [dai.address], | ||||
|             [bigAmountToSwap], | ||||
|             [expectedDaiAmount], | ||||
|             [ | ||||
|               { | ||||
|                 deadline: 0, | ||||
|                 v: 0, | ||||
|                 r: '0x0000000000000000000000000000000000000000000000000000000000000000', | ||||
|                 s: '0x0000000000000000000000000000000000000000000000000000000000000000', | ||||
|               }, | ||||
|             ] | ||||
|           ) | ||||
|         ) | ||||
|           .to.emit(uniswapLiquiditySwapAdapter, 'Swapped') | ||||
|           .withArgs(weth.address, dai.address, amountWETHtoSwap.toString(), expectedDaiAmount); | ||||
| 
 | ||||
|         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 adapterAEthBalance = await aWETH.balanceOf(uniswapLiquiditySwapAdapter.address); | ||||
| 
 | ||||
|         expect(adapterWethBalance).to.be.eq(Zero); | ||||
|         expect(adapterDaiBalance).to.be.eq(Zero); | ||||
|         expect(adapterDaiAllowance).to.be.eq(Zero); | ||||
|         expect(userADaiBalance).to.be.eq(expectedDaiAmount); | ||||
|         expect(userAEthBalance).to.be.eq(Zero); | ||||
|         expect(adapterAEthBalance).to.be.eq(Zero); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Gerardo Nardelli
						Gerardo Nardelli