From 913a6a923756297b45d0ce6bd40d03414fd8df9a Mon Sep 17 00:00:00 2001 From: eboado Date: Thu, 29 Oct 2020 15:14:28 +0100 Subject: [PATCH 1/6] - Added batch of modes to flashLoan() --- contracts/interfaces/ILendingPool.sol | 6 ++--- contracts/lendingpool/LendingPool.sol | 13 +++++----- contracts/libraries/logic/ValidationLogic.sol | 17 +++++++++--- test/flashloan.spec.ts | 26 +++++++++---------- test/pausable-functions.spec.ts | 2 +- 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index f44a458a..4d12b60f 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -106,7 +106,7 @@ interface ILendingPool { **/ event FlashLoan( address indexed target, - uint256 mode, + uint256[] modes, address[] assets, uint256[] amounts, uint256[] premiums, @@ -286,7 +286,7 @@ interface ILendingPool { * @param receiver The address of the contract receiving the funds. The receiver should implement the IFlashLoanReceiver interface. * @param assets the address of the principal reserve * @param amounts the amount requested for this flashloan - * @param mode the flashloan mode + * @param modes the flashloan mode * @param params a bytes array to be sent to the flashloan executor * @param referralCode the referral code of the caller **/ @@ -294,7 +294,7 @@ interface ILendingPool { address receiver, address[] calldata assets, uint256[] calldata amounts, - uint256 mode, + uint256[] calldata modes, bytes calldata params, uint16 referralCode ) external; diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index b0f960b3..618bd508 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -502,7 +502,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * @param receiverAddress The address of the contract receiving the funds. The receiver should implement the IFlashLoanReceiver interface. * @param assets The addresss of the assets being flashborrowed * @param amounts The amounts requested for this flashloan for each asset - * @param mode Type of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable + * @param modes Types of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable * @param params Variadic packed params to pass to the receiver as extra information * @param referralCode Referral code of the flash loan **/ @@ -510,7 +510,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage address receiverAddress, address[] calldata assets, uint256[] calldata amounts, - uint256 mode, + uint256[] calldata modes, bytes calldata params, uint16 referralCode ) external override { @@ -518,13 +518,12 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage FlashLoanLocalVars memory vars; - ValidationLogic.validateFlashloan(assets, amounts, mode); + ValidationLogic.validateFlashloan(assets, amounts, modes); address[] memory aTokenAddresses = new address[](assets.length); uint256[] memory premiums = new uint256[](assets.length); vars.receiver = IFlashLoanReceiver(receiverAddress); - vars.debtMode = ReserveLogic.InterestRateMode(mode); for (vars.i = 0; vars.i < assets.length; vars.i++) { aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress; @@ -546,7 +545,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage vars.currentAmount = amounts[vars.i]; vars.currentPremium = premiums[vars.i]; vars.currentATokenAddress = aTokenAddresses[vars.i]; - + vars.debtMode = ReserveLogic.InterestRateMode(modes[vars.i]); vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium); if (vars.debtMode == ReserveLogic.InterestRateMode.NONE) { @@ -576,14 +575,14 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage msg.sender, msg.sender, vars.currentAmount, - mode, + modes[vars.i], vars.currentATokenAddress, referralCode, false ) ); } - emit FlashLoan(receiverAddress, mode, assets, amounts, premiums, referralCode); + emit FlashLoan(receiverAddress, modes, assets, amounts, premiums, referralCode); } } diff --git a/contracts/libraries/logic/ValidationLogic.sol b/contracts/libraries/logic/ValidationLogic.sol index 947d84ea..c2019fd6 100644 --- a/contracts/libraries/logic/ValidationLogic.sol +++ b/contracts/libraries/logic/ValidationLogic.sol @@ -326,17 +326,26 @@ library ValidationLogic { /** * @dev validates a flashloan action - * @param mode the flashloan mode (0 = classic flashloan, 1 = open a stable rate loan, 2 = open a variable rate loan) + * @param modes the flashloan modes (0 = classic flashloan, 1 = open a stable rate loan, 2 = open a variable rate loan) * @param assets the assets being flashborrowed * @param amounts the amounts for each asset being borrowed **/ function validateFlashloan( address[] memory assets, uint256[] memory amounts, - uint256 mode + uint256[] memory modes ) internal pure { - require(mode <= uint256(ReserveLogic.InterestRateMode.VARIABLE), Errors.INVALID_FLASHLOAN_MODE); - require(assets.length == amounts.length, Errors.INCONSISTENT_FLASHLOAN_PARAMS); + require( + assets.length == amounts.length && assets.length == modes.length, + Errors.INCONSISTENT_FLASHLOAN_PARAMS + ); + + for (uint256 i = 0; i < modes.length; i++) { + require( + modes[i] <= uint256(ReserveLogic.InterestRateMode.VARIABLE), + Errors.INVALID_FLASHLOAN_MODE + ); + } } /** diff --git a/test/flashloan.spec.ts b/test/flashloan.spec.ts index 305d674f..6df207c8 100644 --- a/test/flashloan.spec.ts +++ b/test/flashloan.spec.ts @@ -47,7 +47,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 0, + [0], '0x10', '0' ); @@ -76,7 +76,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], ['1000720000000000000'], - 0, + [0], '0x10', '0' ); @@ -107,7 +107,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 0, + [0], '0x10', '0' ) @@ -127,7 +127,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 0, + [0], '0x10', '0' ) @@ -147,7 +147,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 4, + [4], '0x10', '0' ) @@ -175,7 +175,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 2, + [2], '0x10', '0' ); @@ -201,7 +201,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], ['1004415000000000000'], //slightly higher than the available liquidity - 2, + [2], '0x10', '0' ), @@ -213,7 +213,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const {pool, deployer, weth} = testEnv; await expect( - pool.flashLoan(deployer.address, [weth.address], ['1000000000000000000'], 2, '0x10', '0') + pool.flashLoan(deployer.address, [weth.address], ['1000000000000000000'], [2], '0x10', '0') ).to.be.reverted; }); @@ -241,7 +241,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], - 0, + [0], '0x10', '0' ); @@ -283,7 +283,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], - 2, + [2], '0x10', '0' ) @@ -309,7 +309,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], 2, '0x10', '0'); + .flashLoan(_mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], [2], '0x10', '0'); const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( usdc.address ); @@ -344,7 +344,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await expect( pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 0, '0x10', '0') + .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], [0], '0x10', '0') ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); }); @@ -359,7 +359,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0'); + .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], [1], '0x10', '0'); const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index 2bf8be21..ae7e3874 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -187,7 +187,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await expect( pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0') + .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], [1], '0x10', '0') ).revertedWith(IS_PAUSED); // Unpause pool From de7ec39f24b8a4e44a7c82226a5bbd0df459eb98 Mon Sep 17 00:00:00 2001 From: eboado Date: Fri, 30 Oct 2020 11:42:27 +0100 Subject: [PATCH 2/6] - Fixed comment on ILendingPool --- contracts/interfaces/ILendingPool.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index a9a176f7..9dbb7c89 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -99,15 +99,13 @@ interface ILendingPool { /** * @dev emitted when a flashloan is executed * @param target the address of the flashLoanReceiver - * @param asset the address of the assets being flashborrowed + * @param asset the address of the asset being flashborrowed * @param amount the amount requested * @param premium the total fee on the amount * @param referralCode the referral code of the caller **/ event FlashLoan( address indexed target, - // uint256[] modes, - // address indexed onBehalfOf, address asset, uint256 amount, uint256 premium, From 092aacc85a162a45d56fcf69b53529d3fe586970 Mon Sep 17 00:00:00 2001 From: eboado Date: Fri, 30 Oct 2020 11:49:23 +0100 Subject: [PATCH 3/6] - Added initiator to flash loan event. --- contracts/interfaces/ILendingPool.sol | 2 ++ contracts/lendingpool/LendingPool.sol | 1 + 2 files changed, 3 insertions(+) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index 9dbb7c89..55362ec1 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -99,6 +99,7 @@ interface ILendingPool { /** * @dev emitted when a flashloan is executed * @param target the address of the flashLoanReceiver + * @param initiator the address initiating the flash loan * @param asset the address of the asset being flashborrowed * @param amount the amount requested * @param premium the total fee on the amount @@ -106,6 +107,7 @@ interface ILendingPool { **/ event FlashLoan( address indexed target, + address initiator, address asset, uint256 amount, uint256 premium, diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index a90fc385..987d8eb9 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -595,6 +595,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage } emit FlashLoan( receiverAddress, + msg.sender, vars.currentAsset, vars.currentAmount, vars.currentPremium, From 910fa2dce6eba2a60aee033f9a0d5aaff63bd531 Mon Sep 17 00:00:00 2001 From: eboado Date: Fri, 30 Oct 2020 11:52:00 +0100 Subject: [PATCH 4/6] - Added indexed to flash loan events. --- contracts/interfaces/ILendingPool.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index 55362ec1..564392db 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -107,8 +107,8 @@ interface ILendingPool { **/ event FlashLoan( address indexed target, - address initiator, - address asset, + address indexed initiator, + address indexed asset, uint256 amount, uint256 premium, uint16 referralCode From af6b370f0e5da3e6aabb231e918c0bfda9615f40 Mon Sep 17 00:00:00 2001 From: eboado Date: Fri, 30 Oct 2020 11:55:28 +0100 Subject: [PATCH 5/6] - Removed from memory struct debtMode on flashLoan() --- contracts/lendingpool/LendingPool.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 987d8eb9..471d986c 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -486,7 +486,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage struct FlashLoanLocalVars { IFlashLoanReceiver receiver; address oracle; - ReserveLogic.InterestRateMode debtMode; uint256 i; address currentAsset; address currentATokenAddress; @@ -548,10 +547,9 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage vars.currentAmount = amounts[vars.i]; vars.currentPremium = premiums[vars.i]; vars.currentATokenAddress = aTokenAddresses[vars.i]; - vars.debtMode = ReserveLogic.InterestRateMode(modes[vars.i]); vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium); - if (vars.debtMode == ReserveLogic.InterestRateMode.NONE) { + if (ReserveLogic.InterestRateMode(modes[vars.i]) == ReserveLogic.InterestRateMode.NONE) { _reserves[vars.currentAsset].updateState(); _reserves[vars.currentAsset].cumulateToLiquidityIndex( IERC20(vars.currentATokenAddress).totalSupply(), From 7227717a7a292353fd364fcf17123ee7a0f39429 Mon Sep 17 00:00:00 2001 From: eboado Date: Fri, 30 Oct 2020 12:06:02 +0100 Subject: [PATCH 6/6] - Removed modes from validateFlashLoan. Not needed as executeBorrow() will fail. --- contracts/lendingpool/LendingPool.sol | 2 +- contracts/libraries/logic/ValidationLogic.sol | 19 ++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 471d986c..7e29b92d 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -520,7 +520,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage FlashLoanLocalVars memory vars; - ValidationLogic.validateFlashloan(assets, amounts, modes); + ValidationLogic.validateFlashloan(assets, amounts); address[] memory aTokenAddresses = new address[](assets.length); uint256[] memory premiums = new uint256[](assets.length); diff --git a/contracts/libraries/logic/ValidationLogic.sol b/contracts/libraries/logic/ValidationLogic.sol index cc771f8b..b677f34e 100644 --- a/contracts/libraries/logic/ValidationLogic.sol +++ b/contracts/libraries/logic/ValidationLogic.sol @@ -331,26 +331,11 @@ library ValidationLogic { /** * @dev validates a flashloan action - * @param modes the flashloan modes (0 = classic flashloan, 1 = open a stable rate loan, 2 = open a variable rate loan) * @param assets the assets being flashborrowed * @param amounts the amounts for each asset being borrowed **/ - function validateFlashloan( - address[] calldata assets, - uint256[] calldata amounts, - uint256[] calldata modes - ) external pure { - require( - assets.length == amounts.length && assets.length == modes.length, - Errors.INCONSISTENT_FLASHLOAN_PARAMS - ); - - for (uint256 i = 0; i < modes.length; i++) { - require( - modes[i] <= uint256(ReserveLogic.InterestRateMode.VARIABLE), - Errors.INVALID_FLASHLOAN_MODE - ); - } + function validateFlashloan(address[] memory assets, uint256[] memory amounts) internal pure { + require(assets.length == amounts.length, Errors.INCONSISTENT_FLASHLOAN_PARAMS); } /**