Merge branch 'master' into 100/flash-loan-bath-modes

This commit is contained in:
eboado 2020-10-30 14:55:03 +01:00
commit 5a9a46a31f
15 changed files with 74 additions and 71 deletions

View File

@ -19,16 +19,11 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
mapping(bytes32 => address) private _addresses; mapping(bytes32 => address) private _addresses;
bytes32 private constant LENDING_POOL = 'LENDING_POOL'; bytes32 private constant LENDING_POOL = 'LENDING_POOL';
bytes32 private constant LENDING_POOL_CORE = 'LENDING_POOL_CORE';
bytes32 private constant LENDING_POOL_CONFIGURATOR = 'LENDING_POOL_CONFIGURATOR'; bytes32 private constant LENDING_POOL_CONFIGURATOR = 'LENDING_POOL_CONFIGURATOR';
bytes32 private constant AAVE_ADMIN = 'AAVE_ADMIN'; bytes32 private constant AAVE_ADMIN = 'AAVE_ADMIN';
bytes32 private constant LENDING_POOL_COLLATERAL_MANAGER = 'COLLATERAL_MANAGER'; bytes32 private constant LENDING_POOL_COLLATERAL_MANAGER = 'COLLATERAL_MANAGER';
bytes32 private constant LENDING_POOL_FLASHLOAN_PROVIDER = 'FLASHLOAN_PROVIDER';
bytes32 private constant DATA_PROVIDER = 'DATA_PROVIDER';
bytes32 private constant ETHEREUM_ADDRESS = 'ETHEREUM_ADDRESS';
bytes32 private constant PRICE_ORACLE = 'PRICE_ORACLE'; bytes32 private constant PRICE_ORACLE = 'PRICE_ORACLE';
bytes32 private constant LENDING_RATE_ORACLE = 'LENDING_RATE_ORACLE'; bytes32 private constant LENDING_RATE_ORACLE = 'LENDING_RATE_ORACLE';
bytes32 private constant WALLET_BALANCE_PROVIDER = 'WALLET_BALANCE_PROVIDER';
/** /**
* @dev Sets an address for an id, allowing to cover it or not with a proxy * @dev Sets an address for an id, allowing to cover it or not with a proxy

View File

@ -12,6 +12,7 @@ interface IFlashLoanReceiver {
address[] calldata assets, address[] calldata assets,
uint256[] calldata amounts, uint256[] calldata amounts,
uint256[] calldata premiums, uint256[] calldata premiums,
address initiator,
bytes calldata params bytes calldata params
) external returns (bool); ) external returns (bool);
} }

View File

@ -27,9 +27,10 @@ interface ILendingPool {
* @dev emitted during a withdraw action. * @dev emitted during a withdraw action.
* @param reserve the address of the reserve * @param reserve the address of the reserve
* @param user the address of the user * @param user the address of the user
* @param to address that will receive the underlying
* @param amount the amount to be withdrawn * @param amount the amount to be withdrawn
**/ **/
event Withdraw(address indexed reserve, address indexed user, uint256 amount); event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
event BorrowAllowanceDelegated( event BorrowAllowanceDelegated(
address indexed asset, address indexed asset,
@ -74,7 +75,7 @@ interface ILendingPool {
* @param reserve the address of the reserve * @param reserve the address of the reserve
* @param user the address of the user executing the swap * @param user the address of the user executing the swap
**/ **/
event Swap(address indexed reserve, address indexed user); event Swap(address indexed reserve, address indexed user, uint256 rateMode);
/** /**
* @dev emitted when a user enables a reserve as collateral * @dev emitted when a user enables a reserve as collateral
@ -186,8 +187,13 @@ interface ILendingPool {
* @dev withdraws the assets of user. * @dev withdraws the assets of user.
* @param reserve the address of the reserve * @param reserve the address of the reserve
* @param amount the underlying amount to be redeemed * @param amount the underlying amount to be redeemed
* @param to address that will receive the underlying
**/ **/
function withdraw(address reserve, uint256 amount) external; function withdraw(
address reserve,
uint256 amount,
address to
) external;
/** /**
* @dev Sets allowance to borrow on a certain type of debt asset for a certain user address * @dev Sets allowance to borrow on a certain type of debt asset for a certain user address

View File

@ -1,20 +0,0 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
interface ISwapAdapter {
/**
* @dev Swaps an `amountToSwap` of an asset to another, approving a `fundsDestination` to pull the funds
* @param assetToSwapFrom Origin asset
* @param assetToSwapTo Destination asset
* @param amountToSwap How much `assetToSwapFrom` needs to be swapped
* @param fundsDestination Address that will be pulling the swapped funds
* @param params Additional variadic field to include extra params
*/
function executeOperation(
address assetToSwapFrom,
address assetToSwapTo,
uint256 amountToSwap,
address fundsDestination,
bytes calldata params
) external;
}

View File

@ -20,7 +20,6 @@ import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol'
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol'; import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
import {DebtTokenBase} from '../tokenization/base/DebtTokenBase.sol'; import {DebtTokenBase} from '../tokenization/base/DebtTokenBase.sol';
import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol'; import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol';
import {ISwapAdapter} from '../interfaces/ISwapAdapter.sol';
import {LendingPoolCollateralManager} from './LendingPoolCollateralManager.sol'; import {LendingPoolCollateralManager} from './LendingPoolCollateralManager.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol'; import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
@ -120,8 +119,13 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
* @dev withdraws the _reserves of user. * @dev withdraws the _reserves of user.
* @param asset the address of the reserve * @param asset the address of the reserve
* @param amount the underlying amount to be redeemed * @param amount the underlying amount to be redeemed
* @param to address that will receive the underlying
**/ **/
function withdraw(address asset, uint256 amount) external override { function withdraw(
address asset,
uint256 amount,
address to
) external override {
_whenNotPaused(); _whenNotPaused();
ReserveLogic.ReserveData storage reserve = _reserves[asset]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
@ -155,9 +159,9 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
_usersConfig[msg.sender].setUsingAsCollateral(reserve.id, false); _usersConfig[msg.sender].setUsingAsCollateral(reserve.id, false);
} }
IAToken(aToken).burn(msg.sender, msg.sender, amountToWithdraw, reserve.liquidityIndex); IAToken(aToken).burn(msg.sender, to, amountToWithdraw, reserve.liquidityIndex);
emit Withdraw(asset, msg.sender, amountToWithdraw); emit Withdraw(asset, msg.sender, to, amountToWithdraw);
} }
/** /**
@ -352,7 +356,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0); reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0);
emit Swap(asset, msg.sender); emit Swap(asset, msg.sender, rateMode);
} }
/** /**
@ -538,7 +542,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
//execute action of the receiver //execute action of the receiver
require( require(
vars.receiver.executeOperation(assets, amounts, premiums, params), vars.receiver.executeOperation(assets, amounts, premiums, msg.sender, params),
Errors.INVALID_FLASH_LOAN_EXECUTOR_RETURN Errors.INVALID_FLASH_LOAN_EXECUTOR_RETURN
); );
@ -891,34 +895,34 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
oracle oracle
); );
uint256 reserveId = reserve.id;
if (!userConfig.isBorrowing(reserveId)) {
userConfig.setBorrowing(reserveId, true);
}
reserve.updateState(); reserve.updateState();
//caching the current stable borrow rate //caching the current stable borrow rate
uint256 currentStableRate = 0; uint256 currentStableRate = 0;
bool isFirstBorrowing = false;
if ( if (
ReserveLogic.InterestRateMode(vars.interestRateMode) == ReserveLogic.InterestRateMode.STABLE ReserveLogic.InterestRateMode(vars.interestRateMode) == ReserveLogic.InterestRateMode.STABLE
) { ) {
currentStableRate = reserve.currentStableBorrowRate; currentStableRate = reserve.currentStableBorrowRate;
IStableDebtToken(reserve.stableDebtTokenAddress).mint( isFirstBorrowing = IStableDebtToken(reserve.stableDebtTokenAddress).mint(
vars.onBehalfOf, vars.onBehalfOf,
vars.amount, vars.amount,
currentStableRate currentStableRate
); );
} else { } else {
IVariableDebtToken(reserve.variableDebtTokenAddress).mint( isFirstBorrowing = IVariableDebtToken(reserve.variableDebtTokenAddress).mint(
vars.onBehalfOf, vars.onBehalfOf,
vars.amount, vars.amount,
reserve.variableBorrowIndex reserve.variableBorrowIndex
); );
} }
if (isFirstBorrowing) {
userConfig.setBorrowing(reserve.id, true);
}
reserve.updateInterestRates( reserve.updateInterestRates(
vars.asset, vars.asset,
vars.aTokenAddress, vars.aTokenAddress,

View File

@ -15,7 +15,6 @@ import {Helpers} from '../libraries/helpers/Helpers.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol'; import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {ISwapAdapter} from '../interfaces/ISwapAdapter.sol';
import {Errors} from '../libraries/helpers/Errors.sol'; import {Errors} from '../libraries/helpers/Errors.sol';
import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol'; import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
import {LendingPoolStorage} from './LendingPoolStorage.sol'; import {LendingPoolStorage} from './LendingPoolStorage.sol';

View File

@ -47,7 +47,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve * @param asset the address of the reserve
* @param stableRateEnabled true if stable rate borrowing is enabled, false otherwise * @param stableRateEnabled true if stable rate borrowing is enabled, false otherwise
**/ **/
event BorrowingEnabledOnReserve(address asset, bool stableRateEnabled); event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled);
/** /**
* @dev emitted when borrowing is disabled on a reserve * @dev emitted when borrowing is disabled on a reserve
@ -116,42 +116,42 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve * @param asset the address of the reserve
* @param ltv the new value for the loan to value * @param ltv the new value for the loan to value
**/ **/
event ReserveBaseLtvChanged(address asset, uint256 ltv); event ReserveBaseLtvChanged(address indexed asset, uint256 ltv);
/** /**
* @dev emitted when a reserve factor is updated * @dev emitted when a reserve factor is updated
* @param asset the address of the reserve * @param asset the address of the reserve
* @param factor the new reserve factor * @param factor the new reserve factor
**/ **/
event ReserveFactorChanged(address asset, uint256 factor); event ReserveFactorChanged(address indexed asset, uint256 factor);
/** /**
* @dev emitted when a reserve liquidation threshold is updated * @dev emitted when a reserve liquidation threshold is updated
* @param asset the address of the reserve * @param asset the address of the reserve
* @param threshold the new value for the liquidation threshold * @param threshold the new value for the liquidation threshold
**/ **/
event ReserveLiquidationThresholdChanged(address asset, uint256 threshold); event ReserveLiquidationThresholdChanged(address indexed asset, uint256 threshold);
/** /**
* @dev emitted when a reserve liquidation bonus is updated * @dev emitted when a reserve liquidation bonus is updated
* @param asset the address of the reserve * @param asset the address of the reserve
* @param bonus the new value for the liquidation bonus * @param bonus the new value for the liquidation bonus
**/ **/
event ReserveLiquidationBonusChanged(address asset, uint256 bonus); event ReserveLiquidationBonusChanged(address indexed asset, uint256 bonus);
/** /**
* @dev emitted when the reserve decimals are updated * @dev emitted when the reserve decimals are updated
* @param asset the address of the reserve * @param asset the address of the reserve
* @param decimals the new decimals * @param decimals the new decimals
**/ **/
event ReserveDecimalsChanged(address asset, uint256 decimals); event ReserveDecimalsChanged(address indexed asset, uint256 decimals);
/** /**
* @dev emitted when a reserve interest strategy contract is updated * @dev emitted when a reserve interest strategy contract is updated
* @param asset the address of the reserve * @param asset the address of the reserve
* @param strategy the new address of the interest strategy contract * @param strategy the new address of the interest strategy contract
**/ **/
event ReserveInterestRateStrategyChanged(address asset, address strategy); event ReserveInterestRateStrategyChanged(address indexed asset, address strategy);
/** /**
* @dev emitted when an aToken implementation is upgraded * @dev emitted when an aToken implementation is upgraded
@ -159,7 +159,11 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param proxy the aToken proxy address * @param proxy the aToken proxy address
* @param implementation the new aToken implementation * @param implementation the new aToken implementation
**/ **/
event ATokenUpgraded(address asset, address proxy, address implementation); event ATokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/** /**
* @dev emitted when the implementation of a stable debt token is upgraded * @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 proxy the stable debt token proxy address
* @param implementation the new aToken implementation * @param implementation the new aToken implementation
**/ **/
event StableDebtTokenUpgraded(address asset, address proxy, address implementation); event StableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/** /**
* @dev emitted when the implementation of a variable debt token is upgraded * @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 proxy the variable debt token proxy address
* @param implementation the new aToken implementation * @param implementation the new aToken implementation
**/ **/
event VariableDebtTokenUpgraded(address asset, address proxy, address implementation); event VariableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
ILendingPoolAddressesProvider internal addressesProvider; ILendingPoolAddressesProvider internal addressesProvider;
ILendingPool internal pool; ILendingPool internal pool;

