Merge branch 'master' into feat/uniswap-adapter-flashloan

# Conflicts:
#	test/__setup.spec.ts
This commit is contained in:
Gerardo Nardelli 2020-11-25 10:46:01 -03:00
commit 71ea58f758
115 changed files with 4925 additions and 3075 deletions
.gitignore.gitlab-ci.ymlDockerfilebuidler.config.ts
contracts
dependencies/openzeppelin
deployments
flashloan
interfaces
lendingpool
libraries/helpers
misc
mocks
protocol
docker-compose.test.ymlhardhat.config.ts
helpers
markets/aave

2
.gitignore vendored
View File

@ -7,7 +7,7 @@ dist/
build/
.vscode
.idea
types
/types
deployed-contracts.json

View File

@ -1,14 +1,26 @@
stages:
- test
- checks
test:
stage: test
stage: checks
tags:
- aave-build-runner
before_script:
- docker-compose -f docker-compose.test.yml build
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml build
script:
- docker-compose -f docker-compose.test.yml run contracts-env npm run ci:test
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:test
after_script:
- docker-compose -f docker-compose.test.yml run contracts-env npm run ci:clean
- docker-compose -f docker-compose.test.yml down
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down
deploy-mainnet-fork:
tags:
- aave-build-runner
stage: checks
before_script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml build
script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run aave:fork:main
after_script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down

View File

@ -1,4 +1,4 @@
FROM ethereum/solc:0.6.8 as build-deps
FROM ethereum/solc:0.6.12 as build-deps
FROM node:14
COPY --from=build-deps /usr/bin/solc /usr/bin/solc

View File

