diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index 4848df78..5c852180 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -100,20 +100,18 @@ interface ILendingPool { /** * @dev emitted when a flashloan is executed * @param target the address of the flashLoanReceiver - * @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 onBehalfOf the address incurring the debt, if borrow mode is not 0 - * @param assets the address of the assets being flashborrowed - * @param amounts the amount requested - * @param premiums the total fee on the amount + * @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 * @param referralCode the referral code of the caller **/ event FlashLoan( address indexed target, - uint256 mode, - address indexed onBehalfOf, - address[] assets, - uint256[] amounts, - uint256[] premiums, + address indexed initiator, + address indexed asset, + uint256 amount, + uint256 premium, uint16 referralCode ); @@ -295,7 +293,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 borrow modes * @param params a bytes array to be sent to the flashloan executor * @param referralCode the referral code of the caller **/ @@ -303,7 +301,7 @@ interface ILendingPool { address receiver, address[] calldata assets, uint256[] calldata amounts, - uint256 mode, + uint256[] calldata modes, address onBehalfOf, bytes calldata params, uint16 referralCode diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 6afe0219..39afdd29 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -490,13 +490,13 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage struct FlashLoanLocalVars { IFlashLoanReceiver receiver; address oracle; - ReserveLogic.InterestRateMode debtMode; uint256 i; address currentAsset; address currentATokenAddress; uint256 currentAmount; uint256 currentPremium; uint256 currentAmountPlusPremium; + address debtToken; } /** @@ -506,7 +506,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 onBehalfOf If mode is not 0, then the address to take the debt onBehalfOf. The onBehalfOf address must already have approved `msg.sender` to incur the debt on their behalf. * @param params Variadic packed params to pass to the receiver as extra information * @param referralCode Referral code of the flash loan @@ -515,7 +515,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage address receiverAddress, address[] calldata assets, uint256[] calldata amounts, - uint256 mode, + uint256[] calldata modes, address onBehalfOf, bytes calldata params, uint16 referralCode @@ -524,13 +524,12 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage FlashLoanLocalVars memory vars; - ValidationLogic.validateFlashloan(assets, amounts, mode); + ValidationLogic.validateFlashloan(assets, amounts); 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; @@ -552,10 +551,9 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage vars.currentAmount = amounts[vars.i]; vars.currentPremium = premiums[vars.i]; vars.currentATokenAddress = aTokenAddresses[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(), @@ -575,13 +573,11 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage ); } else { if (msg.sender != onBehalfOf) { - address debtToken = _reserves[vars.currentAsset].getDebtTokenAddress(mode); + vars.debtToken = _reserves[vars.currentAsset].getDebtTokenAddress(modes[vars.i]); - _borrowAllowance[debtToken][onBehalfOf][msg - .sender] = _borrowAllowance[debtToken][onBehalfOf][msg.sender].sub( - vars.currentAmount, - Errors.BORROW_ALLOWANCE_ARE_NOT_ENOUGH - ); + _borrowAllowance[vars.debtToken][onBehalfOf][msg.sender] = _borrowAllowance[vars + .debtToken][onBehalfOf][msg.sender] + .sub(vars.currentAmount, Errors.BORROW_ALLOWANCE_ARE_NOT_ENOUGH); } //if the user didn't choose to return the funds, the system checks if there @@ -592,14 +588,21 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage msg.sender, onBehalfOf, vars.currentAmount, - mode, + modes[vars.i], vars.currentATokenAddress, referralCode, false ) ); } - emit FlashLoan(receiverAddress, mode, onBehalfOf, assets, amounts, premiums, referralCode); + emit FlashLoan( + receiverAddress, + msg.sender, + vars.currentAsset, + vars.currentAmount, + vars.currentPremium, + referralCode + ); } } diff --git a/contracts/lendingpool/LendingPoolConfigurator.sol b/contracts/lendingpool/LendingPoolConfigurator.sol index 1428805e..3fc908a4 100644 --- a/contracts/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/lendingpool/LendingPoolConfigurator.sol @@ -159,7 +159,11 @@ contract LendingPoolConfigurator is VersionedInitializable { * @param proxy the aToken proxy address * @param implementation the new aToken implementation **/ - event ATokenUpgraded(address indexed asset, address indexed proxy, address indexed implementation); + event ATokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); /** * @dev emitted when the implementation of a stable debt token is upgraded @@ -167,7 +171,11 @@ contract LendingPoolConfigurator is VersionedInitializable { * @param proxy the stable debt token proxy address * @param implementation the new aToken implementation **/ - event StableDebtTokenUpgraded(address indexed asset, address indexed proxy, address indexed implementation); + event StableDebtTokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); /** * @dev emitted when the implementation of a variable debt token is upgraded @@ -175,7 +183,11 @@ contract LendingPoolConfigurator is VersionedInitializable { * @param proxy the variable debt token proxy address * @param implementation the new aToken implementation **/ - event VariableDebtTokenUpgraded(address indexed asset, address indexed proxy, address indexed implementation); + event VariableDebtTokenUpgraded( + address indexed asset, + address indexed proxy, + address indexed implementation + ); ILendingPoolAddressesProvider internal addressesProvider; ILendingPool internal pool; diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index b515603f..2c5a36db 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -98,7 +98,6 @@ library Errors { string public constant INVALID_DECIMALS = '73'; string public constant INVALID_RESERVE_FACTOR = '74'; - enum CollateralManagerErrors { NO_ERROR, NO_COLLATERAL_AVAILABLE, diff --git a/contracts/libraries/logic/ValidationLogic.sol b/contracts/libraries/logic/ValidationLogic.sol index adbfdfc7..9b67f297 100644 --- a/contracts/libraries/logic/ValidationLogic.sol +++ b/contracts/libraries/logic/ValidationLogic.sol @@ -283,8 +283,7 @@ library ValidationLogic { require( !userConfig.isUsingAsCollateral(reserve.id) || reserve.configuration.getLtv() == 0 || - stableDebt.add(variableDebt) > - IERC20(reserve.aTokenAddress).balanceOf(msg.sender), + stableDebt.add(variableDebt) > IERC20(reserve.aTokenAddress).balanceOf(msg.sender), Errors.CALLATERAL_SAME_AS_BORROWING_CURRENCY ); } else { @@ -331,16 +330,10 @@ 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 assets the assets being flashborrowed * @param amounts the amounts for each asset being borrowed **/ - function validateFlashloan( - address[] memory assets, - uint256[] memory amounts, - uint256 mode - ) internal pure { - require(mode <= 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); } diff --git a/contracts/tokenization/StableDebtToken.sol b/contracts/tokenization/StableDebtToken.sol index c339317f..d7c76857 100644 --- a/contracts/tokenization/StableDebtToken.sol +++ b/contracts/tokenization/StableDebtToken.sol @@ -97,7 +97,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase { address user, uint256 amount, uint256 rate - ) external override onlyLendingPool returns(bool) { + ) external override onlyLendingPool returns (bool) { MintLocalVars memory vars; //cumulates the user debt diff --git a/contracts/tokenization/interfaces/IStableDebtToken.sol b/contracts/tokenization/interfaces/IStableDebtToken.sol index 4e04f704..7a6e5f5b 100644 --- a/contracts/tokenization/interfaces/IStableDebtToken.sol +++ b/contracts/tokenization/interfaces/IStableDebtToken.sol @@ -62,7 +62,7 @@ interface IStableDebtToken { address user, uint256 amount, uint256 rate - ) external returns(bool); + ) external returns (bool); /** * @dev burns debt of the target user. diff --git a/deployed-contracts.json b/deployed-contracts.json index 401a2694..848902f0 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -266,4 +266,4 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } } -} \ No newline at end of file +} diff --git a/test/atoken-transfer.spec.ts b/test/atoken-transfer.spec.ts index ca92e086..eb3cef4b 100644 --- a/test/atoken-transfer.spec.ts +++ b/test/atoken-transfer.spec.ts @@ -71,8 +71,11 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { users[1].address ); - const userReserveData = await helpersContract.getUserReserveData(weth.address, users[1].address); - + const userReserveData = await helpersContract.getUserReserveData( + weth.address, + users[1].address + ); + expect(userReserveData.currentStableDebt.toString()).to.be.eq(ethers.utils.parseEther('0.1')); }); @@ -80,7 +83,7 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { const {users, pool, aDai, dai, weth} = testEnv; const aDAItoTransfer = await convertToCurrencyDecimals(dai.address, '1000'); - + await expect( aDai.connect(users[1].signer).transfer(users[0].address, aDAItoTransfer), TRANSFER_NOT_ALLOWED @@ -88,15 +91,14 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { }); it('User 1 tries to transfer a small amount of DAI used as collateral back to user 0', async () => { - const {users, pool, aDai, dai, weth} = testEnv; const aDAItoTransfer = await convertToCurrencyDecimals(dai.address, '100'); - + await aDai.connect(users[1].signer).transfer(users[0].address, aDAItoTransfer); const user0Balance = await aDai.balanceOf(users[0].address); expect(user0Balance.toString()).to.be.eq(aDAItoTransfer.toString()); - }); + }); }); diff --git a/test/flashloan.spec.ts b/test/flashloan.spec.ts index fc977fcf..e55634de 100644 --- a/test/flashloan.spec.ts +++ b/test/flashloan.spec.ts @@ -48,7 +48,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 0, + [0], _mockFlashLoanReceiver.address, '0x10', '0' @@ -78,7 +78,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], ['1000720000000000000'], - 0, + [0], _mockFlashLoanReceiver.address, '0x10', '0' @@ -110,7 +110,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 0, + [0], caller.address, '0x10', '0' @@ -131,7 +131,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 0, + [0], caller.address, '0x10', '0' @@ -152,12 +152,12 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 4, + [4], caller.address, '0x10', '0' ) - ).to.be.revertedWith(INVALID_FLASHLOAN_MODE); + ).to.be.reverted; }); it('Caller deposits 1000 DAI as collateral, Takes WETH flashloan with mode = 2, does not return the funds. A variable loan for caller is created', async () => { @@ -181,7 +181,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [ethers.utils.parseEther('0.8')], - 2, + [2], caller.address, '0x10', '0' @@ -209,7 +209,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], ['1004415000000000000'], //slightly higher than the available liquidity - 2, + [2], caller.address, '0x10', '0' @@ -223,7 +223,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { const caller = users[1]; await expect( - pool.flashLoan(deployer.address, [weth.address], ['1000000000000000000'], 2, caller.address, '0x10', '0') + pool.flashLoan( + deployer.address, + [weth.address], + ['1000000000000000000'], + [2], + caller.address, + '0x10', + '0' + ) ).to.be.reverted; }); @@ -251,7 +259,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], - 0, + [0], _mockFlashLoanReceiver.address, '0x10', '0' @@ -294,7 +302,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], - 2, + [2], caller.address, '0x10', '0' @@ -321,7 +329,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], 2, caller.address, '0x10', '0'); + .flashLoan( + _mockFlashLoanReceiver.address, + [usdc.address], + [flashloanAmount], + [2], + caller.address, + '0x10', + '0' + ); const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( usdc.address ); @@ -360,7 +376,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [flashAmount], - 0, + [0], caller.address, '0x10', '0' @@ -383,7 +399,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [flashAmount], - 1, + [1], caller.address, '0x10', '0' @@ -429,7 +445,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [flashAmount], - 1, + [1], onBehalfOf.address, '0x10', '0' @@ -458,7 +474,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [flashAmount], - 1, + [1], onBehalfOf.address, '0x10', '0' diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index 72be7ada..b4aa24c3 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -191,7 +191,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { _mockFlashLoanReceiver.address, [weth.address], [flashAmount], - 1, + [1], caller.address, '0x10', '0'