View File

@ -251,15 +251,15 @@ library ValidationLogic {
* @dev validates a swap of borrow rate mode. * @dev validates a swap of borrow rate mode.
* @param reserve the reserve state on which the user is swapping the rate * @param reserve the reserve state on which the user is swapping the rate
* @param userConfig the user reserves configuration * @param userConfig the user reserves configuration
* @param stableBorrowBalance the stable borrow balance of the user * @param stableDebt the stable debt of the user
* @param variableBorrowBalance the stable borrow balance of the user * @param variableDebt the variable debt of the user
* @param currentRateMode the rate mode of the borrow * @param currentRateMode the rate mode of the borrow
*/ */
function validateSwapRateMode( function validateSwapRateMode(
ReserveLogic.ReserveData storage reserve, ReserveLogic.ReserveData storage reserve,
UserConfiguration.Map storage userConfig, UserConfiguration.Map storage userConfig,
uint256 stableBorrowBalance, uint256 stableDebt,
uint256 variableBorrowBalance, uint256 variableDebt,
ReserveLogic.InterestRateMode currentRateMode ReserveLogic.InterestRateMode currentRateMode
) external view { ) external view {
(bool isActive, bool isFreezed, , bool stableRateEnabled) = reserve.configuration.getFlags(); (bool isActive, bool isFreezed, , bool stableRateEnabled) = reserve.configuration.getFlags();
@ -268,9 +268,9 @@ library ValidationLogic {
require(!isFreezed, Errors.NO_UNFREEZED_RESERVE); require(!isFreezed, Errors.NO_UNFREEZED_RESERVE);
if (currentRateMode == ReserveLogic.InterestRateMode.STABLE) { if (currentRateMode == ReserveLogic.InterestRateMode.STABLE) {
require(stableBorrowBalance > 0, Errors.NO_STABLE_RATE_LOAN_IN_RESERVE); require(stableDebt > 0, Errors.NO_STABLE_RATE_LOAN_IN_RESERVE);
} else if (currentRateMode == ReserveLogic.InterestRateMode.VARIABLE) { } else if (currentRateMode == ReserveLogic.InterestRateMode.VARIABLE) {
require(variableBorrowBalance > 0, Errors.NO_VARIABLE_RATE_LOAN_IN_RESERVE); require(variableDebt > 0, Errors.NO_VARIABLE_RATE_LOAN_IN_RESERVE);
/** /**
* user wants to swap to stable, before swapping we need to ensure that * user wants to swap to stable, before swapping we need to ensure that
* 1. stable borrow rate is enabled on the reserve * 1. stable borrow rate is enabled on the reserve
@ -283,8 +283,7 @@ library ValidationLogic {
require( require(
!userConfig.isUsingAsCollateral(reserve.id) || !userConfig.isUsingAsCollateral(reserve.id) ||
reserve.configuration.getLtv() == 0 || reserve.configuration.getLtv() == 0 ||
stableBorrowBalance.add(variableBorrowBalance) > stableDebt.add(variableDebt) > IERC20(reserve.aTokenAddress).balanceOf(msg.sender),
IERC20(reserve.aTokenAddress).balanceOf(msg.sender),
Errors.CALLATERAL_SAME_AS_BORROWING_CURRENCY Errors.CALLATERAL_SAME_AS_BORROWING_CURRENCY
); );
} else { } else {

View File

@ -47,9 +47,11 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
address[] memory assets, address[] memory assets,
uint256[] memory amounts, uint256[] memory amounts,
uint256[] memory premiums, uint256[] memory premiums,
address initiator,
bytes memory params bytes memory params
) public override returns (bool) { ) public override returns (bool) {
params; params;
initiator;
if (_failExecution) { if (_failExecution) {
emit ExecutedWithFail(assets, amounts, premiums); emit ExecutedWithFail(assets, amounts, premiums);

View File

@ -97,7 +97,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
address user, address user,
uint256 amount, uint256 amount,
uint256 rate uint256 rate
) external override onlyLendingPool { ) external override onlyLendingPool returns (bool) {
MintLocalVars memory vars; MintLocalVars memory vars;
//cumulates the user debt //cumulates the user debt
@ -148,6 +148,8 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
vars.newStableRate, vars.newStableRate,
vars.currentAvgStableRate vars.currentAvgStableRate
); );
return currentBalance == 0;
} }
/** /**

View File

@ -62,7 +62,7 @@ interface IStableDebtToken {
address user, address user,
uint256 amount, uint256 amount,
uint256 rate uint256 rate
) external; ) external returns (bool);
/** /**
* @dev burns debt of the target user. * @dev burns debt of the target user.

View File

@ -163,25 +163,26 @@
}, },
"ReserveLogic": { "ReserveLogic": {
"buidlerevm": { "buidlerevm": {
"address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95", "address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
} }
}, },
"GenericLogic": { "GenericLogic": {
"buidlerevm": { "buidlerevm": {
"address": "0x6082731fdAba4761277Fb31299ebC782AD3bCf24", "address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
} }
}, },
"ValidationLogic": { "ValidationLogic": {
"buidlerevm": { "buidlerevm": {
"address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e", "address": "0xA4765Ff72A9F3CfE73089bb2c3a41B838DF71574",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
} }
}, },
"LendingPool": { "LendingPool": {
"buidlerevm": { "buidlerevm": {
"address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e" "address": "0x35c1419Da7cf0Ff885B8Ef8EA9242FEF6800c99b",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
} }
}, },
"LendingPoolConfigurator": { "LendingPoolConfigurator": {

View File

@ -157,7 +157,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
'0x10', '0x10',
'0' '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 () => { 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 () => {

View File

@ -231,7 +231,7 @@ export const withdraw = async (
if (expectedResult === 'success') { if (expectedResult === 'success') {
const txResult = await waitForTx( const txResult = await waitForTx(
await pool.connect(user.signer).withdraw(reserve, amountToWithdraw) await pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address)
); );
const { const {
@ -269,8 +269,10 @@ export const withdraw = async (
// ); // );
// }); // });
} else if (expectedResult === 'revert') { } else if (expectedResult === 'revert') {
await expect(pool.connect(user.signer).withdraw(reserve, amountToWithdraw), revertMessage).to.be await expect(
.reverted; pool.connect(user.signer).withdraw(reserve, amountToWithdraw, user.address),
revertMessage
).to.be.reverted;
} }
}; };

View File

@ -116,7 +116,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
// user tries to burn // user tries to burn
await expect( await expect(
pool.connect(users[0].signer).withdraw(dai.address, amountDAItoDeposit) pool.connect(users[0].signer).withdraw(dai.address, amountDAItoDeposit, users[0].address)
).to.revertedWith(IS_PAUSED); ).to.revertedWith(IS_PAUSED);
// Configurator unpauses the pool // Configurator unpauses the pool