@ -49,7 +49,7 @@ const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number
const buidlerConfig: any = {
solc: {
version: '0.6.8',
version: '0.6.12',
optimizer: {enabled: true, runs: 200},
evmVersion: 'istanbul',
},

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.8;
pragma solidity 0.6.12;
/**
* @dev Collection of functions related to the address type

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.8;
pragma solidity 0.6.12;
/*
* @dev Provides information about the current execution context, including the

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.8;
pragma solidity 0.6.12;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {IERC20} from './IERC20.sol';

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.8;
pragma solidity 0.6.12;
import {IERC20} from './IERC20.sol';
import {SafeMath} from './SafeMath.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.8;
pragma solidity 0.6.12;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import './BaseAdminUpgradeabilityProxy.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import './UpgradeabilityProxy.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import './Proxy.sol';
import '../contracts/Address.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import './BaseAdminUpgradeabilityProxy.sol';
import './InitializableUpgradeabilityProxy.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import './BaseUpgradeabilityProxy.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import './BaseUpgradeabilityProxy.sol';

View File

@ -1,16 +1,18 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {LendingPool} from '../lendingpool/LendingPool.sol';
import {LendingPoolAddressesProvider} from '../configuration/LendingPoolAddressesProvider.sol';
import {LendingPoolConfigurator} from '../lendingpool/LendingPoolConfigurator.sol';
import {AToken} from '../tokenization/AToken.sol';
import {LendingPool} from '../protocol/lendingpool/LendingPool.sol';
import {
LendingPoolAddressesProvider
} from '../protocol/configuration/LendingPoolAddressesProvider.sol';
import {LendingPoolConfigurator} from '../protocol/lendingpool/LendingPoolConfigurator.sol';
import {AToken} from '../protocol/tokenization/AToken.sol';
import {
DefaultReserveInterestRateStrategy
} from '../lendingpool/DefaultReserveInterestRateStrategy.sol';
} from '../protocol/lendingpool/DefaultReserveInterestRateStrategy.sol';
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {StringLib} from '../libraries/helpers/StringLib.sol';
import {StringLib} from './StringLib.sol';
contract ATokensAndRatesHelper is Ownable {
address payable private pool;
@ -31,7 +33,7 @@ contract ATokensAndRatesHelper is Ownable {
function initDeployment(
address[] calldata tokens,
string[] calldata symbols,
uint256[5][] calldata rates,
uint256[6][] calldata rates,
address incentivesController
) external onlyOwner {
require(tokens.length == symbols.length, 't Arrays not same length');
@ -55,7 +57,8 @@ contract ATokensAndRatesHelper is Ownable {
rates[i][1],
rates[i][2],
rates[i][3],
rates[i][4]
rates[i][4],
rates[i][5]
)
)
);
@ -105,16 +108,16 @@ contract ATokensAndRatesHelper is Ownable {
}
}
function enableBorrowingOnReserves(address[] calldata tokens, bool[] calldata stableBorrows)
function enableBorrowingOnReserves(address[] calldata tokens, bool[] calldata stableBorrowingEnabled)
external
onlyOwner
{
require(stableBorrows.length == tokens.length);
require(stableBorrowingEnabled.length == tokens.length);
for (uint256 i = 0; i < tokens.length; i++) {
LendingPoolConfigurator(poolConfigurator).enableBorrowingOnReserve(
tokens[i],
stableBorrows[i]
stableBorrowingEnabled[i]
);
}
}

View File

@ -1,12 +1,12 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {StableDebtToken} from '../tokenization/StableDebtToken.sol';
import {VariableDebtToken} from '../tokenization/VariableDebtToken.sol';
import {StableDebtToken} from '../protocol/tokenization/StableDebtToken.sol';
import {VariableDebtToken} from '../protocol/tokenization/VariableDebtToken.sol';
import {LendingRateOracle} from '../mocks/oracle/LendingRateOracle.sol';
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {StringLib} from '../libraries/helpers/StringLib.sol';
import {StringLib} from './StringLib.sol';
contract StableAndVariableTokensHelper is Ownable {
address payable private pool;

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
library StringLib {
function concat(string memory a, string memory b) internal pure returns (string memory) {

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
* @title IFlashLoanReceiver interface

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
interface IAaveIncentivesController {

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface IChainlinkAggregator {
function latestAnswer() external view returns (int256);

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';

View File

@ -1,20 +1,19 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol';
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
interface ILendingPool {
/**
* @dev emitted on deposit
* @param reserve the address of the reserve
* @param user the address of the user
* @param amount the amount to be deposited
* @param referral the referral number of the action
* @dev Emitted on deposit()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the deposit
* @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
* @param amount The amount deposited
* @param referral The referral code used
**/
event Deposit(
address indexed reserve,
@ -25,22 +24,24 @@ interface ILendingPool {
);
/**
* @dev emitted during a withdraw action.
* @param reserve the address of the reserve
* @param user the address of the user
* @param to address that will receive the underlying
* @param amount the amount to be withdrawn
* @dev Emitted on withdraw()
* @param reserve The address of the underlyng asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to Address that will receive the underlying
* @param amount The amount to be withdrawn
**/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev emitted on borrow
* @param reserve the address of the reserve
* @param user the address of the user
* @param amount the amount to be deposited
* @param borrowRateMode the rate mode, can be either 1-stable or 2-variable
* @param borrowRate the rate at which the user has borrowed
* @param referral the referral number of the action
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed
* @param referral The referral code used
**/
event Borrow(
address indexed reserve,
@ -51,12 +52,13 @@ interface ILendingPool {
uint256 borrowRate,
uint16 indexed referral
);
/**
* @dev emitted on repay
* @param reserve the address of the reserve
* @param user the address of the user for which the repay has been executed
* @param repayer the address of the user that has performed the repay action
* @param amount the amount repaid
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
**/
event Repay(
address indexed reserve,
@ -64,41 +66,44 @@ interface ILendingPool {
address indexed repayer,
uint256 amount
);
/**
* @dev emitted when a user performs a rate swap
* @param reserve the address of the reserve
* @param user the address of the user executing the swap
* @dev Emitted on swapBorrowRateMode()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user swapping his rate mode
* @param rateMode The rate mode that the user wants to swap to
**/
event Swap(address indexed reserve, address indexed user, uint256 rateMode);
/**
* @dev emitted when a user enables a reserve as collateral
* @param reserve the address of the reserve
* @param user the address of the user
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev emitted when a user disables a reserve as collateral
* @param reserve the address of the reserve
* @param user the address of the user
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev emitted when the stable rate of a user gets rebalanced
* @param reserve the address of the reserve
* @param user the address of the user for which the rebalance has been executed
* @dev Emitted on rebalanceStableBorrowRate()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user for which the rebalance has been executed
**/
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
/**
* @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
* @param referralCode the referral code of the caller
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param premium The fee flash borrowed
* @param referralCode The referral code used
**/
event FlashLoan(
address indexed target,
@ -120,23 +125,23 @@ interface ILendingPool {
event Unpaused();
/**
* @dev emitted when a borrower is liquidated. Thos evemt is emitted directly by the LendingPool
* but it's declared here as the LendingPoolCollateralManager
* is executed using a delegateCall().
* @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
* LendingPoolCollateral manager using a DELEGATECALL
* This allows to have the events in the generated ABI for LendingPool.
* @param collateral the address of the collateral being liquidated
* @param principal the address of the reserve
* @param user the address of the user being liquidated
* @param purchaseAmount the total amount liquidated
* @param liquidatedCollateralAmount the amount of collateral being liquidated
* @param liquidator the address of the liquidator
* @param receiveAToken true if the liquidator wants to receive aTokens, false otherwise
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liiquidator
* @param liquidator The address of the liquidator
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
event LiquidationCall(
address indexed collateral,
address indexed principal,
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 purchaseAmount,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
@ -147,12 +152,12 @@ interface ILendingPool {
* in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
* the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
* gets added to the LendingPool ABI
* @param reserve the address of the reserve
* @param liquidityRate the new liquidity rate
* @param stableBorrowRate the new stable borrow rate
* @param variableBorrowRate the new variable borrow rate
* @param liquidityIndex the new liquidity index
* @param variableBorrowIndex the new variable borrow index
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The new liquidity rate
* @param stableBorrowRate The new stable borrow rate
* @param variableBorrowRate The new variable borrow rate
* @param liquidityIndex The new liquidity index
* @param variableBorrowIndex The new variable borrow index
**/
event ReserveDataUpdated(
address indexed reserve,
@ -164,40 +169,56 @@ interface ILendingPool {
);
/**
* @dev deposits The underlying asset into the reserve. A corresponding amount of the overlying asset (aTokens)
* is minted.
* @param reserve the address of the reserve
* @param amount the amount to be deposited
* @param referralCode integrators are assigned a referral code and can potentially receive rewards.
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User deposits 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to deposit
* @param amount The amount to be deposited
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function deposit(
address reserve,
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @dev withdraws the assets of user.
* @param reserve the address of the reserve
* @param amount the underlying amount to be redeemed
* @param to address that will receive the underlying
* @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to Address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
**/
function withdraw(
address reserve,
address asset,
uint256 amount,
address to
) external;
/**
* @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower
* already deposited enough collateral.
* @param reserve the address of the reserve
* @param amount the amount to be borrowed
* @param interestRateMode the interest rate mode at which the user wants to borrow. Can be 0 (STABLE) or 1 (VARIABLE)
* @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already deposited enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
**/
function borrow(
address reserve,
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
@ -205,73 +226,86 @@ interface ILendingPool {
) external;
/**
* @notice repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
* @dev the target user is defined by onBehalfOf. If there is no repayment on behalf of another account,
* onBehalfOf must be equal to msg.sender.
* @param reserve the address of the reserve on which the user borrowed
* @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
* @param onBehalfOf the address for which msg.sender is repaying.
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
**/
function repay(
address reserve,
address asset,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external;
/**
* @dev borrowers can user this function to swap between stable and variable borrow rate modes.
* @param reserve the address of the reserve on which the user borrowed
* @param rateMode the rate mode that the user wants to swap
* @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
* @param asset The address of the underlying asset borrowed
* @param rateMode The rate mode that the user wants to swap to
**/
function swapBorrowRateMode(address reserve, uint256 rateMode) external;
function swapBorrowRateMode(address asset, uint256 rateMode) external;
/**
* @dev rebalances the stable interest rate of a user if current liquidity rate > user stable rate.
* this is regulated by Aave to ensure that the protocol is not abused, and the user is paying a fair
* rate. Anyone can call this function.
* @param reserve the address of the reserve
* @param user the address of the user to be rebalanced
* @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
* - Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
* borrowed at a stable rate and depositors are not earning enough
* @param asset The address of the underlying asset borrowed
* @param user The address of the user to be rebalanced
**/
function rebalanceStableBorrowRate(address reserve, address user) external;
function rebalanceStableBorrowRate(address asset, address user) external;
/**
* @dev allows depositors to enable or disable a specific deposit as collateral.
* @param reserve the address of the reserve
* @param useAsCollateral true if the user wants to user the deposit as collateral, false otherwise.
* @dev Allows depositors to enable/disable a specific deposited asset as collateral
* @param asset The address of the underlying asset deposited
* @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
**/
function setUserUseReserveAsCollateral(address reserve, bool useAsCollateral) external;
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @dev users can invoke this function to liquidate an undercollateralized position.
* @param reserve the address of the collateral to liquidated
* @param reserve the address of the principal reserve
* @param user the address of the borrower
* @param purchaseAmount the amount of principal that the liquidator wants to repay
* @param receiveAToken true if the liquidators wants to receive the aTokens, false if
* he wants to receive the underlying asset directly
* @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
function liquidationCall(
address collateral,
address reserve,
address collateralAsset,
address debtAsset,
address user,
uint256 purchaseAmount,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @dev allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned. NOTE There are security concerns for developers of flashloan receiver contracts
* that must be kept into consideration. For further details please visit https://developers.aave.com
* @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 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
* @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
* For further details please visit https://developers.aave.com
* @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts amounts being flash-borrowed
* @param modes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function flashLoan(
address receiver,
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata modes,
@ -280,24 +314,28 @@ interface ILendingPool {
uint16 referralCode
) external;
/**
* @dev Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralETH the total collateral in ETH of the user
* @return totalDebtETH the total debt in ETH of the user
* @return availableBorrowsETH the borrowing power left of the user
* @return currentLiquidationThreshold the liquidation threshold of the user
* @return ltv the loan to value of the user
* @return healthFactor the current health factor of the user
**/
function getUserAccountData(address user)
external
view
returns (
uint256 totalCollateralETH,
uint256 totalBorrowsETH,
uint256 totalDebtETH,
uint256 availableBorrowsETH,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
/**
* @dev initializes a reserve
* @param reserve the address of the reserve
* @param aTokenAddress the address of the overlying aToken contract
* @param interestRateStrategyAddress the address of the interest rate strategy contract
**/
function initReserve(
address reserve,
address aTokenAddress,
@ -306,29 +344,51 @@ interface ILendingPool {
address interestRateStrategyAddress
) external;
/**
* @dev updates the address of the interest rate strategy contract
* @param reserve the address of the reserve
* @param rateStrategyAddress the address of the interest rate strategy contract
**/
function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
external;
function setConfiguration(address reserve, uint256 configuration) external;
function getConfiguration(address reserve)
/**
* @dev Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
**/
function getConfiguration(address asset)
external
view
returns (ReserveConfiguration.Map memory);
returns (DataTypes.ReserveConfigurationMap memory);
function getUserConfiguration(address user) external view returns (UserConfiguration.Map memory);
/**
* @dev Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
**/
function getUserConfiguration(address user)
external
view
returns (DataTypes.UserConfigurationMap memory);
function getReserveNormalizedIncome(address reserve) external view returns (uint256);
/**
* @dev Returns the normalized income normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
function getReserveNormalizedVariableDebt(address reserve) external view returns (uint256);
/**
* @dev Returns the normalized variable debt per unit of asset
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
function getReserveData(address asset) external view returns (ReserveLogic.ReserveData memory);
/**
* @dev Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state of the reserve
**/
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
function finalizeTransfer(
address asset,
@ -343,14 +403,7 @@ interface ILendingPool {
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);
/**
* @dev Set the _pause state
* @param val the boolean value to set the current pause state of LendingPool
*/
function setPause(bool val) external;
/**
* @dev Returns if the LendingPool is paused
*/
function paused() external view returns (bool);
}

View File

@ -1,32 +1,27 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
@title ILendingPoolAddressesProvider interface
@notice provides the interface to fetch the Aave protocol address
*/
* @title LendingPoolAddressesProvider contract
* @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
* - Acting also as factory of proxies and admin of those, so with right to change its implementations
* - Owned by the Aave Governance
* @author Aave
**/
interface ILendingPoolAddressesProvider {
event LendingPoolUpdated(address indexed newAddress);
event ConfigurationAdminUpdated(address indexed newAddress);
event EmergencyAdminUpdated(address indexed newAddress);
event LendingPoolConfiguratorUpdated(address indexed newAddress);
event LendingPoolCollateralManagerUpdated(address indexed newAddress);
event EthereumAddressUpdated(address indexed newAddress);
event PriceOracleUpdated(address indexed newAddress);
event LendingRateOracleUpdated(address indexed newAddress);
event ProxyCreated(bytes32 id, address indexed newAddress);
event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);
function setAddress(
bytes32 id,
address newAddress
) external;
function setAddress(bytes32 id, address newAddress) external;
function setAddressAsProxy(
bytes32 id,
address impl
) external;
function setAddressAsProxy(bytes32 id, address impl) external;
function getAddress(bytes32 id) external view returns (address);

View File

@ -1,9 +1,13 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
* @title ILendingPoolAddressesProvider interface
* @notice provides the interface to fetch the LendingPoolCore address
* @title LendingPoolAddressesProviderRegistry contract
* @dev Main registry of LendingPoolAddressesProvider of multiple Aave protocol's markets
* - Used for indexing purposes of Aave protocol's markets
* - The id assigned to a LendingPoolAddressesProvider refers to the market it is connected with,
* for example with `0` for the Aave main market and `1` for the next created
* @author Aave
**/
interface ILendingPoolAddressesProviderRegistry {
event AddressesProviderRegistered(address indexed newAddress);
@ -11,8 +15,6 @@ interface ILendingPoolAddressesProviderRegistry {
function getAddressesProvidersList() external view returns (address[] memory);
function isAddressesProviderRegistered(address provider) external view returns (uint256);
function getAddressesProviderIdByAddress(address addressesProvider)
external
view

View File

@ -0,0 +1,53 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
/**
* @title ILendingPoolCollateralManager interface
* @author Aave
* @notice Defines the actions involving management of collateral in the protocol.
**/
interface ILendingPoolCollateralManager {
/**
* @dev emitted when a borrower is liquidated
* @param collateral the address of the collateral being liquidated
* @param principal the address of the reserve
* @param user the address of the user being liquidated
* @param debtToCover the total amount liquidated
* @param liquidatedCollateralAmount the amount of collateral being liquidated
* @param liquidator the address of the liquidator
* @param receiveAToken true if the liquidator wants to receive aTokens, false otherwise
**/
event LiquidationCall(
address indexed collateral,
address indexed principal,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev emitted when a user disables a reserve as collateral
* @param reserve the address of the reserve
* @param user the address of the user
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev users can invoke this function to liquidate an undercollateralized position.
* @param collateral the address of the collateral to liquidated
* @param principal the address of the principal reserve
* @param user the address of the borrower
* @param debtToCover the amount of principal that the liquidator wants to repay
* @param receiveAToken true if the liquidators wants to receive the aTokens, false if
* he wants to receive the underlying asset directly
**/
function liquidationCall(
address collateral,
address principal,
address user,
uint256 debtToCover,
bool receiveAToken
) external returns (uint256, string memory);
}

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
* @title ILendingRateOracle interface

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/************
@title IPriceOracle interface

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
* @title IPriceOracleGetter interface

View File

@ -1,27 +1,16 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
@title IReserveInterestRateStrategyInterface interface
@notice Interface for the calculation of the interest rates.
*/
* @title IReserveInterestRateStrategyInterface interface
* @dev Interface for the calculation of the interest rates
* @author Aave
*/
interface IReserveInterestRateStrategy {
/**
* @dev returns the base variable borrow rate, in rays
*/
function baseVariableBorrowRate() external view returns (uint256);
/**
* @dev returns the maximum variable borrow rate
*/
function getMaxVariableBorrowRate() external view returns (uint256);
/**
* @dev calculates the liquidity, stable, and variable rates depending on the current utilization rate
* and the base parameters
*
*/
function calculateInterestRates(
address reserve,
uint256 utilizationRate,

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface IUniswapExchange {
event TokenPurchase(

View File

@ -1,340 +0,0 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
import {SafeMath} from '../dependencies/openzeppelin/contracts//SafeMath.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts//IERC20.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {Helpers} from '../libraries/helpers/Helpers.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
import {LendingPoolStorage} from './LendingPoolStorage.sol';
/**
* @title LendingPoolCollateralManager contract
* @author Aave
* @notice Implements actions involving management of collateral in the protocol.
* @notice this contract will be ran always through delegatecall
* @dev LendingPoolCollateralManager inherits VersionedInitializable from OpenZeppelin to have the same storage layout as LendingPool
**/
contract LendingPoolCollateralManager is VersionedInitializable, LendingPoolStorage {
using SafeERC20 for IERC20;
using SafeMath for uint256;
using WadRayMath for uint256;
using PercentageMath for uint256;
// IMPORTANT The storage layout of the LendingPool is reproduced here because this contract
// is gonna be used through DELEGATECALL
uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000;
/**
* @dev emitted when a borrower is liquidated
* @param collateral the address of the collateral being liquidated
* @param principal the address of the reserve
* @param user the address of the user being liquidated
* @param purchaseAmount the total amount liquidated
* @param liquidatedCollateralAmount the amount of collateral being liquidated
* @param liquidator the address of the liquidator
* @param receiveAToken true if the liquidator wants to receive aTokens, false otherwise
**/
event LiquidationCall(
address indexed collateral,
address indexed principal,
address indexed user,
uint256 purchaseAmount,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev emitted when a user disables a reserve as collateral
* @param reserve the address of the reserve
* @param user the address of the user
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
struct LiquidationCallLocalVars {
uint256 userCollateralBalance;
uint256 userStableDebt;
uint256 userVariableDebt;
uint256 maxPrincipalAmountToLiquidate;
uint256 actualAmountToLiquidate;
uint256 liquidationRatio;
uint256 maxAmountCollateralToLiquidate;
uint256 userStableRate;
uint256 maxCollateralToLiquidate;
uint256 principalAmountNeeded;
uint256 healthFactor;
IAToken collateralAtoken;
bool isCollateralEnabled;
ReserveLogic.InterestRateMode borrowRateMode;
address principalAToken;
uint256 errorCode;
string errorMsg;
}
struct AvailableCollateralToLiquidateLocalVars {
uint256 userCompoundedBorrowBalance;
uint256 liquidationBonus;
uint256 collateralPrice;
uint256 principalCurrencyPrice;
uint256 maxAmountCollateralToLiquidate;
uint256 principalDecimals;
uint256 collateralDecimals;
}
/**
* @dev as the contract extends the VersionedInitializable contract to match the state
* of the LendingPool contract, the getRevision() function is needed.
*/
function getRevision() internal override pure returns (uint256) {
return 0;
}
/**
* @dev users can invoke this function to liquidate an undercollateralized position.
* @param collateral the address of the collateral to liquidated
* @param principal the address of the principal reserve
* @param user the address of the borrower
* @param purchaseAmount the amount of principal that the liquidator wants to repay
* @param receiveAToken true if the liquidators wants to receive the aTokens, false if
* he wants to receive the underlying asset directly
**/
function liquidationCall(
address collateral,
address principal,
address user,
uint256 purchaseAmount,
bool receiveAToken
) external returns (uint256, string memory) {
ReserveLogic.ReserveData storage collateralReserve = _reserves[collateral];
ReserveLogic.ReserveData storage principalReserve = _reserves[principal];
UserConfiguration.Map storage userConfig = _usersConfig[user];
LiquidationCallLocalVars memory vars;
(, , , , vars.healthFactor) = GenericLogic.calculateUserAccountData(
user,
_reserves,
userConfig,
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
//if the user hasn't borrowed the specific currency defined by asset, it cannot be liquidated
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(
user,
principalReserve
);
(vars.errorCode, vars.errorMsg) = ValidationLogic.validateLiquidationCall(
collateralReserve,
principalReserve,
userConfig,
vars.healthFactor,
vars.userStableDebt,
vars.userVariableDebt
);
if (Errors.CollateralManagerErrors(vars.errorCode) != Errors.CollateralManagerErrors.NO_ERROR) {
return (vars.errorCode, vars.errorMsg);
}
vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress);
vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user);
vars.maxPrincipalAmountToLiquidate = vars.userStableDebt.add(vars.userVariableDebt).percentMul(
LIQUIDATION_CLOSE_FACTOR_PERCENT
);
vars.actualAmountToLiquidate = purchaseAmount > vars.maxPrincipalAmountToLiquidate
? vars.maxPrincipalAmountToLiquidate
: purchaseAmount;
(
vars.maxCollateralToLiquidate,
vars.principalAmountNeeded
) = _calculateAvailableCollateralToLiquidate(
collateralReserve,
principalReserve,
collateral,
principal,
vars.actualAmountToLiquidate,
vars.userCollateralBalance
);
//if principalAmountNeeded < vars.ActualAmountToLiquidate, there isn't enough
//of collateral to cover the actual amount that is being liquidated, hence we liquidate
//a smaller amount
if (vars.principalAmountNeeded < vars.actualAmountToLiquidate) {
vars.actualAmountToLiquidate = vars.principalAmountNeeded;
}
//if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve
if (!receiveAToken) {
uint256 currentAvailableCollateral = IERC20(collateral).balanceOf(
address(vars.collateralAtoken)
);
if (currentAvailableCollateral < vars.maxCollateralToLiquidate) {
return (
uint256(Errors.CollateralManagerErrors.NOT_ENOUGH_LIQUIDITY),
Errors.LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE
);
}
}
//update the principal reserve
principalReserve.updateState();
if (vars.userVariableDebt >= vars.actualAmountToLiquidate) {
IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
user,
vars.actualAmountToLiquidate,
principalReserve.variableBorrowIndex
);
} else {
//if the user does not have variable debt, no need to try to burn variable
//debt tokens
if (vars.userVariableDebt > 0) {
IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
user,
vars.userVariableDebt,
principalReserve.variableBorrowIndex
);
}
IStableDebtToken(principalReserve.stableDebtTokenAddress).burn(
user,
vars.actualAmountToLiquidate.sub(vars.userVariableDebt)
);
}
principalReserve.updateInterestRates(
principal,
principalReserve.aTokenAddress,
vars.actualAmountToLiquidate,
0
);
//if liquidator reclaims the aToken, he receives the equivalent atoken amount
if (receiveAToken) {
vars.collateralAtoken.transferOnLiquidation(user, msg.sender, vars.maxCollateralToLiquidate);
} else {
//otherwise receives the underlying asset
//updating collateral reserve
collateralReserve.updateState();
collateralReserve.updateInterestRates(
collateral,
address(vars.collateralAtoken),
0,
vars.maxCollateralToLiquidate
);
//burn the equivalent amount of atoken
vars.collateralAtoken.burn(
user,
msg.sender,
vars.maxCollateralToLiquidate,
collateralReserve.liquidityIndex
);
}
//if the collateral being liquidated is equal to the user balance,
//we set the currency as not being used as collateral anymore
if (vars.maxCollateralToLiquidate == vars.userCollateralBalance) {
userConfig.setUsingAsCollateral(collateralReserve.id, false);
emit ReserveUsedAsCollateralDisabled(collateral, user);
}
//transfers the principal currency to the aToken
IERC20(principal).safeTransferFrom(
msg.sender,
principalReserve.aTokenAddress,
vars.actualAmountToLiquidate
);
emit LiquidationCall(
collateral,
principal,
user,
vars.actualAmountToLiquidate,
vars.maxCollateralToLiquidate,
msg.sender,
receiveAToken
);
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.LPCM_NO_ERRORS);
}
/**
* @dev calculates how much of a specific collateral can be liquidated, given
* a certain amount of principal currency. This function needs to be called after
* all the checks to validate the liquidation have been performed, otherwise it might fail.
* @param collateralAddress the collateral to be liquidated
* @param principalAddress the principal currency to be liquidated
* @param purchaseAmount the amount of principal being liquidated
* @param userCollateralBalance the collatera balance for the specific collateral asset of the user being liquidated
* @return collateralAmount the maximum amount that is possible to liquidated given all the liquidation constraints (user balance, close factor)
* @return principalAmountNeeded the purchase amount
**/
function _calculateAvailableCollateralToLiquidate(
ReserveLogic.ReserveData storage collateralReserve,
ReserveLogic.ReserveData storage principalReserve,
address collateralAddress,
address principalAddress,
uint256 purchaseAmount,
uint256 userCollateralBalance
) internal view returns (uint256, uint256) {
uint256 collateralAmount = 0;
uint256 principalAmountNeeded = 0;
IPriceOracleGetter oracle = IPriceOracleGetter(_addressesProvider.getPriceOracle());
AvailableCollateralToLiquidateLocalVars memory vars;
vars.collateralPrice = oracle.getAssetPrice(collateralAddress);
vars.principalCurrencyPrice = oracle.getAssetPrice(principalAddress);
(, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve
.configuration
.getParams();
vars.principalDecimals = principalReserve.configuration.getDecimals();
//this is the maximum possible amount of the selected collateral that can be liquidated, given the
//max amount of principal currency that is available for liquidation.
vars.maxAmountCollateralToLiquidate = vars
.principalCurrencyPrice
.mul(purchaseAmount)
.mul(10**vars.collateralDecimals)
.percentMul(vars.liquidationBonus)
.div(vars.collateralPrice.mul(10**vars.principalDecimals));
if (vars.maxAmountCollateralToLiquidate > userCollateralBalance) {
collateralAmount = userCollateralBalance;
principalAmountNeeded = vars
.collateralPrice
.mul(collateralAmount)
.mul(10**vars.principalDecimals)
.div(vars.principalCurrencyPrice.mul(10**vars.collateralDecimals))
.percentDiv(vars.liquidationBonus);
} else {
collateralAmount = vars.maxAmountCollateralToLiquidate;
principalAmountNeeded = purchaseAmount;
}
return (collateralAmount, principalAmountNeeded);
}
}

View File

@ -1,40 +0,0 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
import {DebtTokenBase} from '../../tokenization/base/DebtTokenBase.sol';
import {ReserveLogic} from '../logic/ReserveLogic.sol';
/**
* @title Helpers library
* @author Aave
* @notice Implements calculation helpers.
*/
library Helpers {
/**
* @dev fetches the user current stable and variable debt balances
* @param user the user
* @param reserve the reserve object
* @return the stable and variable debt balance
**/
function getUserCurrentDebt(address user, ReserveLogic.ReserveData storage reserve)
internal
view
returns (uint256, uint256)
{
return (
DebtTokenBase(reserve.stableDebtTokenAddress).balanceOf(user),
DebtTokenBase(reserve.variableDebtTokenAddress).balanceOf(user)
);
}
function getUserCurrentDebtMemory(address user, ReserveLogic.ReserveData memory reserve)
internal
view
returns (uint256, uint256)
{
return (
DebtTokenBase(reserve.stableDebtTokenAddress).balanceOf(user),
DebtTokenBase(reserve.variableDebtTokenAddress).balanceOf(user)
);
}
}

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';

View File

@ -1,20 +1,19 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
import 'hardhat/console.sol';
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol';
import {IStableDebtToken} from '../protocol/tokenization/interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../protocol/tokenization/interfaces/IVariableDebtToken.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
contract AaveProtocolDataProvider {
using ReserveConfiguration for ReserveConfiguration.Map;
using UserConfiguration for UserConfiguration.Map;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
address constant MKR = 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2;
address constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
@ -56,7 +55,7 @@ contract AaveProtocolDataProvider {
address[] memory reserves = pool.getReservesList();
TokenData[] memory aTokens = new TokenData[](reserves.length);
for (uint256 i = 0; i < reserves.length; i++) {
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(reserves[i]);
DataTypes.ReserveData memory reserveData = pool.getReserveData(reserves[i]);
aTokens[i] = TokenData({
symbol: IERC20Detailed(reserveData.aTokenAddress).symbol(),
tokenAddress: reserveData.aTokenAddress
@ -81,10 +80,8 @@ contract AaveProtocolDataProvider {
bool isFrozen
)
{
ReserveConfiguration.Map memory configuration = ILendingPool(
ADDRESSES_PROVIDER.getLendingPool()
)
.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory configuration =
ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset);
(ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = configuration
.getParamsMemory();
@ -111,8 +108,8 @@ contract AaveProtocolDataProvider {
uint40 lastUpdateTimestamp
)
{
ReserveLogic.ReserveData memory reserve = ILendingPool(ADDRESSES_PROVIDER.getLendingPool())
.getReserveData(asset);
DataTypes.ReserveData memory reserve =
ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getReserveData(asset);
return (
IERC20Detailed(asset).balanceOf(reserve.aTokenAddress),
@ -143,11 +140,11 @@ contract AaveProtocolDataProvider {
bool usageAsCollateralEnabled
)
{
ReserveLogic.ReserveData memory reserve = ILendingPool(ADDRESSES_PROVIDER.getLendingPool())
.getReserveData(asset);
DataTypes.ReserveData memory reserve =
ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getReserveData(asset);
UserConfiguration.Map memory userConfig = ILendingPool(ADDRESSES_PROVIDER.getLendingPool())
.getUserConfiguration(user);
DataTypes.UserConfigurationMap memory userConfig =
ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getUserConfiguration(user);
currentATokenBalance = IERC20Detailed(reserve.aTokenAddress).balanceOf(user);
currentVariableDebt = IERC20Detailed(reserve.variableDebtTokenAddress).balanceOf(user);
@ -171,8 +168,8 @@ contract AaveProtocolDataProvider {
address variableDebtTokenAddress
)
{
ReserveLogic.ReserveData memory reserve = ILendingPool(ADDRESSES_PROVIDER.getLendingPool())
.getReserveData(asset);
DataTypes.ReserveData memory reserve =
ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getReserveData(asset);
return (
reserve.aTokenAddress,

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
@ -7,22 +7,22 @@ import {IUiPoolDataProvider} from './interfaces/IUiPoolDataProvider.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
import {IAToken} from '../protocol/tokenization/interfaces/IAToken.sol';
import {IVariableDebtToken} from '../protocol/tokenization/interfaces/IVariableDebtToken.sol';
import {IStableDebtToken} from '../protocol/tokenization/interfaces/IStableDebtToken.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {WadRayMath} from '../protocol/libraries/math/WadRayMath.sol';
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol';
import {
DefaultReserveInterestRateStrategy
} from '../lendingpool/DefaultReserveInterestRateStrategy.sol';
} from '../protocol/lendingpool/DefaultReserveInterestRateStrategy.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
contract UiPoolDataProvider is IUiPoolDataProvider {
using WadRayMath for uint256;
using ReserveConfiguration for ReserveConfiguration.Map;
using UserConfiguration for UserConfiguration.Map;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
@ -46,8 +46,8 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
function getReservesData(ILendingPoolAddressesProvider provider, address user)
external
override
view
override
returns (
AggregatedReserveData[] memory,
UserReserveData[] memory,
@ -57,21 +57,19 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle());
address[] memory reserves = lendingPool.getReservesList();
UserConfiguration.Map memory userConfig = lendingPool.getUserConfiguration(user);
DataTypes.UserConfigurationMap memory userConfig = lendingPool.getUserConfiguration(user);
AggregatedReserveData[] memory reservesData = new AggregatedReserveData[](reserves.length);
UserReserveData[] memory userReservesData = new UserReserveData[](
user != address(0) ? reserves.length : 0
);
UserReserveData[] memory userReservesData =
new UserReserveData[](user != address(0) ? reserves.length : 0);
for (uint256 i = 0; i < reserves.length; i++) {
AggregatedReserveData memory reserveData = reservesData[i];
reserveData.underlyingAsset = reserves[i];
// reserve current state
ReserveLogic.ReserveData memory baseData = lendingPool.getReserveData(
reserveData.underlyingAsset
);
DataTypes.ReserveData memory baseData =
lendingPool.getReserveData(reserveData.underlyingAsset);
reserveData.liquidityIndex = baseData.liquidityIndex;
reserveData.variableBorrowIndex = baseData.variableBorrowIndex;
reserveData.liquidityRate = baseData.currentLiquidityRate;

View File

@ -1,21 +1,21 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {IWETH} from './interfaces/IWETH.sol';
import {IWETHGateway} from './interfaces/IWETHGateway.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {Helpers} from '../libraries/helpers/Helpers.sol';
import {IAToken} from '../protocol/tokenization/interfaces/IAToken.sol';
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol';
import {Helpers} from '../protocol/libraries/helpers/Helpers.sol';
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
contract WETHGateway is IWETHGateway, Ownable {
using ReserveConfiguration for ReserveConfiguration.Map;
using UserConfiguration for UserConfiguration.Map;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
IWETH internal immutable WETH;
ILendingPool internal immutable POOL;
@ -40,7 +40,7 @@ contract WETHGateway is IWETHGateway, Ownable {
* @param onBehalfOf address of the user who will receive the aTokens representing the deposit
* @param referralCode integrators are assigned a referral code and can potentially receive rewards.
**/
function depositETH(address onBehalfOf, uint16 referralCode) external override payable {
function depositETH(address onBehalfOf, uint16 referralCode) external payable override {
WETH.deposit{value: msg.value}();
POOL.deposit(address(WETH), msg.value, onBehalfOf, referralCode);
}
@ -74,16 +74,14 @@ contract WETHGateway is IWETHGateway, Ownable {
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external override payable {
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebtMemory(
onBehalfOf,
POOL.getReserveData(address(WETH))
);
) external payable override {
(uint256 stableDebt, uint256 variableDebt) =
Helpers.getUserCurrentDebtMemory(onBehalfOf, POOL.getReserveData(address(WETH)));
uint256 paybackAmount = ReserveLogic.InterestRateMode(rateMode) ==
ReserveLogic.InterestRateMode.STABLE
? stableDebt
: variableDebt;
uint256 paybackAmount =
DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE
? stableDebt
: variableDebt;
if (amount < paybackAmount) {
paybackAmount = amount;

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
@ -9,7 +9,8 @@ import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title WalletBalanceProvider contract
@ -22,15 +23,10 @@ contract WalletBalanceProvider {
using Address for address payable;
using Address for address;
using SafeERC20 for IERC20;
using ReserveConfiguration for ReserveConfiguration.Map;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
ILendingPoolAddressesProvider internal immutable _provider;
address constant MOCK_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
constructor(ILendingPoolAddressesProvider provider) public {
_provider = provider;
}
/**
@dev Fallback function, don't accept any ETH
**/
@ -80,12 +76,12 @@ contract WalletBalanceProvider {
/**
@dev provides balances of user wallet for all reserves available on the pool
*/
function getUserWalletBalances(address user)
function getUserWalletBalances(address provider, address user)
external
view
returns (address[] memory, uint256[] memory)
{
ILendingPool pool = ILendingPool(_provider.getLendingPool());
ILendingPool pool = ILendingPool(ILendingPoolAddressesProvider(provider).getLendingPool());
address[] memory reserves = pool.getReservesList();
address[] memory reservesWithEth = new address[](reserves.length + 1);
@ -97,7 +93,7 @@ contract WalletBalanceProvider {
uint256[] memory balances = new uint256[](reservesWithEth.length);
for (uint256 j = 0; j < reserves.length; j++) {
ReserveConfiguration.Map memory configuration = pool.getConfiguration(reservesWithEth[j]);
DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(reservesWithEth[j]);
(bool isActive, , , ) = configuration.getFlagsMemory();

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
contract IERC20DetailedBytes {
bytes32 public name;

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {ReserveLogic} from '../../libraries/logic/ReserveLogic.sol';
interface IUiPoolDataProvider {
struct AggregatedReserveData {

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface IWETH {
function deposit() external payable;

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface IWETHGateway {
function depositETH(address onBehalfOf, uint16 referralCode) external payable;

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
contract SelfdestructTransfer {
function destroyAndTransfer(address payable to) external payable {

View File

@ -13,7 +13,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.4.22 <=0.6.8;
pragma solidity >=0.4.22 <=0.6.12;
contract WETH9 {
string public name = 'Wrapped Ether';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
contract MockAggregator {
int256 private _latestAnswer;

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface ChainlinkUSDETHOracleI {
event AnswerUpdated(int256 indexed current, uint256 indexed answerId);

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface GenericOracleI {
// ganache

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface IExtendedPriceAggregator {
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp);

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol';
import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {IPriceOracle} from '../../interfaces/IPriceOracle.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {ERC20} from '../../dependencies/openzeppelin/contracts/ERC20.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {ERC20} from '../../dependencies/openzeppelin/contracts/ERC20.sol';

View File

@ -1,4 +1,5 @@
pragma solidity >=0.4.22 <=0.6.8;
// SPDX-License-Identifier: agpl-3.0
pragma solidity >=0.4.22 <=0.6.12;
import {WETH9} from '../dependencies/weth/WETH9.sol';

View File

@ -1,8 +1,8 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {AToken} from '../../tokenization/AToken.sol';
import {LendingPool} from '../../lendingpool/LendingPool.sol';
import {AToken} from '../../protocol/tokenization/AToken.sol';
import {LendingPool} from '../../protocol/lendingpool/LendingPool.sol';
contract MockAToken is AToken {
constructor(
@ -24,7 +24,7 @@ contract MockAToken is AToken {
)
{}
function getRevision() internal override pure returns (uint256) {
function getRevision() internal pure override returns (uint256) {
return 0x2;
}

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {StableDebtToken} from '../../tokenization/StableDebtToken.sol';
import {StableDebtToken} from '../../protocol/tokenization/StableDebtToken.sol';
contract MockStableDebtToken is StableDebtToken {
constructor(
@ -15,7 +15,7 @@ contract MockStableDebtToken is StableDebtToken {
StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController)
{}
function getRevision() internal override pure returns (uint256) {
function getRevision() internal pure override returns (uint256) {
return 0x2;
}
}

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {VariableDebtToken} from '../../tokenization/VariableDebtToken.sol';
import {VariableDebtToken} from '../../protocol/tokenization/VariableDebtToken.sol';
contract MockVariableDebtToken is VariableDebtToken {
constructor(
@ -21,7 +21,7 @@ contract MockVariableDebtToken is VariableDebtToken {
)
{}
function getRevision() internal override pure returns (uint256) {
function getRevision() internal pure override returns (uint256) {
return 0x2;
}
}

View File

@ -1,21 +1,21 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol';
// Prettier ignore to prevent buidler flatter bug
// prettier-ignore
import {InitializableImmutableAdminUpgradeabilityProxy} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
/**
* @title LendingPoolAddressesProvider contract
* @notice Is the main registry of the protocol. All the different components of the protocol are accessible
* through the addresses provider.
* @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
* - Acting also as factory of proxies and admin of those, so with right to change its implementations
* - Owned by the Aave Governance
* @author Aave
**/
contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider {
mapping(bytes32 => address) private _addresses;
@ -28,28 +28,30 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
bytes32 private constant LENDING_RATE_ORACLE = 'LENDING_RATE_ORACLE';
/**
* @dev Sets an address for an id by updating a proxy implementation
* @dev General function to update the implementation of a proxy registered with
* certain `id`. If there is no proxy registered, it will instantiate one and
* set as implementation the `implementationAddress`
* IMPORTANT Use this function carefully, only for ids that don't have an explicit
* setter function, in order to avoid unexpected consequences
* @param id The id
* @param implementationAddress The address of the implementation if we want it covered by a proxy
* address(0) if we don't want a proxy covering
* @param implementationAddress The address of the new implementation
*/
function setAddressAsProxy(
bytes32 id,
address implementationAddress
) external override onlyOwner {
function setAddressAsProxy(bytes32 id, address implementationAddress)
external
override
onlyOwner
{
_updateImpl(id, implementationAddress);
emit AddressSet(id, implementationAddress, true);
}
/**
* @dev Sets an address for an id replacing the address saved in the addresses map
* IMPORTANT Use this function carefully, as it will do a hard replacement
* @param id The id
* @param newAddress The address to set, pass address(0) if a proxy is needed
* @param newAddress The address to set
*/
function setAddress(
bytes32 id,
address newAddress
) external override onlyOwner {
function setAddress(bytes32 id, address newAddress) external override onlyOwner {
_addresses[id] = newAddress;
emit AddressSet(id, newAddress, false);
}
@ -58,21 +60,22 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
* @dev Returns an address by id
* @return The address
*/
function getAddress(bytes32 id) public override view returns (address) {
function getAddress(bytes32 id) public view override returns (address) {
return _addresses[id];
}
/**
* @dev returns the address of the LendingPool proxy
* @return the lending pool proxy address
* @dev Returns the address of the LendingPool proxy
* @return The LendingPool proxy address
**/
function getLendingPool() external override view returns (address) {
function getLendingPool() external view override returns (address) {
return getAddress(LENDING_POOL);
}
/**
* @dev updates the implementation of the lending pool
* @param pool the new lending pool implementation
* @dev Updates the implementation of the LendingPool, or creates the proxy
* setting the new `pool` implementation on the first time calling it
* @param pool The new LendingPool implementation
**/
function setLendingPoolImpl(address pool) external override onlyOwner {
_updateImpl(LENDING_POOL, pool);
@ -80,16 +83,17 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
}
/**
* @dev returns the address of the LendingPoolConfigurator proxy
* @return the lending pool configurator proxy address
* @dev Returns the address of the LendingPoolConfigurator proxy
* @return The LendingPoolConfigurator proxy address
**/
function getLendingPoolConfigurator() external override view returns (address) {
function getLendingPoolConfigurator() external view override returns (address) {
return getAddress(LENDING_POOL_CONFIGURATOR);
}
/**
* @dev updates the implementation of the lending pool configurator
* @param configurator the new lending pool configurator implementation
* @dev Updates the implementation of the LendingPoolConfigurator, or creates the proxy
* setting the new `configurator` implementation on the first time calling it
* @param configurator The new LendingPoolConfigurator implementation
**/
function setLendingPoolConfiguratorImpl(address configurator) external override onlyOwner {
_updateImpl(LENDING_POOL_CONFIGURATOR, configurator);
@ -97,19 +101,19 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
}
/**
* @dev returns the address of the LendingPoolCollateralManager. Since the manager is used
* @dev Returns the address of the LendingPoolCollateralManager. Since the manager is used
* through delegateCall within the LendingPool contract, the proxy contract pattern does not work properly hence
* the addresses are changed directly.
* @return the address of the Lending pool collateral manager
* the addresses are changed directly
* @return The address of the LendingPoolCollateralManager
**/
function getLendingPoolCollateralManager() external override view returns (address) {
function getLendingPoolCollateralManager() external view override returns (address) {
return getAddress(LENDING_POOL_COLLATERAL_MANAGER);
}
/**
* @dev updates the address of the Lending pool collateral manager
* @param manager the new lending pool collateral manager address
* @dev Updates the address of the LendingPoolCollateralManager
* @param manager The new LendingPoolCollateralManager address
**/
function setLendingPoolCollateralManager(address manager) external override onlyOwner {
_addresses[LENDING_POOL_COLLATERAL_MANAGER] = manager;
@ -117,11 +121,11 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
}
/**
* @dev the functions below are storing specific addresses that are outside the context of the protocol
* hence the upgradable proxy pattern is not used
* @dev The functions below are getters/setters of addresses that are outside the context
* of the protocol hence the upgradable proxy pattern is not used
**/
function getPoolAdmin() external override view returns (address) {
function getPoolAdmin() external view override returns (address) {
return getAddress(POOL_ADMIN);
}
@ -130,7 +134,7 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
emit ConfigurationAdminUpdated(admin);
}
function getEmergencyAdmin() external override view returns (address) {
function getEmergencyAdmin() external view override returns (address) {
return getAddress(EMERGENCY_ADMIN);
}
@ -139,7 +143,7 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
emit EmergencyAdminUpdated(emergencyAdmin);
}
function getPriceOracle() external override view returns (address) {
function getPriceOracle() external view override returns (address) {
return getAddress(PRICE_ORACLE);
}
@ -148,7 +152,7 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
emit PriceOracleUpdated(priceOracle);
}
function getLendingRateOracle() external override view returns (address) {
function getLendingRateOracle() external view override returns (address) {
return getAddress(LENDING_RATE_ORACLE);
}
@ -158,16 +162,19 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
}
/**
* @dev internal function to update the implementation of a specific component of the protocol
* @param id the id of the contract to be updated
* @param newAddress the address of the new implementation
* @dev Internal function to update the implementation of a specific proxied component of the protocol
* - If there is no proxy registered in the given `id`, it creates the proxy setting `newAdress`
* as implementation and calls the initialize() function on the proxy
* - If there is already a proxy registered, it just updates the implementation to `newAddress` and
* calls the initialize() function via upgradeToAndCall() in the proxy
* @param id The id of the proxy to be updated
* @param newAddress The address of the new implementation
**/
function _updateImpl(bytes32 id, address newAddress) internal {
address payable proxyAddress = payable(_addresses[id]);
InitializableImmutableAdminUpgradeabilityProxy proxy
= InitializableImmutableAdminUpgradeabilityProxy(proxyAddress);
InitializableImmutableAdminUpgradeabilityProxy proxy =
InitializableImmutableAdminUpgradeabilityProxy(proxyAddress);
bytes memory params = abi.encodeWithSignature('initialize(address)', address(this));
if (proxyAddress == address(0)) {

View File

@ -1,41 +1,29 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol';
import {
ILendingPoolAddressesProviderRegistry
} from '../interfaces/ILendingPoolAddressesProviderRegistry.sol';
} from '../../interfaces/ILendingPoolAddressesProviderRegistry.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
/**
* @title LendingPoolAddressesProviderRegistry contract
* @notice contains the list of active addresses providers
* @dev Main registry of LendingPoolAddressesProvider of multiple Aave protocol's markets
* - Used for indexing purposes of Aave protocol's markets
* - The id assigned to a LendingPoolAddressesProvider refers to the market it is connected with,
* for example with `0` for the Aave main market and `1` for the next created
* @author Aave
**/
contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesProviderRegistry {
mapping(address => uint256) private _addressesProviders;
address[] private _addressesProvidersList;
/**
* @dev returns if an addressesProvider is registered or not
* @param provider the addresses provider
* @return The id of the addresses provider or 0 if the addresses provider not registered
* @dev Returns the list of registered addresses provider
* @return The list of addresses provider, potentially containing address(0) elements
**/
function isAddressesProviderRegistered(address provider)
external
override
view
returns (uint256)
{
return _addressesProviders[provider];
}
/**
* @dev returns the list of active addressesProviders
* @return the list of addressesProviders, potentially containing address(0) elements
**/
function getAddressesProvidersList() external override view returns (address[] memory) {
function getAddressesProvidersList() external view override returns (address[] memory) {
address[] memory addressesProvidersList = _addressesProvidersList;
uint256 maxLength = addressesProvidersList.length;
@ -52,8 +40,9 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
}
/**
* @dev adds a lending pool to the list of registered lending pools
* @param provider the pool address to be registered
* @dev Registers an addresses provider
* @param provider The address of the new LendingPoolAddressesProvider
* @param id The id for the new LendingPoolAddressesProvider, referring to the market it belongs to
**/
function registerAddressesProvider(address provider, uint256 id) external override onlyOwner {
require(id != 0, Errors.LPAPR_INVALID_ADDRESSES_PROVIDER_ID);
@ -64,8 +53,8 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
}
/**
* @dev removes a lending pool from the list of registered lending pools
* @param provider the pool address to be unregistered
* @dev Removes a LendingPoolAddressesProvider from the list of registered addresses provider
* @param provider The LendingPoolAddressesProvider address
**/
function unregisterAddressesProvider(address provider) external override onlyOwner {
require(_addressesProviders[provider] > 0, Errors.LPAPR_PROVIDER_NOT_REGISTERED);
@ -74,9 +63,18 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
}
/**
* @dev adds to the list of the addresses providers, if it wasn't already added before
* @param provider the pool address to be added
**/
* @dev Returns the id on a registered LendingPoolAddressesProvider
* @return The id or 0 if the LendingPoolAddressesProvider is not registered
*/
function getAddressesProviderIdByAddress(address addressesProvider)
external
view
override
returns (uint256)
{
return _addressesProviders[addressesProvider];
}
function _addToAddressesProvidersList(address provider) internal {
uint256 providersCount = _addressesProvidersList.length;
@ -88,17 +86,4 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
_addressesProvidersList.push(provider);
}
/**
* @dev Returns the id on an `addressesProvider` or address(0) if not registered
* @return The id or 0 if the addresses provider is not registered
*/
function getAddressesProviderIdByAddress(address addressesProvider)
external
override
view
returns (uint256)
{
return _addressesProviders[addressesProvider];
}
}

View File

@ -1,63 +1,69 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IReserveInterestRateStrategy} from '../interfaces/IReserveInterestRateStrategy.sol';
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IReserveInterestRateStrategy} from '../../interfaces/IReserveInterestRateStrategy.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {LendingPoolAddressesProvider} from '../configuration/LendingPoolAddressesProvider.sol';
import {ILendingRateOracle} from '../interfaces/ILendingRateOracle.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol';
/**
* @title DefaultReserveInterestRateStrategy contract
* @notice implements the calculation of the interest rates depending on the reserve parameters.
* @dev if there is need to update the calculation of the interest rates for a specific reserve,
* a new version of this contract will be deployed.
* @notice Implements the calculation of the interest rates depending on the reserve state
* @dev The model of interest rate is based on 2 slopes, one before the `OPTIMAL_UTILIZATION_RATE`
* point of utilization and another from that one to 100%
* - An instance of this same contract, can't be used across different Aave markets, due to the caching
* of the LendingPoolAddressesProvider
* @author Aave
**/
contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
using WadRayMath for uint256;
using SafeMath for uint256;
using PercentageMath for uint256;
/**
* @dev this constant represents the utilization rate at which the pool aims to obtain most competitive borrow rates
* expressed in ray
**/
uint256 public constant OPTIMAL_UTILIZATION_RATE = 0.8 * 1e27;
/**
* @dev this constant represents the excess utilization rate above the optimal. It's always equal to
* 1-optimal utilization rate. Added as a constant here for gas optimizations
* expressed in ray
* @dev this constant represents the utilization rate at which the pool aims to obtain most competitive borrow rates.
* Expressed in ray
**/
uint256 public immutable OPTIMAL_UTILIZATION_RATE;
/**
* @dev This constant represents the excess utilization rate above the optimal. It's always equal to
* 1-optimal utilization rate. Added as a constant here for gas optimizations.
* Expressed in ray
**/
uint256 public constant EXCESS_UTILIZATION_RATE = 0.2 * 1e27;
uint256 public immutable EXCESS_UTILIZATION_RATE;
LendingPoolAddressesProvider public immutable addressesProvider;
ILendingPoolAddressesProvider public immutable addressesProvider;
//base variable borrow rate when Utilization rate = 0. Expressed in ray
// Base variable borrow rate when Utilization rate = 0. Expressed in ray
uint256 internal immutable _baseVariableBorrowRate;
//slope of the variable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
// Slope of the variable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable _variableRateSlope1;
//slope of the variable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
// Slope of the variable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable _variableRateSlope2;
//slope of the stable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
// Slope of the stable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable _stableRateSlope1;
//slope of the stable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
// Slope of the stable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable _stableRateSlope2;
constructor(
LendingPoolAddressesProvider provider,
ILendingPoolAddressesProvider provider,
uint256 optimalUtilizationRate,
uint256 baseVariableBorrowRate,
uint256 variableRateSlope1,
uint256 variableRateSlope2,
uint256 stableRateSlope1,
uint256 stableRateSlope2
) public {
OPTIMAL_UTILIZATION_RATE = optimalUtilizationRate;
EXCESS_UTILIZATION_RATE = WadRayMath.ray().sub(optimalUtilizationRate);
addressesProvider = provider;
_baseVariableBorrowRate = baseVariableBorrowRate;
_variableRateSlope1 = variableRateSlope1;
@ -66,10 +72,6 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
_stableRateSlope2 = stableRateSlope2;
}
/**
* @dev accessors
*/
function variableRateSlope1() external view returns (uint256) {
return _variableRateSlope1;
}
@ -86,16 +88,16 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
return _stableRateSlope2;
}
function baseVariableBorrowRate() external override view returns (uint256) {
function baseVariableBorrowRate() external view override returns (uint256) {
return _baseVariableBorrowRate;
}
function getMaxVariableBorrowRate() external override view returns (uint256) {
function getMaxVariableBorrowRate() external view override returns (uint256) {
return _baseVariableBorrowRate.add(_variableRateSlope1).add(_variableRateSlope2);
}
struct CalcInterestRatesLocalVars {
uint256 totalBorrows;
uint256 totalDebt;
uint256 currentVariableBorrowRate;
uint256 currentStableBorrowRate;
uint256 currentLiquidityRate;
@ -103,16 +105,14 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
}
/**
* @dev calculates the interest rates depending on the available liquidity and the total borrowed.
* @param reserve the address of the reserve
* @param availableLiquidity the liquidity available in the reserve
* @param totalStableDebt the total borrowed from the reserve a stable rate
* @param totalVariableDebt the total borrowed from the reserve at a variable rate
* @param averageStableBorrowRate the weighted average of all the stable rate borrows
* @param reserveFactor the reserve portion of the interest to redirect to the reserve treasury
* @return currentLiquidityRate the liquidity rate
* @return currentStableBorrowRate stable borrow rate
* @return currentVariableBorrowRate variable borrow rate
* @dev Calculates the interest rates depending on the reserve's state and configurations
* @param reserve The address of the reserve
* @param availableLiquidity The liquidity available in the reserve
* @param totalStableDebt The total borrowed from the reserve a stable rate
* @param totalVariableDebt The total borrowed from the reserve at a variable rate
* @param averageStableBorrowRate The weighted average of all the stable rate loans
* @param reserveFactor The reserve portion of the interest that goes to the treasury of the market
* @return The liquidity rate, the stable borrow rate and the variable borrow rate
**/
function calculateInterestRates(
address reserve,
@ -123,8 +123,8 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
uint256 reserveFactor
)
external
override
view
override
returns (
uint256,
uint256,
@ -133,22 +133,22 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
{
CalcInterestRatesLocalVars memory vars;
vars.totalBorrows = totalStableDebt.add(totalVariableDebt);
vars.totalDebt = totalStableDebt.add(totalVariableDebt);
vars.currentVariableBorrowRate = 0;
vars.currentStableBorrowRate = 0;
vars.currentLiquidityRate = 0;
uint256 utilizationRate = vars.totalBorrows == 0
? 0
: vars.totalBorrows.rayDiv(availableLiquidity.add(vars.totalBorrows));
uint256 utilizationRate =
vars.totalDebt == 0
? 0
: vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt));
vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle())
.getMarketBorrowRate(reserve);
if (utilizationRate > OPTIMAL_UTILIZATION_RATE) {
uint256 excessUtilizationRateRatio = utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(
EXCESS_UTILIZATION_RATE
);
uint256 excessUtilizationRateRatio =
utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(EXCESS_UTILIZATION_RATE);
vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(_stableRateSlope1).add(
_stableRateSlope2.rayMul(excessUtilizationRateRatio)
@ -184,12 +184,12 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
}
/**
* @dev calculates the overall borrow rate as the weighted average between the total variable borrows and total stable borrows.
* @param totalStableDebt the total borrowed from the reserve a stable rate
* @param totalVariableDebt the total borrowed from the reserve at a variable rate
* @param currentVariableBorrowRate the current variable borrow rate
* @param currentAverageStableBorrowRate the weighted average of all the stable rate borrows
* @return the weighted averaged borrow rate
* @dev Calculates the overall borrow rate as the weighted average between the total variable debt and total stable debt
* @param totalStableDebt The total borrowed from the reserve a stable rate
* @param totalVariableDebt The total borrowed from the reserve at a variable rate
* @param currentVariableBorrowRate The current variable borrow rate of the reserve
* @param currentAverageStableBorrowRate The current weighted average of all the stable rate loans
* @return The weighted averaged borrow rate
**/
function _getOverallBorrowRate(
uint256 totalStableDebt,
@ -197,17 +197,16 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
uint256 currentVariableBorrowRate,
uint256 currentAverageStableBorrowRate
) internal pure returns (uint256) {
uint256 totalBorrows = totalStableDebt.add(totalVariableDebt);
uint256 totalDebt = totalStableDebt.add(totalVariableDebt);
if (totalBorrows == 0) return 0;
if (totalDebt == 0) return 0;
uint256 weightedVariableRate = totalVariableDebt.wadToRay().rayMul(currentVariableBorrowRate);
uint256 weightedStableRate = totalStableDebt.wadToRay().rayMul(currentAverageStableBorrowRate);
uint256 overallBorrowRate = weightedVariableRate.add(weightedStableRate).rayDiv(
totalBorrows.wadToRay()
);
uint256 overallBorrowRate =
weightedVariableRate.add(weightedStableRate).rayDiv(totalDebt.wadToRay());
return overallBorrowRate;
}

View File

@ -1,11 +1,11 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
import {Helpers} from '../libraries/helpers/Helpers.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
@ -18,18 +18,29 @@ import {ReserveConfiguration} from '../libraries/configuration/ReserveConfigurat
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
import {DebtTokenBase} from '../tokenization/base/DebtTokenBase.sol';
import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol';
import {LendingPoolCollateralManager} from './LendingPoolCollateralManager.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {IFlashLoanReceiver} from '../../flashloan/interfaces/IFlashLoanReceiver.sol';
import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
import {SafeERC20} from '../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {LendingPoolStorage} from './LendingPoolStorage.sol';
import {Address} from '../dependencies/openzeppelin/contracts/Address.sol';
import {Address} from '../../dependencies/openzeppelin/contracts/Address.sol';
import {DataTypes} from '../libraries/types/DataTypes.sol';
/**
* @title LendingPool contract
* @notice Implements the actions of the LendingPool, and exposes accessory methods to fetch the users and reserve data
* @dev Main point of interaction with an Aave protocol's market
* - Users can:
* # Deposit
* # Withdraw
* # Borrow
* # Repay
* # Swap their loans between variable and stable rate
* # Enable/disable their deposits as collateral rebalance stable rate borrow positions
* # Liquidate positions
* # Execute Flash Loans
* - To be covered by a proxy contract, owned by the LendingPoolAddressesProvider of the specific market
* - All admin functions are callable by the LendingPoolConfigurator contract defined also in the
* LendingPoolAddressesProvider
* @author Aave
**/
contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage {
@ -44,25 +55,20 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
uint256 public constant MAX_NUMBER_RESERVES = 128;
uint256 public constant LENDINGPOOL_REVISION = 0x2;
/**
* @dev functions marked by this modifier can only be called when the protocol is not paused
**/
modifier whenNotPaused() {
_whenNotPaused();
_;
}
/**
* @dev functions marked by this modifier can only be called by the LendingPoolConfigurator
**/
modifier onlyLendingPoolConfigurator() {
_onlyLendingPoolConfigurator();
_;
}
/**
* @dev only lending pools configurator can use functions affected by this modifier
**/
function _whenNotPaused() internal view {
require(!_paused, Errors.LP_IS_PAUSED);
}
function _onlyLendingPoolConfigurator() internal view {
require(
_addressesProvider.getLendingPoolConfigurator() == msg.sender,
@ -70,36 +76,31 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
);
}
/**
* @dev Function to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _whenNotPaused() internal view {
require(!_paused, Errors.LP_IS_PAUSED);
}
function getRevision() internal override pure returns (uint256) {
return LENDINGPOOL_REVISION;
}
/**
* @dev this function is invoked by the proxy contract when the LendingPool contract is added to the
* AddressesProvider.
* @param provider the address of the LendingPoolAddressesProvider registry
* @dev Function is invoked by the proxy contract when the LendingPool contract is added to the
* LendingPoolAddressesProvider of the market.
* - Caching the address of the LendingPoolAddressesProvider in order to reduce gas consumption
* on subsequent operations
* @param provider The address of the LendingPoolAddressesProvider
**/
function initialize(ILendingPoolAddressesProvider provider) public initializer {
_addressesProvider = provider;
}
/**
* @dev deposits The underlying asset into the reserve. A corresponding amount of the overlying asset (aTokens)
* is minted.
* @param asset the address of the reserve
* @param amount the amount to be deposited
* @param referralCode integrators are assigned a referral code and can potentially receive rewards.
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User deposits 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to deposit
* @param amount The amount to be deposited
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function deposit(
address asset,
@ -107,7 +108,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
address onBehalfOf,
uint16 referralCode
) external override whenNotPaused {
ReserveLogic.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveData storage reserve = _reserves[asset];
ValidationLogic.validateDeposit(reserve, amount);
@ -123,24 +124,27 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
}
//transfer to the aToken contract
IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);
emit Deposit(asset, msg.sender, onBehalfOf, amount, referralCode);
}
/**
* @dev withdraws the _reserves of user.
* @param asset the address of the reserve
* @param amount the underlying amount to be redeemed
* @param to address that will receive the underlying
* @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to Address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
**/
function withdraw(
address asset,
uint256 amount,
address to
) external override whenNotPaused {
ReserveLogic.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveData storage reserve = _reserves[asset];
address aToken = reserve.aTokenAddress;
@ -148,7 +152,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
uint256 amountToWithdraw = amount;
//if amount is equal to uint(-1), the user wants to redeem everything
if (amount == type(uint256).max) {
amountToWithdraw = userBalance;
}
@ -179,16 +182,19 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev Allows users to borrow a specific amount of the reserve underlying asset, provided that the borrower
* @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already deposited enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* @param asset the address of the reserve
* @param amount the amount to be borrowed
* @param interestRateMode the interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode a referral code for integrators
* @param onBehalfOf address of the user who will receive the debt. Should be the address of the borrower itself
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
* if he has been given credit delegation allowance
**/
function borrow(
address asset,
@ -197,7 +203,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
uint16 referralCode,
address onBehalfOf
) external override whenNotPaused {
ReserveLogic.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveData storage reserve = _reserves[asset];
_executeBorrow(
ExecuteBorrowParams(
@ -214,12 +220,15 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @notice repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
* @dev the target user is defined by onBehalfOf. If there is no repayment on behalf of another account,
* onBehalfOf must be equal to msg.sender.
* @param asset the address of the reserve on which the user borrowed
* @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
* @param onBehalfOf the address for which msg.sender is repaying.
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
**/
function repay(
address asset,
@ -227,11 +236,11 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
uint256 rateMode,
address onBehalfOf
) external override whenNotPaused {
ReserveLogic.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveData storage reserve = _reserves[asset];
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve);
ReserveLogic.InterestRateMode interestRateMode = ReserveLogic.InterestRateMode(rateMode);
DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode);
ValidationLogic.validateRepay(
reserve,
@ -242,8 +251,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
variableDebt
);
//default to max amount
uint256 paybackAmount = interestRateMode == ReserveLogic.InterestRateMode.STABLE
uint256 paybackAmount = interestRateMode == DataTypes.InterestRateMode.STABLE
? stableDebt
: variableDebt;
@ -253,8 +261,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
reserve.updateState();
//burns an equivalent amount of debt tokens
if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) {
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
IStableDebtToken(reserve.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount);
} else {
IVariableDebtToken(reserve.variableDebtTokenAddress).burn(
@ -277,16 +284,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev borrowers can user this function to swap between stable and variable borrow rate modes.
* @param asset the address of the reserve on which the user borrowed
* @param rateMode the rate mode that the user wants to swap
* @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
* @param asset The address of the underlying asset borrowed
* @param rateMode The rate mode that the user wants to swap to
**/
function swapBorrowRateMode(address asset, uint256 rateMode) external override whenNotPaused {
ReserveLogic.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveData storage reserve = _reserves[asset];
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
ReserveLogic.InterestRateMode interestRateMode = ReserveLogic.InterestRateMode(rateMode);
DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode);
ValidationLogic.validateSwapRateMode(
reserve,
@ -298,8 +305,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
reserve.updateState();
if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) {
//burn stable rate tokens, mint variable rate tokens
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt);
IVariableDebtToken(reserve.variableDebtTokenAddress).mint(
msg.sender,
@ -308,7 +314,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
reserve.variableBorrowIndex
);
} else {
//do the opposite
IVariableDebtToken(reserve.variableDebtTokenAddress).burn(
msg.sender,
variableDebt,
@ -328,15 +333,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev rebalances the stable interest rate of a user. Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
* borrowed at a stable rate and depositors are not earning enough.
* @param asset the address of the reserve
* @param user the address of the user to be rebalanced
* @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
* - Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
* borrowed at a stable rate and depositors are not earning enough
* @param asset The address of the underlying asset borrowed
* @param user The address of the user to be rebalanced
**/
function rebalanceStableBorrowRate(address asset, address user) external override whenNotPaused {
ReserveLogic.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveData storage reserve = _reserves[asset];
IERC20 stableDebtToken = IERC20(reserve.stableDebtTokenAddress);
IERC20 variableDebtToken = IERC20(reserve.variableDebtTokenAddress);
@ -368,16 +374,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev allows depositors to enable or disable a specific deposit as collateral.
* @param asset the address of the reserve
* @param useAsCollateral true if the user wants to use the deposit as collateral, false otherwise.
* @dev Allows depositors to enable/disable a specific deposited asset as collateral
* @param asset The address of the underlying asset deposited
* @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
**/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)
external
override
whenNotPaused
{
ReserveLogic.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveData storage reserve = _reserves[asset];
ValidationLogic.validateSetUseReserveAsCollateral(
reserve,
@ -400,19 +406,21 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev users can invoke this function to liquidate an undercollateralized position.
* @param asset the address of the collateral to liquidated
* @param asset the address of the principal reserve
* @param user the address of the borrower
* @param purchaseAmount the amount of principal that the liquidator wants to repay
* @param receiveAToken true if the liquidators wants to receive the aTokens, false if
* he wants to receive the underlying asset directly
* @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
function liquidationCall(
address collateral,
address asset,
address collateralAsset,
address debtAsset,
address user,
uint256 purchaseAmount,
uint256 debtToCover,
bool receiveAToken
) external override whenNotPaused {
address collateralManager = _addressesProvider.getLendingPoolCollateralManager();
@ -421,10 +429,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
(bool success, bytes memory result) = collateralManager.delegatecall(
abi.encodeWithSignature(
'liquidationCall(address,address,address,uint256,bool)',
collateral,
asset,
collateralAsset,
debtAsset,
user,
purchaseAmount,
debtToCover,
receiveAToken
)
);
@ -448,16 +456,21 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned. NOTE There are security concerns for developers of flashloan receiver contracts
* that must be kept into consideration. For further details please visit https://developers.aave.com
* @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 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.
* @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
* For further details please visit https://developers.aave.com
* @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts amounts being flash-borrowed
* @param modes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode Referral code of the flash loan
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function flashLoan(
address receiverAddress,
@ -482,11 +495,9 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
premiums[vars.i] = amounts[vars.i].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000);
//transfer funds to the receiver
IAToken(aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]);
}
//execute action of the receiver
require(
vars.receiver.executeOperation(assets, amounts, premiums, msg.sender, params),
Errors.LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN
@ -499,7 +510,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
vars.currentATokenAddress = aTokenAddresses[vars.i];
vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium);
if (ReserveLogic.InterestRateMode(modes[vars.i]) == ReserveLogic.InterestRateMode.NONE) {
if (DataTypes.InterestRateMode(modes[vars.i]) == DataTypes.InterestRateMode.NONE) {
_reserves[vars.currentAsset].updateState();
_reserves[vars.currentAsset].cumulateToLiquidityIndex(
IERC20(vars.currentATokenAddress).totalSupply(),
@ -518,8 +529,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
vars.currentAmountPlusPremium
);
} else {
//if the user didn't choose to return the funds, the system checks if there
//is enough collateral and eventually open a position
// If the user chose to not return the funds, the system checks if there is enough collateral and
// eventually opens a debt position
_executeBorrow(
ExecuteBorrowParams(
vars.currentAsset,
@ -545,22 +556,22 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev returns the state and configuration of the reserve
* @param asset the address of the reserve
* @return the state of the reserve
* @dev Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state of the reserve
**/
function getReserveData(address asset)
external
override
view
returns (ReserveLogic.ReserveData memory)
override
returns (DataTypes.ReserveData memory)
{
return _reserves[asset];
}
/**
* @dev returns the user account data across all the reserves
* @param user the address of the user
* @dev Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralETH the total collateral in ETH of the user
* @return totalDebtETH the total debt in ETH of the user
* @return availableBorrowsETH the borrowing power left of the user
@ -570,8 +581,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
**/
function getUserAccountData(address user)
external
override
view
override
returns (
uint256 totalCollateralETH,
uint256 totalDebtETH,
@ -604,57 +615,57 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev returns the configuration of the reserve
* @param asset the address of the reserve
* @return the configuration of the reserve
* @dev Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
**/
function getConfiguration(address asset)
external
override
view
returns (ReserveConfiguration.Map memory)
override
returns (DataTypes.ReserveConfigurationMap memory)
{
return _reserves[asset].configuration;
}
/**
* @dev returns the configuration of the user across all the reserves
* @param user the user
* @return the configuration of the user
* @dev Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
**/
function getUserConfiguration(address user)
external
override
view
returns (UserConfiguration.Map memory)
override
returns (DataTypes.UserConfigurationMap memory)
{
return _usersConfig[user];
}
/**
* @dev returns the normalized income per unit of asset
* @param asset the address of the reserve
* @return the reserve normalized income
* @dev Returns the normalized income per unit of asset
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset)
external
view
virtual
override
view
returns (uint256)
{
return _reserves[asset].getNormalizedIncome();
}
/**
* @dev returns the normalized variable debt per unit of asset
* @param asset the address of the reserve
* @return the reserve normalized debt
* @dev Returns the normalized variable debt per unit of asset
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset)
external
override
view
override
returns (uint256)
{
return _reserves[asset].getNormalizedDebt();
@ -663,14 +674,14 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
/**
* @dev Returns if the LendingPool is paused
*/
function paused() external override view returns (bool) {
function paused() external view override returns (bool) {
return _paused;
}
/**
* @dev returns the list of the initialized reserves
* @dev Returns the list of the initialized reserves
**/
function getReservesList() external override view returns (address[] memory) {
function getReservesList() external view override returns (address[] memory) {
address[] memory _activeReserves = new address[](_reservesCount);
for (uint256 i = 0; i < _reservesCount; i++) {
@ -680,20 +691,21 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev returns the addresses provider
* @dev Returns the cached LendingPoolAddressesProvider connected to this contract
**/
function getAddressesProvider() external override view returns (ILendingPoolAddressesProvider) {
function getAddressesProvider() external view override returns (ILendingPoolAddressesProvider) {
return _addressesProvider;
}
/**
* @dev validates and finalizes an aToken transfer
* @param asset the address of the reserve
* @param from the user from which the aTokens are transferred
* @param to the user receiving the aTokens
* @param amount the amount being transferred/redeemed
* @param balanceFromBefore the balance of the from user before the transfer
* @param balanceToBefore the balance of the to user before the transfer
* @dev Validates and finalizes an aToken transfer
* - Only callable by the overlying aToken of the `asset`
* @param asset The address of the underlying asset of the aToken
* @param from The user from which the aTokens are transferred
* @param to The user receiving the aTokens
* @param amount The amount being transferred/withdrawn
* @param balanceFromBefore The aToken balance of the `from` user before the transfer
* @param balanceToBefore The aToken balance of the `to` user before the transfer
*/
function finalizeTransfer(
address asset,
@ -718,13 +730,13 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
if (from != to) {
if (balanceFromBefore.sub(amount) == 0) {
UserConfiguration.Map storage fromConfig = _usersConfig[from];
DataTypes.UserConfigurationMap storage fromConfig = _usersConfig[from];
fromConfig.setUsingAsCollateral(reserveId, false);
emit ReserveUsedAsCollateralDisabled(asset, from);
}
if (balanceToBefore == 0 && amount != 0) {
UserConfiguration.Map storage toConfig = _usersConfig[to];
DataTypes.UserConfigurationMap storage toConfig = _usersConfig[to];
toConfig.setUsingAsCollateral(reserveId, true);
emit ReserveUsedAsCollateralEnabled(asset, to);
}
@ -732,10 +744,14 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev initializes a reserve
* @param asset the address of the reserve
* @param aTokenAddress the address of the overlying aToken contract
* @param interestRateStrategyAddress the address of the interest rate strategy contract
* @dev Initializes a reserve, activating it, assigning an aToken and debt tokens and an
* interest rate strategy
* - Only callable by the LendingPoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param aTokenAddress The address of the aToken that will be assigned to the reserve
* @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve
* @param aTokenAddress The address of the VariableDebtToken that will be assigned to the reserve
* @param interestRateStrategyAddress The address of the interest rate strategy contract
**/
function initReserve(
address asset,
@ -755,9 +771,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev updates the address of the interest rate strategy contract
* @param asset the address of the reserve
* @param rateStrategyAddress the address of the interest rate strategy contract
* @dev Updates the address of the interest rate strategy contract
* - Only callable by the LendingPoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param rateStrategyAddress The address of the interest rate strategy contract
**/
function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress)
external
@ -768,9 +785,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev sets the configuration map of the reserve
* @param asset the address of the reserve
* @param configuration the configuration map
* @dev Sets the configuration bitmap of the reserve as a whole
* - Only callable by the LendingPoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param configuration The new configuration bitmap
**/
function setConfiguration(address asset, uint256 configuration)
external
@ -781,8 +799,9 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
/**
* @dev Set the _pause state
* @param val the boolean value to set the current pause state of LendingPool
* @dev Set the _pause state of a reserve
* - Only callable by the LendingPoolConfigurator contract
* @param val `true` to pause the reserve, `false` to un-pause it
*/
function setPause(bool val) external override onlyLendingPoolConfigurator {
_paused = val;
@ -793,7 +812,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
}
// internal functions
struct ExecuteBorrowParams {
address asset;
address user;
@ -805,19 +823,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
bool releaseUnderlying;
}
/**
* @dev Internal function to execute a borrowing action, allowing to transfer or not the underlying
* @param vars Input struct for the borrowing action, in order to avoid STD errors
**/
function _executeBorrow(ExecuteBorrowParams memory vars) internal {
ReserveLogic.ReserveData storage reserve = _reserves[vars.asset];
UserConfiguration.Map storage userConfig = _usersConfig[vars.onBehalfOf];
DataTypes.ReserveData storage reserve = _reserves[vars.asset];
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[vars.onBehalfOf];
address oracle = _addressesProvider.getPriceOracle();
uint256 amountInETH = IPriceOracleGetter(oracle).getAssetPrice(vars.asset).mul(vars.amount).div(
10**reserve.configuration.getDecimals()
);
uint256 amountInETH =
IPriceOracleGetter(oracle).getAssetPrice(vars.asset).mul(vars.amount).div(
10**reserve.configuration.getDecimals()
);
ValidationLogic.validateBorrow(
vars.asset,
@ -836,12 +851,11 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
reserve.updateState();
//caching the current stable borrow rate
uint256 currentStableRate = 0;
bool isFirstBorrowing = false;
if (
ReserveLogic.InterestRateMode(vars.interestRateMode) == ReserveLogic.InterestRateMode.STABLE
DataTypes.InterestRateMode(vars.interestRateMode) == DataTypes.InterestRateMode.STABLE
) {
currentStableRate = reserve.currentStableBorrowRate;
@ -881,16 +895,13 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
vars.onBehalfOf,
vars.amount,
vars.interestRateMode,
ReserveLogic.InterestRateMode(vars.interestRateMode) == ReserveLogic.InterestRateMode.STABLE
DataTypes.InterestRateMode(vars.interestRateMode) == DataTypes.InterestRateMode.STABLE
? currentStableRate
: reserve.currentVariableBorrowRate,
vars.referralCode
);
}
/**
* @dev adds a reserve to the array of the _reserves address
**/
function _addReserveToList(address asset) internal {
uint256 reservesCount = _reservesCount;

View File

@ -0,0 +1,309 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
import {SafeMath} from '../../dependencies/openzeppelin/contracts//SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts//IERC20.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
import {ILendingPoolCollateralManager} from '../../interfaces/ILendingPoolCollateralManager.sol';
import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
import {Helpers} from '../libraries/helpers/Helpers.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {SafeERC20} from '../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
import {LendingPoolStorage} from './LendingPoolStorage.sol';
import {DataTypes} from '../libraries/types/DataTypes.sol';
/**
* @title LendingPoolCollateralManager contract
* @author Aave
* @dev Implements actions involving management of collateral in the protocol, the main one being the liquidations
* IMPORTANT This contract will run always via DELEGATECALL, through the LendingPool, so the chain of inheritance
* is the same as the LendingPool, to have compatible storage layouts
**/
contract LendingPoolCollateralManager is
ILendingPoolCollateralManager,
VersionedInitializable,
LendingPoolStorage
{
using SafeERC20 for IERC20;
using SafeMath for uint256;
using WadRayMath for uint256;
using PercentageMath for uint256;
uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000;
struct LiquidationCallLocalVars {
uint256 userCollateralBalance;
uint256 userStableDebt;
uint256 userVariableDebt;
uint256 maxLiquidatableDebt;
uint256 actualDebtToLiquidate;
uint256 liquidationRatio;
uint256 maxAmountCollateralToLiquidate;
uint256 userStableRate;
uint256 maxCollateralToLiquidate;
uint256 debtAmountNeeded;
uint256 healthFactor;
IAToken collateralAtoken;
bool isCollateralEnabled;
DataTypes.InterestRateMode borrowRateMode;
uint256 errorCode;
string errorMsg;
}
/**
* @dev As thIS contract extends the VersionedInitializable contract to match the state
* of the LendingPool contract, the getRevision() function is needed, but the value is not
* important, as the initialize() function will never be called here
*/
function getRevision() internal pure override returns (uint256) {
return 0;
}
/**
* @dev Function to liquidate a position if its Health Factor drops below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external override returns (uint256, string memory) {
DataTypes.ReserveData storage collateralReserve = _reserves[collateralAsset];
DataTypes.ReserveData storage debtReserve = _reserves[debtAsset];
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[user];
LiquidationCallLocalVars memory vars;
(, , , , vars.healthFactor) = GenericLogic.calculateUserAccountData(
user,
_reserves,
userConfig,
_reservesList,
_reservesCount,
_addressesProvider.getPriceOracle()
);
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(user, debtReserve);
(vars.errorCode, vars.errorMsg) = ValidationLogic.validateLiquidationCall(
collateralReserve,
debtReserve,
userConfig,
vars.healthFactor,
vars.userStableDebt,
vars.userVariableDebt
);
if (Errors.CollateralManagerErrors(vars.errorCode) != Errors.CollateralManagerErrors.NO_ERROR) {
return (vars.errorCode, vars.errorMsg);
}
vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress);
vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user);
vars.maxLiquidatableDebt = vars.userStableDebt.add(vars.userVariableDebt).percentMul(
LIQUIDATION_CLOSE_FACTOR_PERCENT
);
vars.actualDebtToLiquidate = debtToCover > vars.maxLiquidatableDebt
? vars.maxLiquidatableDebt
: debtToCover;
(
vars.maxCollateralToLiquidate,
vars.debtAmountNeeded
) = _calculateAvailableCollateralToLiquidate(
collateralReserve,
debtReserve,
collateralAsset,
debtAsset,
vars.actualDebtToLiquidate,
vars.userCollateralBalance
);
// If debtAmountNeeded < actualDebtToLiquidate, there isn't enough
// collateral to cover the actual amount that is being liquidated, hence we liquidate
// a smaller amount
if (vars.debtAmountNeeded < vars.actualDebtToLiquidate) {
vars.actualDebtToLiquidate = vars.debtAmountNeeded;
}
// If the liquidator reclaims the underlying asset, we make sure there is enough available liquidity in the
// collateral reserve
if (!receiveAToken) {
uint256 currentAvailableCollateral =
IERC20(collateralAsset).balanceOf(address(vars.collateralAtoken));
if (currentAvailableCollateral < vars.maxCollateralToLiquidate) {
return (
uint256(Errors.CollateralManagerErrors.NOT_ENOUGH_LIQUIDITY),
Errors.LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE
);
}
}
debtReserve.updateState();
if (vars.userVariableDebt >= vars.actualDebtToLiquidate) {
IVariableDebtToken(debtReserve.variableDebtTokenAddress).burn(
user,
vars.actualDebtToLiquidate,
debtReserve.variableBorrowIndex
);
} else {
// If the user doesn't have variable debt, no need to try to burn variable debt tokens
if (vars.userVariableDebt > 0) {
IVariableDebtToken(debtReserve.variableDebtTokenAddress).burn(
user,
vars.userVariableDebt,
debtReserve.variableBorrowIndex
);
}
IStableDebtToken(debtReserve.stableDebtTokenAddress).burn(
user,
vars.actualDebtToLiquidate.sub(vars.userVariableDebt)
);
}
debtReserve.updateInterestRates(
debtAsset,
debtReserve.aTokenAddress,
vars.actualDebtToLiquidate,
0
);
if (receiveAToken) {
vars.collateralAtoken.transferOnLiquidation(user, msg.sender, vars.maxCollateralToLiquidate);
} else {
collateralReserve.updateState();
collateralReserve.updateInterestRates(
collateralAsset,
address(vars.collateralAtoken),
0,
vars.maxCollateralToLiquidate
);
// Burn the equivalent amount of aToken, sending the underlying to the liquidator
vars.collateralAtoken.burn(
user,
msg.sender,
vars.maxCollateralToLiquidate,
collateralReserve.liquidityIndex
);
}
// If the collateral being liquidated is equal to the user balance,
// we set the currency as not being used as collateral anymore
if (vars.maxCollateralToLiquidate == vars.userCollateralBalance) {
userConfig.setUsingAsCollateral(collateralReserve.id, false);
emit ReserveUsedAsCollateralDisabled(collateralAsset, user);
}
// Transfers the debt asset being repaid to the aToken, where the liquidity is kept
IERC20(debtAsset).safeTransferFrom(
msg.sender,
debtReserve.aTokenAddress,
vars.actualDebtToLiquidate
);
emit LiquidationCall(
collateralAsset,
debtAsset,
user,
vars.actualDebtToLiquidate,
vars.maxCollateralToLiquidate,
msg.sender,
receiveAToken
);
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.LPCM_NO_ERRORS);
}
struct AvailableCollateralToLiquidateLocalVars {
uint256 userCompoundedBorrowBalance;
uint256 liquidationBonus;
uint256 collateralPrice;
uint256 debtAssetPrice;
uint256 maxAmountCollateralToLiquidate;
uint256 debtAssetDecimals;
uint256 collateralDecimals;
}
/**
* @dev Calculates how much of a specific collateral can be liquidated, given
* a certain amount of debt asset.
* - This function needs to be called after all the checks to validate the liquidation have been performed,
* otherwise it might fail.
* @param collateralReserve The data of the collateral reserve
* @param debtReserve The data of the debt reserve
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param userCollateralBalance The collateral balance for the specific `collateralAsset` of the user being liquidated
* @return collateralAmount: The maximum amount that is possible to liquidate given all the liquidation constraints
* (user balance, close factor)
* debtAmountNeeded: The amount to repay with the liquidation
**/
function _calculateAvailableCollateralToLiquidate(
DataTypes.ReserveData storage collateralReserve,
DataTypes.ReserveData storage debtReserve,
address collateralAsset,
address debtAsset,
uint256 debtToCover,
uint256 userCollateralBalance
) internal view returns (uint256, uint256) {
uint256 collateralAmount = 0;
uint256 debtAmountNeeded = 0;
IPriceOracleGetter oracle = IPriceOracleGetter(_addressesProvider.getPriceOracle());
AvailableCollateralToLiquidateLocalVars memory vars;
vars.collateralPrice = oracle.getAssetPrice(collateralAsset);
vars.debtAssetPrice = oracle.getAssetPrice(debtAsset);
(, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve
.configuration
.getParams();
vars.debtAssetDecimals = debtReserve.configuration.getDecimals();
// This is the maximum possible amount of the selected collateral that can be liquidated, given the
// max amount of liquidatable debt
vars.maxAmountCollateralToLiquidate = vars
.debtAssetPrice
.mul(debtToCover)
.mul(10**vars.collateralDecimals)
.percentMul(vars.liquidationBonus)
.div(vars.collateralPrice.mul(10**vars.debtAssetDecimals));
if (vars.maxAmountCollateralToLiquidate > userCollateralBalance) {
collateralAmount = userCollateralBalance;
debtAmountNeeded = vars
.collateralPrice
.mul(collateralAmount)
.mul(10**vars.debtAssetDecimals)
.div(vars.debtAssetPrice.mul(10**vars.collateralDecimals))
.percentDiv(vars.liquidationBonus);
} else {
collateralAmount = vars.maxAmountCollateralToLiquidate;
debtAmountNeeded = debtToCover;
}
return (collateralAmount, debtAmountNeeded);
}
}

View File

@ -1,20 +1,20 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol';
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {
InitializableImmutableAdminUpgradeabilityProxy
} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {ITokenConfiguration} from '../tokenization/interfaces/ITokenConfiguration.sol';
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {DataTypes} from '../libraries/types/DataTypes.sol';
/**
* @title LendingPoolConfigurator contract
@ -25,7 +25,7 @@ import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
contract LendingPoolConfigurator is VersionedInitializable {
using SafeMath for uint256;
using ReserveConfiguration for ReserveConfiguration.Map;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
/**
* @dev emitted when a reserve is initialized.
@ -105,14 +105,14 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
**/
event ReserveUnfrozen(address indexed asset);
/**
* @dev emitted when a reserve factor is updated
* @param asset the address of the reserve
* @param factor the new reserve factor
**/
event ReserveFactorChanged(address indexed asset, uint256 factor);
/**
* @dev emitted when the reserve decimals are updated
* @param asset the address of the reserve
@ -187,7 +187,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
uint256 internal constant CONFIGURATOR_REVISION = 0x3;
function getRevision() internal override pure returns (uint256) {
function getRevision() internal pure override returns (uint256) {
return CONFIGURATOR_REVISION;
}
@ -236,15 +236,11 @@ contract LendingPoolConfigurator is VersionedInitializable {
address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals);
address stableDebtTokenProxyAddress = _initTokenWithProxy(
stableDebtTokenImpl,
underlyingAssetDecimals
);
address stableDebtTokenProxyAddress =
_initTokenWithProxy(stableDebtTokenImpl, underlyingAssetDecimals);
address variableDebtTokenProxyAddress = _initTokenWithProxy(
variableDebtTokenImpl,
underlyingAssetDecimals
);
address variableDebtTokenProxyAddress =
_initTokenWithProxy(variableDebtTokenImpl, underlyingAssetDecimals);
pool.initReserve(
asset,
@ -254,7 +250,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
interestRateStrategyAddress
);
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setDecimals(underlyingAssetDecimals);
@ -278,7 +274,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param implementation the address of the new aToken implementation
**/
function updateAToken(address asset, address implementation) external onlyPoolAdmin {
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
_upgradeTokenImplementation(asset, reserveData.aTokenAddress, implementation);
@ -291,7 +287,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param implementation the address of the new aToken implementation
**/
function updateStableDebtToken(address asset, address implementation) external onlyPoolAdmin {
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
_upgradeTokenImplementation(asset, reserveData.stableDebtTokenAddress, implementation);
@ -304,7 +300,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param implementation the address of the new aToken implementation
**/
function updateVariableDebtToken(address asset, address implementation) external onlyPoolAdmin {
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
_upgradeTokenImplementation(asset, reserveData.variableDebtTokenAddress, implementation);
@ -320,7 +316,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
external
onlyPoolAdmin
{
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setBorrowingEnabled(true);
currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled);
@ -335,7 +331,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
**/
function disableBorrowingOnReserve(address asset) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setBorrowingEnabled(false);
@ -358,7 +354,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
uint256 liquidationThreshold,
uint256 liquidationBonus
) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
//validation of the parameters: the LTV can
//only be lower or equal than the liquidation threshold
@ -368,13 +364,16 @@ contract LendingPoolConfigurator is VersionedInitializable {
if (liquidationThreshold != 0) {
//liquidation bonus must be bigger than 100.00%, otherwise the liquidator would receive less
//collateral than needed to cover the debt.
uint256 absoluteBonus = liquidationBonus.sub(PercentageMath.PERCENTAGE_FACTOR, Errors.LPC_INVALID_CONFIGURATION);
uint256 absoluteBonus =
liquidationBonus.sub(PercentageMath.PERCENTAGE_FACTOR, Errors.LPC_INVALID_CONFIGURATION);
require(absoluteBonus > 0, Errors.LPC_INVALID_CONFIGURATION);
//we also need to require that the liq threshold is lower or equal than the liquidation bonus, to ensure that
//there is always enough margin for liquidators to receive the bonus.
require(liquidationThreshold.add(absoluteBonus) <= PercentageMath.PERCENTAGE_FACTOR, Errors.LPC_INVALID_CONFIGURATION);
require(
liquidationThreshold.add(absoluteBonus) <= PercentageMath.PERCENTAGE_FACTOR,
Errors.LPC_INVALID_CONFIGURATION
);
} else {
require(liquidationBonus == 0, Errors.LPC_INVALID_CONFIGURATION);
//if the liquidation threshold is being set to 0,
@ -397,7 +396,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
**/
function enableReserveStableRate(address asset) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setStableRateBorrowingEnabled(true);
@ -411,7 +410,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
**/
function disableReserveStableRate(address asset) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setStableRateBorrowingEnabled(false);
@ -425,7 +424,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
**/
function activateReserve(address asset) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setActive(true);
@ -441,7 +440,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
function deactivateReserve(address asset) external onlyPoolAdmin {
_checkNoLiquidity(asset);
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setActive(false);
@ -455,7 +454,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
**/
function freezeReserve(address asset) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setFrozen(true);
@ -469,7 +468,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
**/
function unfreezeReserve(address asset) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setFrozen(false);
@ -484,7 +483,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param reserveFactor the new reserve factor of the reserve
**/
function setReserveFactor(address asset, uint256 reserveFactor) external onlyPoolAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setReserveFactor(reserveFactor);
@ -512,16 +511,16 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param decimals the decimals of the token
**/
function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) {
InitializableImmutableAdminUpgradeabilityProxy proxy =
new InitializableImmutableAdminUpgradeabilityProxy(address(this));
InitializableImmutableAdminUpgradeabilityProxy proxy
= new InitializableImmutableAdminUpgradeabilityProxy(address(this));
bytes memory params = abi.encodeWithSignature(
'initialize(uint8,string,string)',
decimals,
IERC20Detailed(implementation).name(),
IERC20Detailed(implementation).symbol()
);
bytes memory params =
abi.encodeWithSignature(
'initialize(uint8,string,string)',
decimals,
IERC20Detailed(implementation).name(),
IERC20Detailed(implementation).symbol()
);
proxy.initialize(implementation, params);
@ -533,20 +532,20 @@ contract LendingPoolConfigurator is VersionedInitializable {
address proxyAddress,
address implementation
) internal {
InitializableImmutableAdminUpgradeabilityProxy proxy =
InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress));
InitializableImmutableAdminUpgradeabilityProxy proxy
= InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress));
ReserveConfiguration.Map memory configuration = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(asset);
(, , , uint256 decimals, ) = configuration.getParamsMemory();
bytes memory params = abi.encodeWithSignature(
'initialize(uint8,string,string)',
uint8(decimals),
IERC20Detailed(implementation).name(),
IERC20Detailed(implementation).symbol()
);
bytes memory params =
abi.encodeWithSignature(
'initialize(uint8,string,string)',
uint8(decimals),
IERC20Detailed(implementation).name(),
IERC20Detailed(implementation).symbol()
);
proxy.upgradeToAndCall(implementation, params);
}
@ -560,7 +559,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
}
function _checkNoLiquidity(address asset) internal view {
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
uint256 availableLiquidity = IERC20Detailed(asset).balanceOf(reserveData.aTokenAddress);

View File

@ -1,20 +1,21 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {DataTypes} from '../libraries/types/DataTypes.sol';
contract LendingPoolStorage {
using ReserveLogic for ReserveLogic.ReserveData;
using ReserveConfiguration for ReserveConfiguration.Map;
using UserConfiguration for UserConfiguration.Map;
using ReserveLogic for DataTypes.ReserveData;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
ILendingPoolAddressesProvider internal _addressesProvider;
mapping(address => ReserveLogic.ReserveData) internal _reserves;
mapping(address => UserConfiguration.Map) internal _usersConfig;
mapping(address => DataTypes.ReserveData) internal _reserves;
mapping(address => DataTypes.UserConfigurationMap) internal _usersConfig;
// the list of the available reserves, structured as a mapping for gas savings reasons
mapping(uint256 => address) internal _reservesList;

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import '../../dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol';
import '../../../dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol';
/**
* @title BaseImmutableAdminUpgradeabilityProxy

View File

@ -1,8 +1,8 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import './BaseImmutableAdminUpgradeabilityProxy.sol';
import '../../dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol';
import '../../../dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol';
/**
* @title InitializableAdminUpgradeabilityProxy

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.8;
pragma solidity 0.6.12;
/**
* @title VersionedInitializable
@ -51,7 +51,7 @@ abstract contract VersionedInitializable {
/// @dev returns the revision number of the contract.
/// Needs to be defined in the inherited class as a constant.
function getRevision() internal virtual pure returns (uint256);
function getRevision() internal pure virtual returns (uint256);
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {Errors} from '../helpers/Errors.sol';
import {DataTypes} from '../types/DataTypes.sol';
/**
* @title ReserveConfiguration library
@ -35,26 +36,12 @@ library ReserveConfiguration {
uint256 constant MAX_VALID_DECIMALS = 255;
uint256 constant MAX_VALID_RESERVE_FACTOR = 65535;
struct Map {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: Reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: stable rate borrowing enabled
//bit 60-63: reserved
//bit 64-79: reserve factor
uint256 data;
}
/**
* @dev sets the Loan to Value of the reserve
* @param self the reserve configuration
* @param ltv the new ltv
**/
function setLtv(ReserveConfiguration.Map memory self, uint256 ltv) internal pure {
function setLtv(DataTypes.ReserveConfigurationMap memory self, uint256 ltv) internal pure {
require(ltv <= MAX_VALID_LTV, Errors.RC_INVALID_LTV);
self.data = (self.data & LTV_MASK) | ltv;
@ -65,7 +52,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the loan to value
**/
function getLtv(ReserveConfiguration.Map storage self) internal view returns (uint256) {
function getLtv(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) {
return self.data & ~LTV_MASK;
}
@ -74,7 +61,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param threshold the new liquidation threshold
**/
function setLiquidationThreshold(ReserveConfiguration.Map memory self, uint256 threshold)
function setLiquidationThreshold(DataTypes.ReserveConfigurationMap memory self, uint256 threshold)
internal
pure
{
@ -90,7 +77,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the liquidation threshold
**/
function getLiquidationThreshold(ReserveConfiguration.Map storage self)
function getLiquidationThreshold(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
@ -103,7 +90,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param bonus the new liquidation bonus
**/
function setLiquidationBonus(ReserveConfiguration.Map memory self, uint256 bonus) internal pure {
function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus) internal pure {
require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.RC_INVALID_LIQ_BONUS);
self.data =
@ -116,7 +103,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the liquidation bonus
**/
function getLiquidationBonus(ReserveConfiguration.Map storage self)
function getLiquidationBonus(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
@ -129,7 +116,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param decimals the decimals
**/
function setDecimals(ReserveConfiguration.Map memory self, uint256 decimals) internal pure {
function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals) internal pure {
require(decimals <= MAX_VALID_DECIMALS, Errors.RC_INVALID_DECIMALS);
self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION);
@ -140,7 +127,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the decimals of the asset
**/
function getDecimals(ReserveConfiguration.Map storage self) internal view returns (uint256) {
function getDecimals(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) {
return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION;
}
@ -149,7 +136,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param active the active state
**/
function setActive(ReserveConfiguration.Map memory self, bool active) internal pure {
function setActive(DataTypes.ReserveConfigurationMap memory self, bool active) internal pure {
self.data =
(self.data & ACTIVE_MASK) |
(uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION);
@ -160,7 +147,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the active state
**/
function getActive(ReserveConfiguration.Map storage self) internal view returns (bool) {
function getActive(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) {
return (self.data & ~ACTIVE_MASK) != 0;
}
@ -169,7 +156,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param frozen the frozen state
**/
function setFrozen(ReserveConfiguration.Map memory self, bool frozen) internal pure {
function setFrozen(DataTypes.ReserveConfigurationMap memory self, bool frozen) internal pure {
self.data =
(self.data & FROZEN_MASK) |
(uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION);
@ -180,7 +167,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the frozen state
**/
function getFrozen(ReserveConfiguration.Map storage self) internal view returns (bool) {
function getFrozen(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) {
return (self.data & ~FROZEN_MASK) != 0;
}
@ -189,7 +176,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param enabled true if the borrowing needs to be enabled, false otherwise
**/
function setBorrowingEnabled(ReserveConfiguration.Map memory self, bool enabled) internal pure {
function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) internal pure {
self.data =
(self.data & BORROWING_MASK) |
(uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION);
@ -200,7 +187,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the borrowing state
**/
function getBorrowingEnabled(ReserveConfiguration.Map storage self) internal view returns (bool) {
function getBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) {
return (self.data & ~BORROWING_MASK) != 0;
}
@ -209,7 +196,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param enabled true if the stable rate borrowing needs to be enabled, false otherwise
**/
function setStableRateBorrowingEnabled(ReserveConfiguration.Map memory self, bool enabled)
function setStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled)
internal
pure
{
@ -223,7 +210,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the stable rate borrowing state
**/
function getStableRateBorrowingEnabled(ReserveConfiguration.Map storage self)
function getStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (bool)
@ -236,7 +223,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @param reserveFactor the reserve factor
**/
function setReserveFactor(ReserveConfiguration.Map memory self, uint256 reserveFactor)
function setReserveFactor(DataTypes.ReserveConfigurationMap memory self, uint256 reserveFactor)
internal
pure
{
@ -252,7 +239,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the reserve factor
**/
function getReserveFactor(ReserveConfiguration.Map storage self) internal view returns (uint256) {
function getReserveFactor(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) {
return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION;
}
@ -261,7 +248,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled
**/
function getFlags(ReserveConfiguration.Map storage self)
function getFlags(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (
@ -286,7 +273,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals
**/
function getParams(ReserveConfiguration.Map storage self)
function getParams(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (
@ -313,7 +300,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals
**/
function getParamsMemory(ReserveConfiguration.Map memory self)
function getParamsMemory(DataTypes.ReserveConfigurationMap memory self)
internal
pure
returns (
@ -338,7 +325,7 @@ library ReserveConfiguration {
* @param self the reserve configuration
* @return the state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled
**/
function getFlagsMemory(ReserveConfiguration.Map memory self)
function getFlagsMemory(DataTypes.ReserveConfigurationMap memory self)
internal
pure
returns (

View File

@ -1,18 +1,17 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {Errors} from '../helpers/Errors.sol';
import {DataTypes} from '../types/DataTypes.sol';
/**
* @title UserConfiguration library
* @author Aave
* @notice Implements the bitmap logic to handle the user configuration
*/
library UserConfiguration {
uint256 internal constant BORROWING_MASK = 0x5555555555555555555555555555555555555555555555555555555555555555;
struct Map {
uint256 data;
}
uint256 internal constant BORROWING_MASK =
0x5555555555555555555555555555555555555555555555555555555555555555;
/**
* @dev sets if the user is borrowing the reserve identified by reserveIndex
@ -21,7 +20,7 @@ library UserConfiguration {
* @param borrowing true if the user is borrowing the reserve, false otherwise
**/
function setBorrowing(
UserConfiguration.Map storage self,
DataTypes.UserConfigurationMap storage self,
uint256 reserveIndex,
bool borrowing
) internal {
@ -38,7 +37,7 @@ library UserConfiguration {
* @param _usingAsCollateral true if the user is usin the reserve as collateral, false otherwise
**/
function setUsingAsCollateral(
UserConfiguration.Map storage self,
DataTypes.UserConfigurationMap storage self,
uint256 reserveIndex,
bool _usingAsCollateral
) internal {
@ -54,7 +53,7 @@ library UserConfiguration {
* @param reserveIndex the index of the reserve in the bitmap
* @return true if the user has been using a reserve for borrowing or as collateral, false otherwise
**/
function isUsingAsCollateralOrBorrowing(UserConfiguration.Map memory self, uint256 reserveIndex)
function isUsingAsCollateralOrBorrowing(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex)
internal
pure
returns (bool)
@ -69,7 +68,7 @@ library UserConfiguration {
* @param reserveIndex the index of the reserve in the bitmap
* @return true if the user has been using a reserve for borrowing, false otherwise
**/
function isBorrowing(UserConfiguration.Map memory self, uint256 reserveIndex)
function isBorrowing(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex)
internal
pure
returns (bool)
@ -84,7 +83,7 @@ library UserConfiguration {
* @param reserveIndex the index of the reserve in the bitmap
* @return true if the user has been using a reserve as collateral, false otherwise
**/
function isUsingAsCollateral(UserConfiguration.Map memory self, uint256 reserveIndex)
function isUsingAsCollateral(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex)
internal
pure
returns (bool)
@ -98,7 +97,7 @@ library UserConfiguration {
* @param self the configuration object
* @return true if the user has been borrowing any reserve, false otherwise
**/
function isBorrowingAny(UserConfiguration.Map memory self) internal pure returns (bool) {
function isBorrowingAny(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) {
return self.data & BORROWING_MASK != 0;
}
@ -107,7 +106,7 @@ library UserConfiguration {
* @param self the configuration object
* @return true if the user has been borrowing any reserve, false otherwise
**/
function isEmpty(UserConfiguration.Map memory self) internal pure returns (bool) {
function isEmpty(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) {
return self.data == 0;
}
}

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
* @title Errors library

View File

@ -0,0 +1,40 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {DataTypes} from '../types/DataTypes.sol';
/**
* @title Helpers library
* @author Aave
* @notice Implements calculation helpers.
*/
library Helpers {
/**
* @dev fetches the user current stable and variable debt balances
* @param user the user
* @param reserve the reserve object
* @return the stable and variable debt balance
**/
function getUserCurrentDebt(address user, DataTypes.ReserveData storage reserve)
internal
view
returns (uint256, uint256)
{
return (
IERC20(reserve.stableDebtTokenAddress).balanceOf(user),
IERC20(reserve.variableDebtTokenAddress).balanceOf(user)
);
}
function getUserCurrentDebtMemory(address user, DataTypes.ReserveData memory reserve)
internal
view
returns (uint256, uint256)
{
return (
IERC20(reserve.stableDebtTokenAddress).balanceOf(user),
IERC20(reserve.variableDebtTokenAddress).balanceOf(user)
);
}
}

View File

@ -1,15 +1,16 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {ReserveLogic} from './ReserveLogic.sol';
import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../configuration/UserConfiguration.sol';
import {WadRayMath} from '../math/WadRayMath.sol';
import {PercentageMath} from '../math/PercentageMath.sol';
import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol';
import {DataTypes} from '../types/DataTypes.sol';
/**
* @title GenericLogic library
@ -17,12 +18,12 @@ import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
* @title Implements protocol-level logic to check the status of the user across all the reserves
*/
library GenericLogic {
using ReserveLogic for ReserveLogic.ReserveData;
using ReserveLogic for DataTypes.ReserveData;
using SafeMath for uint256;
using WadRayMath for uint256;
using PercentageMath for uint256;
using ReserveConfiguration for ReserveConfiguration.Map;
using UserConfiguration for UserConfiguration.Map;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1 ether;
@ -55,8 +56,8 @@ library GenericLogic {
address asset,
address user,
uint256 amount,
mapping(address => ReserveLogic.ReserveData) storage reservesData,
UserConfiguration.Map calldata userConfig,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap calldata userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
@ -104,11 +105,12 @@ library GenericLogic {
.sub(vars.amountToDecreaseETH.mul(vars.liquidationThreshold))
.div(vars.collateralBalanceAfterDecrease);
uint256 healthFactorAfterDecrease = calculateHealthFactorFromBalances(
vars.collateralBalanceAfterDecrease,
vars.borrowBalanceETH,
vars.liquidationThresholdAfterDecrease
);
uint256 healthFactorAfterDecrease =
calculateHealthFactorFromBalances(
vars.collateralBalanceAfterDecrease,
vars.borrowBalanceETH,
vars.liquidationThresholdAfterDecrease
);
return healthFactorAfterDecrease >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD;
}
@ -149,8 +151,8 @@ library GenericLogic {
**/
function calculateUserAccountData(
address user,
mapping(address => ReserveLogic.ReserveData) storage reservesData,
UserConfiguration.Map memory userConfig,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap memory userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
@ -176,7 +178,7 @@ library GenericLogic {
}
vars.currentReserveAddress = reserves[vars.i];
ReserveLogic.ReserveData storage currentReserve = reservesData[vars.currentReserveAddress];
DataTypes.ReserveData storage currentReserve = reservesData[vars.currentReserveAddress];
(vars.ltv, vars.liquidationThreshold, , vars.decimals, ) = currentReserve
.configuration
@ -188,10 +190,8 @@ library GenericLogic {
if (vars.liquidationThreshold != 0 && userConfig.isUsingAsCollateral(vars.i)) {
vars.compoundedLiquidityBalance = IERC20(currentReserve.aTokenAddress).balanceOf(user);
uint256 liquidityBalanceETH = vars
.reserveUnitPrice
.mul(vars.compoundedLiquidityBalance)
.div(vars.tokenUnit);
uint256 liquidityBalanceETH =
vars.reserveUnitPrice.mul(vars.compoundedLiquidityBalance).div(vars.tokenUnit);
vars.totalCollateralBalanceETH = vars.totalCollateralBalanceETH.add(liquidityBalanceETH);

View File

@ -1,18 +1,19 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {MathUtils} from '../math/MathUtils.sol';
import {SafeERC20} from '../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {SafeERC20} from '../../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {IAToken} from '../../tokenization/interfaces/IAToken.sol';
import {IStableDebtToken} from '../../tokenization/interfaces/IStableDebtToken.sol';
import {IVariableDebtToken} from '../../tokenization/interfaces/IVariableDebtToken.sol';
import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';
import {IReserveInterestRateStrategy} from '../../interfaces/IReserveInterestRateStrategy.sol';
import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol';
import {WadRayMath} from '../math/WadRayMath.sol';
import {PercentageMath} from '../math/PercentageMath.sol';
import {Errors} from '../helpers/Errors.sol';
import {DataTypes} from '../types/DataTypes.sol';
/**
* @title ReserveLogic library
@ -43,35 +44,8 @@ library ReserveLogic {
uint256 variableBorrowIndex
);
using ReserveLogic for ReserveLogic.ReserveData;
using ReserveConfiguration for ReserveConfiguration.Map;
enum InterestRateMode {NONE, STABLE, VARIABLE}
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
struct ReserveData {
//stores the reserve configuration
ReserveConfiguration.Map configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
//tokens addresses
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the id of the reserve. Represents the position in the list of the active reserves
uint8 id;
}
using ReserveLogic for DataTypes.ReserveData;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
/**
* @dev returns the ongoing normalized income for the reserve.
@ -80,7 +54,11 @@ library ReserveLogic {
* @param reserve the reserve object
* @return the normalized income. expressed in ray
**/
function getNormalizedIncome(ReserveData storage reserve) internal view returns (uint256) {
function getNormalizedIncome(DataTypes.ReserveData storage reserve)
internal
view
returns (uint256)
{
uint40 timestamp = reserve.lastUpdateTimestamp;
//solium-disable-next-line
@ -89,9 +67,10 @@ library ReserveLogic {
return reserve.liquidityIndex;
}
uint256 cumulated = MathUtils
.calculateLinearInterest(reserve.currentLiquidityRate, timestamp)
.rayMul(reserve.liquidityIndex);
uint256 cumulated =
MathUtils.calculateLinearInterest(reserve.currentLiquidityRate, timestamp).rayMul(
reserve.liquidityIndex
);
return cumulated;
}
@ -103,7 +82,11 @@ library ReserveLogic {
* @param reserve the reserve object
* @return the normalized variable debt. expressed in ray
**/
function getNormalizedDebt(ReserveData storage reserve) internal view returns (uint256) {
function getNormalizedDebt(DataTypes.ReserveData storage reserve)
internal
view
returns (uint256)
{
uint40 timestamp = reserve.lastUpdateTimestamp;
//solium-disable-next-line
@ -112,9 +95,10 @@ library ReserveLogic {
return reserve.variableBorrowIndex;
}
uint256 cumulated = MathUtils
.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp)
.rayMul(reserve.variableBorrowIndex);
uint256 cumulated =
MathUtils.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp).rayMul(
reserve.variableBorrowIndex
);
return cumulated;
}
@ -124,20 +108,21 @@ library ReserveLogic {
* a formal specification.
* @param reserve the reserve object
**/
function updateState(ReserveData storage reserve) internal {
uint256 scaledVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress)
.scaledTotalSupply();
function updateState(DataTypes.ReserveData storage reserve) internal {
uint256 scaledVariableDebt =
IVariableDebtToken(reserve.variableDebtTokenAddress).scaledTotalSupply();
uint256 previousVariableBorrowIndex = reserve.variableBorrowIndex;
uint256 previousLiquidityIndex = reserve.liquidityIndex;
uint40 lastUpdatedTimestamp = reserve.lastUpdateTimestamp;
(uint256 newLiquidityIndex, uint256 newVariableBorrowIndex) = _updateIndexes(
reserve,
scaledVariableDebt,
previousLiquidityIndex,
previousVariableBorrowIndex,
lastUpdatedTimestamp
);
(uint256 newLiquidityIndex, uint256 newVariableBorrowIndex) =
_updateIndexes(
reserve,
scaledVariableDebt,
previousLiquidityIndex,
previousVariableBorrowIndex,
lastUpdatedTimestamp
);
_mintToTreasury(
reserve,
@ -157,7 +142,7 @@ library ReserveLogic {
* @param amount the amount to accomulate
**/
function cumulateToLiquidityIndex(
ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
uint256 totalLiquidity,
uint256 amount
) internal {
@ -178,14 +163,14 @@ library ReserveLogic {
* @param interestRateStrategyAddress the address of the interest rate strategy contract
**/
function init(
ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
address aTokenAddress,
address stableDebtTokenAddress,
address variableDebtTokenAddress,
address interestRateStrategyAddress
) external {
require(reserve.aTokenAddress == address(0), Errors.RL_RESERVE_ALREADY_INITIALIZED);
reserve.liquidityIndex = uint128(WadRayMath.ray());
reserve.variableBorrowIndex = uint128(WadRayMath.ray());
reserve.aTokenAddress = aTokenAddress;
@ -213,7 +198,7 @@ library ReserveLogic {
* @param liquidityTaken the amount of liquidity taken from the protocol (redeem or borrow)
**/
function updateInterestRates(
ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
address reserveAddress,
address aTokenAddress,
uint256 liquidityAdded,
@ -289,7 +274,7 @@ library ReserveLogic {
* @param newVariableBorrowIndex the variable borrow index after the last accumulation of the interest
**/
function _mintToTreasury(
ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
uint256 scaledVariableDebt,
uint256 previousVariableBorrowIndex,
uint256 newLiquidityIndex,
@ -349,7 +334,7 @@ library ReserveLogic {
* @param variableBorrowIndex the last stored variable borrow index
**/
function _updateIndexes(
ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
uint256 scaledVariableDebt,
uint256 liquidityIndex,
uint256 variableBorrowIndex,
@ -362,10 +347,8 @@ library ReserveLogic {
//only cumulating if there is any income being produced
if (currentLiquidityRate > 0) {
uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest(
currentLiquidityRate,
timestamp
);
uint256 cumulatedLiquidityInterest =
MathUtils.calculateLinearInterest(currentLiquidityRate, timestamp);
newLiquidityIndex = cumulatedLiquidityInterest.rayMul(liquidityIndex);
require(newLiquidityIndex < type(uint128).max, Errors.RL_LIQUIDITY_INDEX_OVERFLOW);
@ -374,12 +357,13 @@ library ReserveLogic {
//as the liquidity rate might come only from stable rate loans, we need to ensure
//that there is actual variable debt before accumulating
if (scaledVariableDebt != 0) {
uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest(
reserve.currentVariableBorrowRate,
timestamp
);
uint256 cumulatedVariableBorrowInterest =
MathUtils.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp);
newVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(variableBorrowIndex);
require(newVariableBorrowIndex < type(uint128).max, Errors.RL_VARIABLE_BORROW_INDEX_OVERFLOW);
require(
newVariableBorrowIndex < type(uint128).max,
Errors.RL_VARIABLE_BORROW_INDEX_OVERFLOW
);
reserve.variableBorrowIndex = uint128(newVariableBorrowIndex);
}
}

View File

@ -1,19 +1,20 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {ReserveLogic} from './ReserveLogic.sol';
import {GenericLogic} from './GenericLogic.sol';
import {WadRayMath} from '../math/WadRayMath.sol';
import {PercentageMath} from '../math/PercentageMath.sol';
import {SafeERC20} from '../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {SafeERC20} from '../../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../configuration/UserConfiguration.sol';
import {Errors} from '../helpers/Errors.sol';
import {Helpers} from '../helpers/Helpers.sol';
import {IReserveInterestRateStrategy} from '../../interfaces/IReserveInterestRateStrategy.sol';
import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol';
import {DataTypes} from '../types/DataTypes.sol';
/**
* @title ReserveLogic library
@ -21,13 +22,13 @@ import {IReserveInterestRateStrategy} from '../../interfaces/IReserveInterestRat
* @notice Implements functions to validate specific action on the protocol.
*/
library ValidationLogic {
using ReserveLogic for ReserveLogic.ReserveData;
using ReserveLogic for DataTypes.ReserveData;
using SafeMath for uint256;
using WadRayMath for uint256;
using PercentageMath for uint256;
using SafeERC20 for IERC20;
using ReserveConfiguration for ReserveConfiguration.Map;
using UserConfiguration for UserConfiguration.Map;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
uint256 public constant REBALANCE_UP_LIQUIDITY_RATE_THRESHOLD = 4000;
uint256 public constant REBALANCE_UP_USAGE_RATIO_THRESHOLD = 0.95 * 1e27; //usage ratio of 95%
@ -37,7 +38,7 @@ library ValidationLogic {
* @param reserve the reserve state on which the user is depositing
* @param amount the amount to be deposited
*/
function validateDeposit(ReserveLogic.ReserveData storage reserve, uint256 amount) external view {
function validateDeposit(DataTypes.ReserveData storage reserve, uint256 amount) external view {
(bool isActive, bool isFrozen, , ) = reserve.configuration.getFlags();
require(amount != 0, Errors.VL_INVALID_AMOUNT);
@ -60,17 +61,16 @@ library ValidationLogic {
address reserveAddress,
uint256 amount,
uint256 userBalance,
mapping(address => ReserveLogic.ReserveData) storage reservesData,
UserConfiguration.Map storage userConfig,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap storage userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
) external view {
require(amount != 0, Errors.VL_INVALID_AMOUNT);
require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE);
(bool isActive,, , ) = reservesData[reserveAddress].configuration.getFlags();
(bool isActive, , , ) = reservesData[reserveAddress].configuration.getFlags();
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
require(
@ -101,7 +101,7 @@ library ValidationLogic {
uint256 availableLiquidity;
uint256 finalUserBorrowRate;
uint256 healthFactor;
ReserveLogic.InterestRateMode rateMode;
DataTypes.InterestRateMode rateMode;
bool healthFactorBelowThreshold;
bool isActive;
bool isFrozen;
@ -126,14 +126,14 @@ library ValidationLogic {
function validateBorrow(
address asset,
ReserveLogic.ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
address userAddress,
uint256 amount,
uint256 amountInETH,
uint256 interestRateMode,
uint256 maxStableLoanPercent,
mapping(address => ReserveLogic.ReserveData) storage reservesData,
UserConfiguration.Map storage userConfig,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap storage userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
@ -152,8 +152,8 @@ library ValidationLogic {
//validate interest rate mode
require(
uint256(ReserveLogic.InterestRateMode.VARIABLE) == interestRateMode ||
uint256(ReserveLogic.InterestRateMode.STABLE) == interestRateMode,
uint256(DataTypes.InterestRateMode.VARIABLE) == interestRateMode ||
uint256(DataTypes.InterestRateMode.STABLE) == interestRateMode,
Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED
);
@ -198,7 +198,7 @@ library ValidationLogic {
* liquidity
**/
if (vars.rateMode == ReserveLogic.InterestRateMode.STABLE) {
if (vars.rateMode == DataTypes.InterestRateMode.STABLE) {
//check if the borrow mode is stable and if stable rate borrowing is enabled on this reserve
require(vars.stableRateBorrowingEnabled, Errors.VL_STABLE_BORROWING_NOT_ENABLED);
@ -229,9 +229,9 @@ library ValidationLogic {
* @param variableDebt the borrow balance of the user
*/
function validateRepay(
ReserveLogic.ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
uint256 amountSent,
ReserveLogic.InterestRateMode rateMode,
DataTypes.InterestRateMode rateMode,
address onBehalfOf,
uint256 stableDebt,
uint256 variableDebt
@ -244,9 +244,9 @@ library ValidationLogic {
require(
(stableDebt > 0 &&
ReserveLogic.InterestRateMode(rateMode) == ReserveLogic.InterestRateMode.STABLE) ||
DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE) ||
(variableDebt > 0 &&
ReserveLogic.InterestRateMode(rateMode) == ReserveLogic.InterestRateMode.VARIABLE),
DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.VARIABLE),
Errors.VL_NO_DEBT_OF_SELECTED_TYPE
);
@ -265,20 +265,20 @@ library ValidationLogic {
* @param currentRateMode the rate mode of the borrow
*/
function validateSwapRateMode(
ReserveLogic.ReserveData storage reserve,
UserConfiguration.Map storage userConfig,
DataTypes.ReserveData storage reserve,
DataTypes.UserConfigurationMap storage userConfig,
uint256 stableDebt,
uint256 variableDebt,
ReserveLogic.InterestRateMode currentRateMode
DataTypes.InterestRateMode currentRateMode
) external view {
(bool isActive, bool isFrozen, , bool stableRateEnabled) = reserve.configuration.getFlags();
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
require(!isFrozen, Errors.VL_RESERVE_FROZEN);
if (currentRateMode == ReserveLogic.InterestRateMode.STABLE) {
if (currentRateMode == DataTypes.InterestRateMode.STABLE) {
require(stableDebt > 0, Errors.VL_NO_STABLE_RATE_LOAN_IN_RESERVE);
} else if (currentRateMode == ReserveLogic.InterestRateMode.VARIABLE) {
} else if (currentRateMode == DataTypes.InterestRateMode.VARIABLE) {
require(variableDebt > 0, Errors.VL_NO_VARIABLE_RATE_LOAN_IN_RESERVE);
/**
* user wants to swap to stable, before swapping we need to ensure that
@ -309,35 +309,28 @@ library ValidationLogic {
* @param aTokenAddress the address of the aToken contract
*/
function validateRebalanceStableBorrowRate(
ReserveLogic.ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
address reserveAddress,
IERC20 stableDebtToken,
IERC20 variableDebtToken,
address aTokenAddress) external view {
(bool isActive,,, ) = reserve.configuration.getFlags();
address aTokenAddress
) external view {
(bool isActive, , , ) = reserve.configuration.getFlags();
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
//if the usage ratio is below 95%, no rebalances are needed
uint256 totalDebt = stableDebtToken
.totalSupply()
.add(variableDebtToken.totalSupply())
.wadToRay();
uint256 totalDebt =
stableDebtToken.totalSupply().add(variableDebtToken.totalSupply()).wadToRay();
uint256 availableLiquidity = IERC20(reserveAddress).balanceOf(aTokenAddress).wadToRay();
uint256 usageRatio = totalDebt == 0
? 0
: totalDebt.rayDiv(availableLiquidity.add(totalDebt));
uint256 usageRatio = totalDebt == 0 ? 0 : totalDebt.rayDiv(availableLiquidity.add(totalDebt));
//if the liquidity rate is below REBALANCE_UP_THRESHOLD of the max variable APR at 95% usage,
//then we allow rebalancing of the stable rate positions.
uint256 currentLiquidityRate = reserve.currentLiquidityRate;
uint256 maxVariableBorrowRate = IReserveInterestRateStrategy(
reserve
.interestRateStrategyAddress
)
.getMaxVariableBorrowRate();
uint256 maxVariableBorrowRate =
IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).getMaxVariableBorrowRate();
require(
usageRatio >= REBALANCE_UP_USAGE_RATIO_THRESHOLD &&
@ -345,7 +338,6 @@ library ValidationLogic {
maxVariableBorrowRate.percentMul(REBALANCE_UP_LIQUIDITY_RATE_THRESHOLD),
Errors.LP_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET
);
}
/**
@ -358,11 +350,11 @@ library ValidationLogic {
* @param oracle the price oracle
*/
function validateSetUseReserveAsCollateral(
ReserveLogic.ReserveData storage reserve,
DataTypes.ReserveData storage reserve,
address reserveAddress,
bool useAsCollateral,
mapping(address => ReserveLogic.ReserveData) storage reservesData,
UserConfiguration.Map storage userConfig,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap storage userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
@ -373,16 +365,16 @@ library ValidationLogic {
require(
useAsCollateral ||
GenericLogic.balanceDecreaseAllowed(
reserveAddress,
msg.sender,
underlyingBalance,
reservesData,
userConfig,
reserves,
reservesCount,
oracle
),
GenericLogic.balanceDecreaseAllowed(
reserveAddress,
msg.sender,
underlyingBalance,
reservesData,
userConfig,
reserves,
reservesCount,
oracle
),
Errors.VL_DEPOSIT_ALREADY_IN_USE
);
}
@ -406,9 +398,9 @@ library ValidationLogic {
* @param userVariableDebt Total variable debt balance of the user
**/
function validateLiquidationCall(
ReserveLogic.ReserveData storage collateralReserve,
ReserveLogic.ReserveData storage principalReserve,
UserConfiguration.Map storage userConfig,
DataTypes.ReserveData storage collateralReserve,
DataTypes.ReserveData storage principalReserve,
DataTypes.UserConfigurationMap storage userConfig,
uint256 userHealthFactor,
uint256 userStableDebt,
uint256 userVariableDebt
@ -429,8 +421,9 @@ library ValidationLogic {
);
}
bool isCollateralEnabled = collateralReserve.configuration.getLiquidationThreshold() > 0 &&
userConfig.isUsingAsCollateral(collateralReserve.id);
bool isCollateralEnabled =
collateralReserve.configuration.getLiquidationThreshold() > 0 &&
userConfig.isUsingAsCollateral(collateralReserve.id);
//if collateral isn't enabled as collateral by user, it cannot be liquidated
if (!isCollateralEnabled) {
@ -460,20 +453,21 @@ library ValidationLogic {
*/
function validateTransfer(
address from,
mapping(address => ReserveLogic.ReserveData) storage reservesData,
UserConfiguration.Map storage userConfig,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap storage userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
) internal view {
(, , , , uint256 healthFactor) = GenericLogic.calculateUserAccountData(
from,
reservesData,
userConfig,
reserves,
reservesCount,
oracle
);
(, , , , uint256 healthFactor) =
GenericLogic.calculateUserAccountData(
from,
reservesData,
userConfig,
reserves,
reservesCount,
oracle
);
require(
healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {WadRayMath} from './WadRayMath.sol';
library MathUtils {

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {Errors} from '../helpers/Errors.sol';

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {Errors} from '../helpers/Errors.sol';

View File

@ -0,0 +1,49 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
library DataTypes {
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
//tokens addresses
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the id of the reserve. Represents the position in the list of the active reserves
uint8 id;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: Reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: stable rate borrowing enabled
//bit 60-63: reserved
//bit 64-79: reserve factor
uint256 data;
}
struct UserConfigurationMap {
uint256 data;
}
enum InterestRateMode {NONE, STABLE, VARIABLE}
}

View File

@ -1,14 +1,14 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {IncentivizedERC20} from './IncentivizedERC20.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {IAToken} from './interfaces/IAToken.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeERC20} from '../../dependencies/openzeppelin/contracts/SafeERC20.sol';
/**
* @title Aave ERC20 AToken
@ -21,12 +21,10 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
using SafeERC20 for IERC20;
bytes public constant EIP712_REVISION = bytes('1');
bytes32 internal constant EIP712_DOMAIN = keccak256(
'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'
);
bytes32 public constant PERMIT_TYPEHASH = keccak256(
'Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant EIP712_DOMAIN =
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
bytes32 public constant PERMIT_TYPEHASH =
keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');
uint256 public constant UINT_MAX_VALUE = uint256(-1);
uint256 public constant ATOKEN_REVISION = 0x1;
@ -57,7 +55,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
RESERVE_TREASURY_ADDRESS = reserveTreasuryAddress;
}
function getRevision() internal virtual override pure returns (uint256) {
function getRevision() internal pure virtual override returns (uint256) {
return ATOKEN_REVISION;
}
@ -187,8 +185,8 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
**/
function balanceOf(address user)
public
override(IncentivizedERC20, IERC20)
view
override(IncentivizedERC20, IERC20)
returns (uint256)
{
return super.balanceOf(user).rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS));
@ -200,7 +198,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
* @param user the address of the user
* @return the scaled balance of the user
**/
function scaledBalanceOf(address user) external override view returns (uint256) {
function scaledBalanceOf(address user) external view override returns (uint256) {
return super.balanceOf(user);
}
@ -212,8 +210,8 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
**/
function getScaledUserBalanceAndSupply(address user)
external
override
view
override
returns (uint256, uint256)
{
return (super.balanceOf(user), super.totalSupply());
@ -225,7 +223,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
* does that too.
* @return the current total supply
**/
function totalSupply() public override(IncentivizedERC20, IERC20) view returns (uint256) {
function totalSupply() public view override(IncentivizedERC20, IERC20) returns (uint256) {
uint256 currentSupplyScaled = super.totalSupply();
if (currentSupplyScaled == 0) {
@ -236,10 +234,10 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
}
/**
* @dev Returns the scaled total supply of the variable debt token. Represents sum(borrows/index)
* @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)
* @return the scaled total supply
**/
function scaledTotalSupply() public virtual override view returns (uint256) {
function scaledTotalSupply() public view virtual override returns (uint256) {
return super.totalSupply();
}
@ -283,13 +281,14 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
//solium-disable-next-line
require(block.timestamp <= deadline, 'INVALID_EXPIRATION');
uint256 currentValidNonce = _nonces[owner];
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline))
)
);
bytes32 digest =
keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline))
)
);
require(owner == ecrecover(digest, v, r, s), 'INVALID_SIGNATURE');
_nonces[owner] = currentValidNonce.add(1);
_approve(owner, spender, value);

View File

@ -1,8 +1,8 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {AToken} from './AToken.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
/**

View File

@ -1,11 +1,11 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.8;
pragma solidity 0.6.12;
import {Context} from '../dependencies/openzeppelin/contracts/Context.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol';
import {Context} from '../../dependencies/openzeppelin/contracts/Context.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
/**
* @title ERC20
@ -40,35 +40,35 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
/**
* @return the name of the token
**/
function name() public override view returns (string memory) {
function name() public view override returns (string memory) {
return _name;
}
/**
* @return the symbol of the token
**/
function symbol() public override view returns (string memory) {
function symbol() public view override returns (string memory) {
return _symbol;
}
/**
* @return the decimals of the token
**/
function decimals() public override view returns (uint8) {
function decimals() public view override returns (uint8) {
return _decimals;
}
/**
* @return the total supply of the token
**/
function totalSupply() public virtual override view returns (uint256) {
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @return the balance of the token
**/
function balanceOf(address account) public virtual override view returns (uint256) {
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
@ -92,9 +92,9 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
**/
function allowance(address owner, address spender)
public
view
virtual
override
view
returns (uint256)
{
return _allowances[owner][spender];

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {DebtTokenBase} from './base/DebtTokenBase.sol';
import {MathUtils} from '../libraries/math/MathUtils.sol';
@ -34,7 +34,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @dev gets the revision of the stable debt token implementation
* @return the debt token implementation revision
**/
function getRevision() internal virtual override pure returns (uint256) {
function getRevision() internal pure virtual override returns (uint256) {
return DEBT_TOKEN_REVISION;
}
@ -42,7 +42,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @dev returns the average stable rate across all the stable rate debt
* @return the average stable rate
**/
function getAverageStableRate() external virtual override view returns (uint256) {
function getAverageStableRate() external view virtual override returns (uint256) {
return _avgStableRate;
}
@ -50,7 +50,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @dev returns the timestamp of the last user action
* @return the last update timestamp
**/
function getUserLastUpdated(address user) external virtual override view returns (uint40) {
function getUserLastUpdated(address user) external view virtual override returns (uint40) {
return _timestamps[user];
}
@ -59,7 +59,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @param user the address of the user
* @return the stable rate of user
**/
function getUserStableRate(address user) external virtual override view returns (uint256) {
function getUserStableRate(address user) external view virtual override returns (uint256) {
return _usersStableRate[user];
}
@ -67,16 +67,14 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @dev calculates the current user debt balance
* @return the accumulated debt of the user
**/
function balanceOf(address account) public virtual override view returns (uint256) {
function balanceOf(address account) public view virtual override returns (uint256) {
uint256 accountBalance = super.balanceOf(account);
uint256 stableRate = _usersStableRate[account];
if (accountBalance == 0) {
return 0;
}
uint256 cumulatedInterest = MathUtils.calculateCompoundedInterest(
stableRate,
_timestamps[account]
);
uint256 cumulatedInterest =
MathUtils.calculateCompoundedInterest(stableRate, _timestamps[account]);
return accountBalance.rayMul(cumulatedInterest);
}
@ -248,8 +246,8 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
**/
function getSupplyData()
public
override
view
override
returns (
uint256,
uint256,
@ -264,7 +262,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
/**
* @dev returns the the total supply and the average stable rate
**/
function getTotalSupplyAndAvgRate() public override view returns (uint256, uint256) {
function getTotalSupplyAndAvgRate() public view override returns (uint256, uint256) {
uint256 avgRate = _avgStableRate;
return (_calcTotalSupply(avgRate), avgRate);
}
@ -272,14 +270,14 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
/**
* @dev returns the total supply
**/
function totalSupply() public override view returns (uint256) {
function totalSupply() public view override returns (uint256) {
return _calcTotalSupply(_avgStableRate);
}
/**
* @dev returns the timestamp at which the total supply was updated
**/
function getTotalSupplyLastUpdated() public override view returns (uint40) {
function getTotalSupplyLastUpdated() public view override returns (uint40) {
return _totalSupplyTimestamp;
}
@ -288,7 +286,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @param user the user
* @return The debt balance of the user since the last burn/mint action
**/
function principalBalanceOf(address user) external virtual override view returns (uint256) {
function principalBalanceOf(address user) external view virtual override returns (uint256) {
return super.balanceOf(user);
}
@ -297,17 +295,15 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
* @param avgRate the average rate at which calculate the total supply
* @return The debt balance of the user since the last burn/mint action
**/
function _calcTotalSupply(uint256 avgRate) internal virtual view returns (uint256) {
function _calcTotalSupply(uint256 avgRate) internal view virtual returns (uint256) {
uint256 principalSupply = super.totalSupply();
if (principalSupply == 0) {
return 0;
}
uint256 cumulatedInterest = MathUtils.calculateCompoundedInterest(
avgRate,
_totalSupplyTimestamp
);
uint256 cumulatedInterest =
MathUtils.calculateCompoundedInterest(avgRate, _totalSupplyTimestamp);
return principalSupply.rayMul(cumulatedInterest);
}

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {DebtTokenBase} from './base/DebtTokenBase.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
@ -28,7 +28,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
* @dev gets the revision of the stable debt token implementation
* @return the debt token implementation revision
**/
function getRevision() internal virtual override pure returns (uint256) {
function getRevision() internal pure virtual override returns (uint256) {
return DEBT_TOKEN_REVISION;
}
@ -36,7 +36,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
* @dev calculates the accumulated debt balance of the user
* @return the debt balance of the user
**/
function balanceOf(address user) public virtual override view returns (uint256) {
function balanceOf(address user) public view virtual override returns (uint256) {
uint256 scaledBalance = super.balanceOf(user);
if (scaledBalance == 0) {
@ -98,7 +98,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
* @dev Returns the principal debt balance of the user from
* @return The debt balance of the user since the last burn/mint action
**/
function scaledBalanceOf(address user) public virtual override view returns (uint256) {
function scaledBalanceOf(address user) public view virtual override returns (uint256) {
return super.balanceOf(user);
}
@ -106,16 +106,16 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
* @dev Returns the total supply of the variable debt token. Represents the total debt accrued by the users
* @return the total supply
**/
function totalSupply() public virtual override view returns (uint256) {
function totalSupply() public view virtual override returns (uint256) {
return
super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
}
/**
* @dev Returns the scaled total supply of the variable debt token. Represents sum(borrows/index)
* @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)
* @return the scaled total supply
**/
function scaledTotalSupply() public virtual override view returns (uint256) {
function scaledTotalSupply() public view virtual override returns (uint256) {
return super.totalSupply();
}
@ -127,8 +127,8 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
**/
function getScaledUserBalanceAndSupply(address user)
external
override
view
override
returns (uint256, uint256)
{
return (super.balanceOf(user), super.totalSupply());

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {ILendingPool} from '../../../interfaces/ILendingPool.sol';
import {
VersionedInitializable
} from '../../libraries/aave-upgradeability/VersionedInitializable.sol';
@ -100,9 +100,9 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
function allowance(address owner, address spender)
public
view
virtual
override
view
returns (uint256)
{
owner;
@ -154,10 +154,8 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
address delegatee,
uint256 amount
) internal {
uint256 newAllowance = _borrowAllowances[delegator][delegatee].sub(
amount,
Errors.BORROW_ALLOWANCE_NOT_ENOUGH
);
uint256 newAllowance =
_borrowAllowances[delegator][delegatee].sub(amount, Errors.BORROW_ALLOWANCE_NOT_ENOUGH);
_borrowAllowances[delegator][delegatee] = newAllowance;

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
interface IAToken is IERC20, IScaledBalanceToken {

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
interface IScaledBalanceToken {
/**
@ -19,7 +19,7 @@ interface IScaledBalanceToken {
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @dev Returns the scaled total supply of the variable debt token. Represents sum(borrows/index)
* @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)
* @return the scaled total supply
**/
function scaledTotalSupply() external view returns (uint256);

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
/**
* @title interface IStableDebtToken

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6;
/**

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma solidity 0.6.12;
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';

View File

@ -4,4 +4,6 @@ services:
build:
context: ./
dockerfile: ./Dockerfile_test
command: npm run test
environment:
- MNEMONIC
- ALCHEMY_KEY

View File

@ -71,7 +71,7 @@ const mainnetFork = MAINNET_FORK
const buidlerConfig: HardhatUserConfig = {
solidity: {
version: '0.6.8',
version: '0.6.12',
settings: {
optimizer: {enabled: true, runs: 200},
evmVersion: 'istanbul',

View File

@ -16,7 +16,6 @@ export const MAX_UINT_AMOUNT =
export const ONE_YEAR = '31536000';
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
export const ONE_ADDRESS = '0x0000000000000000000000000000000000000001';
// ----------------
// PROTOCOL GLOBAL PARAMS
// ----------------

View File

@ -165,8 +165,8 @@ export const deployAaveLibraries = async (
// libPath example: contracts/libraries/logic/GenericLogic.sol
// libName example: GenericLogic
return {
['__$5201a97c05ba6aa659e2f36a933dd51801$__']: validationLogic.address,
['__$d3b4366daeb9cadc7528af6145b50b2183$__']: reserveLogic.address,
['__$de8c0cf1a7d7c36c802af9a64fb9d86036$__']: validationLogic.address,
['__$22cd43a9dda9ce44e9b92ba393b88fb9ac$__']: reserveLogic.address,
};
};
@ -247,14 +247,11 @@ export const deployMockFlashLoanReceiver = async (
verify
);
export const deployWalletBalancerProvider = async (
addressesProvider: tEthereumAddress,
verify?: boolean
) =>
export const deployWalletBalancerProvider = async (verify?: boolean) =>
withSaveAndVerify(
await new WalletBalanceProviderFactory(await getFirstSigner()).deploy(addressesProvider),
await new WalletBalanceProviderFactory(await getFirstSigner()).deploy(),
eContractid.WalletBalanceProvider,
[addressesProvider],
[],
verify
);
@ -291,7 +288,7 @@ export const deployMintableDelegationERC20 = async (
verify
);
export const deployDefaultReserveInterestRateStrategy = async (
args: [tEthereumAddress, string, string, string, string, string],
args: [tEthereumAddress, string, string, string, string, string, string],
verify: boolean
) =>
withSaveAndVerify(
@ -369,7 +366,7 @@ export const deployDelegationAwareAToken = async (
] = [poolAddress, underlyingAssetAddress, ZERO_ADDRESS, name, symbol, incentivesController];
return withSaveAndVerify(
await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(...args),
eContractid.AToken,
eContractid.DelegationAwareAToken,
args,
verify
);

View File

@ -1,4 +1,4 @@
import { iMultiPoolsAssets, IReserveParams, tEthereumAddress } from './types';
import { eContractid, iMultiPoolsAssets, IReserveParams, tEthereumAddress } from './types';
import { AaveProtocolDataProvider } from '../types/AaveProtocolDataProvider';
import { chunk, waitForTx } from './misc-utils';
import {
@ -8,17 +8,38 @@ import {
} from './contracts-getters';
import { rawInsertContractAddressInDb } from './contracts-helpers';
import { BigNumberish } from 'ethers';
import {
deployDefaultReserveInterestRateStrategy,
deployDelegationAwareAToken,
deployGenericAToken,
deployStableDebtToken,
deployVariableDebtToken,
} from './contracts-deployments';
import { ZERO_ADDRESS } from './constants';
const chooseATokenDeployment = (id: eContractid) => {
switch (id) {
case eContractid.AToken:
return deployGenericAToken;
case eContractid.DelegationAwareAToken:
return deployDelegationAwareAToken;
default:
throw Error(`Missing aToken deployment script for: ${id}`);
}
};
export const initReservesByHelper = async (
reservesParams: iMultiPoolsAssets<IReserveParams>,
tokenAddresses: { [symbol: string]: tEthereumAddress },
admin: tEthereumAddress,
incentivesController: tEthereumAddress
incentivesController: tEthereumAddress,
verify: boolean
) => {
const stableAndVariableDeployer = await getStableAndVariableTokensHelper();
const atokenAndRatesDeployer = await getATokensAndRatesHelper();
const addressProvider = await getLendingPoolAddressesProvider();
const poolAddress = await addressProvider.getLendingPool();
// Set aTokenAndRatesDeployer as temporal admin
await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
@ -27,9 +48,11 @@ export const initReservesByHelper = async (
const tokensChunks = 4;
const initChunks = 6;
// Deploy tokens and rates in chunks
// Deploy tokens and rates that uses common aToken in chunks
const reservesChunks = chunk(
Object.entries(reservesParams) as [string, IReserveParams][],
Object.entries(reservesParams).filter(
([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken
) as [string, IReserveParams][],
tokensChunks
);
// Initialize variables for future reserves initialization
@ -39,6 +62,7 @@ export const initReservesByHelper = async (
let deployedRates: string[] = [];
let reserveTokens: string[] = [];
let reserveInitDecimals: string[] = [];
let reserveSymbols: string[] = [];
console.log(
`- Token deployments in ${reservesChunks.length * 2} txs instead of ${
@ -54,6 +78,7 @@ export const initReservesByHelper = async (
BigNumberish,
BigNumberish,
BigNumberish,
BigNumberish,
BigNumberish
][] = [];
const reservesDecimals: string[] = [];
@ -72,6 +97,7 @@ export const initReservesByHelper = async (
const [
,
{
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
@ -83,6 +109,7 @@ export const initReservesByHelper = async (
tokens.push(tokenAddress);
symbols.push(assetSymbol);
strategyRates.push([
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
@ -126,6 +153,75 @@ export const initReservesByHelper = async (
deployedRates = [...deployedRates, ...strategies];
reserveInitDecimals = [...reserveInitDecimals, ...reservesDecimals];
reserveTokens = [...reserveTokens, ...tokens];
reserveSymbols = [...reserveSymbols, ...symbols];
}
// Deploy delegated aware reserves tokens
const delegatedAwareReserves = Object.entries(reservesParams).filter(
([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken
) as [string, IReserveParams][];
for (let [symbol, params] of delegatedAwareReserves) {
console.log(` - Deploy ${symbol} delegation await aToken, debts tokens, and strategy`);
const {
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
} = params;
const deployCustomAToken = chooseATokenDeployment(params.aTokenImpl);
const aToken = await deployCustomAToken(
[
poolAddress,
tokenAddresses[symbol],
`Aave interest bearing ${symbol}`,
`a${symbol}`,
ZERO_ADDRESS,
],
verify
);
const stableDebt = await deployStableDebtToken(
[
poolAddress,
tokenAddresses[symbol],
`Aave stable debt bearing ${symbol}`,
`stableDebt${symbol}`,
ZERO_ADDRESS,
],
verify
);
const variableDebt = await deployVariableDebtToken(
[
poolAddress,
tokenAddresses[symbol],
`Aave variable debt bearing ${symbol}`,
`variableDebt${symbol}`,
ZERO_ADDRESS,
],
verify
);
const rates = await deployDefaultReserveInterestRateStrategy(
[
tokenAddresses[symbol],
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
],
verify
);
deployedStableTokens.push(stableDebt.address);
deployedVariableTokens.push(variableDebt.address);
deployedATokens.push(aToken.address);
deployedRates.push(rates.address);
reserveInitDecimals.push(params.reserveDecimals);
reserveTokens.push(tokenAddresses[symbol]);
reserveSymbols.push(symbol);
}
// Deploy init reserves per chunks
@ -134,7 +230,7 @@ export const initReservesByHelper = async (
const chunkedAtokens = chunk(deployedATokens, initChunks);
const chunkedRates = chunk(deployedRates, initChunks);
const chunkedDecimals = chunk(reserveInitDecimals, initChunks);
const chunkedSymbols = chunk(Object.keys(tokenAddresses), initChunks);
const chunkedSymbols = chunk(reserveSymbols, initChunks);
console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`);
for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) {

View File

@ -263,9 +263,12 @@ export enum TokenContractId {
ENJ = 'ENJ',
}
export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams {}
export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams {
aTokenImpl: eContractid;
}
export interface IReserveBorrowParams {
optimalUtilizationRate: string;
baseVariableBorrowRate: string;
variableRateSlope1: string;
variableRateSlope2: string;
@ -324,12 +327,8 @@ export enum EthereumNetwork {
}
export interface IProtocolGlobalConfig {
OptimalUtilizationRate: BigNumber;
ExcessUtilizationRate: BigNumber;
ApprovalAmountLendingPoolCore: string;
TokenDistributorPercentageBase: string;
MockUsdPriceInWei: string;
EthereumAddress: tEthereumAddress;
UsdAddress: tEthereumAddress;
NilAddress: tEthereumAddress;
OneAddress: tEthereumAddress;

View File

@ -33,12 +33,8 @@ export const CommonsConfig: ICommonConfiguration = {
ConfigName: 'Commons',
ProviderId: 0,
ProtocolGlobalParams: {
OptimalUtilizationRate: new BigNumber(0.8).times(RAY),
ExcessUtilizationRate: new BigNumber(0.2).times(RAY),
ApprovalAmountLendingPoolCore: '1000000000000000000000000000',
TokenDistributorPercentageBase: '10000',
MockUsdPriceInWei: '5848466240000000',
EthereumAddress: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
UsdAddress: '0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96',
NilAddress: '0x0000000000000000000000000000000000000000',
OneAddress: '0x0000000000000000000000000000000000000001',

Some files were not shown because too many files have changed in this diff Show More