mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'master' into feat/uniswap-adapter-flashloan
# Conflicts: # helpers/contracts-helpers.ts # test/__setup.spec.ts # test/helpers/make-suite.ts
This commit is contained in:
commit
723e3f82a6
|
@ -11,7 +11,7 @@ usePlugin('buidler-typechain');
|
|||
usePlugin('solidity-coverage');
|
||||
usePlugin('@nomiclabs/buidler-waffle');
|
||||
usePlugin('@nomiclabs/buidler-etherscan');
|
||||
//usePlugin('buidler-gas-reporter');
|
||||
usePlugin('buidler-gas-reporter');
|
||||
|
||||
const SKIP_LOAD = process.env.SKIP_LOAD === 'true';
|
||||
const DEFAULT_BLOCK_GAS_LIMIT = 10000000;
|
||||
|
|
|
@ -36,13 +36,15 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
|
|||
* @return the list of addressesProviders
|
||||
**/
|
||||
function getAddressesProvidersList() external override view returns (address[] memory) {
|
||||
uint256 maxLength = _addressesProvidersList.length;
|
||||
address[] memory addressesProvidersList = _addressesProvidersList;
|
||||
|
||||
uint256 maxLength = addressesProvidersList.length;
|
||||
|
||||
address[] memory activeProviders = new address[](maxLength);
|
||||
|
||||
for (uint256 i = 0; i < _addressesProvidersList.length; i++) {
|
||||
if (_addressesProviders[_addressesProvidersList[i]] > 0) {
|
||||
activeProviders[i] = _addressesProvidersList[i];
|
||||
for (uint256 i = 0; i < maxLength; i++) {
|
||||
if (_addressesProviders[addressesProvidersList[i]] > 0) {
|
||||
activeProviders[i] = addressesProvidersList[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +56,8 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
|
|||
* @param provider the pool address to be registered
|
||||
**/
|
||||
function registerAddressesProvider(address provider, uint256 id) external override onlyOwner {
|
||||
require(id != 0, Errors.INVALID_ADDRESSES_PROVIDER_ID);
|
||||
|
||||
_addressesProviders[provider] = id;
|
||||
_addToAddressesProvidersList(provider);
|
||||
emit AddressesProviderRegistered(provider);
|
||||
|
@ -74,7 +78,9 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
|
|||
* @param provider the pool address to be added
|
||||
**/
|
||||
function _addToAddressesProvidersList(address provider) internal {
|
||||
for (uint256 i = 0; i < _addressesProvidersList.length; i++) {
|
||||
uint256 providersCount = _addressesProvidersList.length;
|
||||
|
||||
for (uint256 i = 0; i < providersCount; i++) {
|
||||
if (_addressesProvidersList[i] == provider) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ pragma solidity ^0.6.8;
|
|||
**/
|
||||
interface IFlashLoanReceiver {
|
||||
function executeOperation(
|
||||
address reserve,
|
||||
uint256 amount,
|
||||
uint256 fee,
|
||||
address[] calldata assets,
|
||||
uint256[] calldata amounts,
|
||||
uint256[] calldata premiums,
|
||||
bytes calldata params
|
||||
) external returns (bool);
|
||||
}
|
||||
|
|
|
@ -99,27 +99,35 @@ interface ILendingPool {
|
|||
/**
|
||||
* @dev emitted when a flashloan is executed
|
||||
* @param target the address of the flashLoanReceiver
|
||||
* @param reserve the address of the reserve
|
||||
* @param amount the amount requested
|
||||
* @param totalPremium the total fee on the amount
|
||||
* @param assets the address of the assets being flashborrowed
|
||||
* @param amounts the amount requested
|
||||
* @param premiums the total fee on the amount
|
||||
* @param referralCode the referral code of the caller
|
||||
**/
|
||||
event FlashLoan(
|
||||
address indexed target,
|
||||
address indexed reserve,
|
||||
uint256 amount,
|
||||
uint256 totalPremium,
|
||||
uint256 mode,
|
||||
address[] assets,
|
||||
uint256[] amounts,
|
||||
uint256[] premiums,
|
||||
uint16 referralCode
|
||||
);
|
||||
/**
|
||||
* @dev these events are not emitted directly by the LendingPool
|
||||
* but they are declared here as the LendingPoolCollateralManager
|
||||
* is executed using a delegateCall().
|
||||
* This allows to have the events in the generated ABI for LendingPool.
|
||||
**/
|
||||
|
||||
/**
|
||||
* @dev emitted when a borrower is liquidated
|
||||
* @dev Emitted when the pause is triggered.
|
||||
*/
|
||||
event Paused();
|
||||
|
||||
/**
|
||||
* @dev Emitted when the pause is lifted.
|
||||
*/
|
||||
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().
|
||||
* 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
|
||||
|
@ -137,15 +145,28 @@ interface ILendingPool {
|
|||
address liquidator,
|
||||
bool receiveAToken
|
||||
);
|
||||
/**
|
||||
* @dev Emitted when the pause is triggered.
|
||||
*/
|
||||
event Paused();
|
||||
|
||||
/**
|
||||
* @dev Emitted when the pause is lifted.
|
||||
*/
|
||||
event Unpaused();
|
||||
* @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared
|
||||
* 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
|
||||
**/
|
||||
event ReserveDataUpdated(
|
||||
address indexed reserve,
|
||||
uint256 liquidityRate,
|
||||
uint256 stableBorrowRate,
|
||||
uint256 averageStableBorrowRate,
|
||||
uint256 variableBorrowRate,
|
||||
uint256 liquidityIndex,
|
||||
uint256 variableBorrowIndex
|
||||
);
|
||||
|
||||
/**
|
||||
* @dev deposits The underlying asset into the reserve. A corresponding amount of the overlying asset (aTokens)
|
||||
|
@ -264,16 +285,17 @@ interface ILendingPool {
|
|||
* 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 reserve the address of the principal reserve
|
||||
* @param amount the amount requested for this flashloan
|
||||
* @param assets the address of the principal reserve
|
||||
* @param amounts the amount requested for this flashloan
|
||||
* @param mode the flashloan mode
|
||||
* @param params a bytes array to be sent to the flashloan executor
|
||||
* @param referralCode the referral code of the caller
|
||||
**/
|
||||
function flashLoan(
|
||||
address receiver,
|
||||
address reserve,
|
||||
uint256 amount,
|
||||
uint256 debtType,
|
||||
address[] calldata assets,
|
||||
uint256[] calldata amounts,
|
||||
uint256 mode,
|
||||
bytes calldata params,
|
||||
uint16 referralCode
|
||||
) external;
|
||||
|
|
|
@ -162,7 +162,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
|
|||
_stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
|
||||
);
|
||||
vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(
|
||||
utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE).rayMul(_variableRateSlope1)
|
||||
utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
IAToken(aToken).burn(msg.sender, msg.sender, amountToWithdraw, reserve.liquidityIndex);
|
||||
|
||||
emit Withdraw(asset, msg.sender, amount);
|
||||
emit Withdraw(asset, msg.sender, amountToWithdraw);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -262,15 +262,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
ReserveLogic.InterestRateMode interestRateMode = ReserveLogic.InterestRateMode(rateMode);
|
||||
|
||||
//default to max amount
|
||||
uint256 paybackAmount = interestRateMode == ReserveLogic.InterestRateMode.STABLE
|
||||
? stableDebt
|
||||
: variableDebt;
|
||||
|
||||
if (amount != type(uint256).max && amount < paybackAmount) {
|
||||
paybackAmount = amount;
|
||||
}
|
||||
|
||||
ValidationLogic.validateRepay(
|
||||
reserve,
|
||||
amount,
|
||||
|
@ -280,6 +271,15 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
variableDebt
|
||||
);
|
||||
|
||||
//default to max amount
|
||||
uint256 paybackAmount = interestRateMode == ReserveLogic.InterestRateMode.STABLE
|
||||
? stableDebt
|
||||
: variableDebt;
|
||||
|
||||
if (amount < paybackAmount) {
|
||||
paybackAmount = amount;
|
||||
}
|
||||
|
||||
reserve.updateState();
|
||||
|
||||
//burns an equivalent amount of debt tokens
|
||||
|
@ -356,9 +356,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @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
|
||||
**/
|
||||
|
@ -373,7 +374,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
uint256 stableBorrowBalance = IERC20(stableDebtToken).balanceOf(user);
|
||||
|
||||
//if the utilization rate is below 95%, no rebalances are needed
|
||||
//if the usage ratio is below 95%, no rebalances are needed
|
||||
uint256 totalBorrows = stableDebtToken
|
||||
.totalSupply()
|
||||
.add(variableDebtToken.totalSupply())
|
||||
|
@ -417,7 +418,7 @@ 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 user the deposit as collateral, false otherwise.
|
||||
* @param useAsCollateral true if the user wants to use the deposit as collateral, false otherwise.
|
||||
**/
|
||||
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external override {
|
||||
_whenNotPaused();
|
||||
|
@ -483,11 +484,15 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
}
|
||||
|
||||
struct FlashLoanLocalVars {
|
||||
uint256 premium;
|
||||
uint256 amountPlusPremium;
|
||||
IFlashLoanReceiver receiver;
|
||||
address aTokenAddress;
|
||||
address oracle;
|
||||
ReserveLogic.InterestRateMode debtMode;
|
||||
uint256 i;
|
||||
address currentAsset;
|
||||
address currentATokenAddress;
|
||||
uint256 currentAmount;
|
||||
uint256 currentPremium;
|
||||
uint256 currentAmountPlusPremium;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -495,68 +500,90 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
* 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 asset The address of the principal reserve
|
||||
* @param amount The amount requested for this flashloan
|
||||
* @param assets The addresss of the assets being flashborrowed
|
||||
* @param amounts The amounts requested for this flashloan for each asset
|
||||
* @param mode Type of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable
|
||||
* @param params Variadic packed params to pass to the receiver as extra information
|
||||
* @param referralCode Referral code of the flash loan
|
||||
**/
|
||||
function flashLoan(
|
||||
address receiverAddress,
|
||||
address asset,
|
||||
uint256 amount,
|
||||
address[] calldata assets,
|
||||
uint256[] calldata amounts,
|
||||
uint256 mode,
|
||||
bytes calldata params,
|
||||
uint16 referralCode
|
||||
) external override {
|
||||
_whenNotPaused();
|
||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||
|
||||
FlashLoanLocalVars memory vars;
|
||||
|
||||
vars.aTokenAddress = reserve.aTokenAddress;
|
||||
ValidationLogic.validateFlashloan(assets, amounts, mode);
|
||||
|
||||
vars.premium = amount.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000);
|
||||
|
||||
ValidationLogic.validateFlashloan(mode, vars.premium);
|
||||
|
||||
ReserveLogic.InterestRateMode debtMode = ReserveLogic.InterestRateMode(mode);
|
||||
address[] memory aTokenAddresses = new address[](assets.length);
|
||||
uint256[] memory premiums = new uint256[](assets.length);
|
||||
|
||||
vars.receiver = IFlashLoanReceiver(receiverAddress);
|
||||
vars.debtMode = ReserveLogic.InterestRateMode(mode);
|
||||
|
||||
//transfer funds to the receiver
|
||||
IAToken(vars.aTokenAddress).transferUnderlyingTo(receiverAddress, amount);
|
||||
for (vars.i = 0; vars.i < assets.length; vars.i++) {
|
||||
aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress;
|
||||
|
||||
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(asset, amount, vars.premium, params),
|
||||
vars.receiver.executeOperation(assets, amounts, premiums, params),
|
||||
Errors.INVALID_FLASH_LOAN_EXECUTOR_RETURN
|
||||
);
|
||||
|
||||
vars.amountPlusPremium = amount.add(vars.premium);
|
||||
for (vars.i = 0; vars.i < assets.length; vars.i++) {
|
||||
vars.currentAsset = assets[vars.i];
|
||||
vars.currentAmount = amounts[vars.i];
|
||||
vars.currentPremium = premiums[vars.i];
|
||||
vars.currentATokenAddress = aTokenAddresses[vars.i];
|
||||
|
||||
if (debtMode == ReserveLogic.InterestRateMode.NONE) {
|
||||
IERC20(asset).safeTransferFrom(receiverAddress, vars.aTokenAddress, vars.amountPlusPremium);
|
||||
vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium);
|
||||
|
||||
reserve.updateState();
|
||||
reserve.cumulateToLiquidityIndex(IERC20(vars.aTokenAddress).totalSupply(), vars.premium);
|
||||
reserve.updateInterestRates(asset, vars.aTokenAddress, vars.premium, 0);
|
||||
if (vars.debtMode == ReserveLogic.InterestRateMode.NONE) {
|
||||
_reserves[vars.currentAsset].updateState();
|
||||
_reserves[vars.currentAsset].cumulateToLiquidityIndex(
|
||||
IERC20(vars.currentATokenAddress).totalSupply(),
|
||||
vars.currentPremium
|
||||
);
|
||||
_reserves[vars.currentAsset].updateInterestRates(
|
||||
vars.currentAsset,
|
||||
vars.currentATokenAddress,
|
||||
vars.currentPremium,
|
||||
0
|
||||
);
|
||||
|
||||
emit FlashLoan(receiverAddress, asset, amount, vars.premium, referralCode);
|
||||
} else {
|
||||
//if the user didn't choose to return the funds, the system checks if there
|
||||
//is enough collateral and eventually open a position
|
||||
_executeBorrow(
|
||||
ExecuteBorrowParams(
|
||||
asset,
|
||||
msg.sender,
|
||||
msg.sender,
|
||||
vars.amountPlusPremium,
|
||||
mode,
|
||||
vars.aTokenAddress,
|
||||
referralCode,
|
||||
false
|
||||
)
|
||||
);
|
||||
IERC20(vars.currentAsset).safeTransferFrom(
|
||||
receiverAddress,
|
||||
vars.currentATokenAddress,
|
||||
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
|
||||
_executeBorrow(
|
||||
ExecuteBorrowParams(
|
||||
vars.currentAsset,
|
||||
msg.sender,
|
||||
msg.sender,
|
||||
vars.currentAmount,
|
||||
mode,
|
||||
vars.currentATokenAddress,
|
||||
referralCode,
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
emit FlashLoan(receiverAddress, mode, assets, amounts, premiums, referralCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -194,13 +194,6 @@ contract LendingPoolCollateralManager is VersionedInitializable, LendingPoolStor
|
|||
//update the principal reserve
|
||||
principalReserve.updateState();
|
||||
|
||||
principalReserve.updateInterestRates(
|
||||
principal,
|
||||
principalReserve.aTokenAddress,
|
||||
vars.actualAmountToLiquidate,
|
||||
0
|
||||
);
|
||||
|
||||
if (vars.userVariableDebt >= vars.actualAmountToLiquidate) {
|
||||
IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
|
||||
user,
|
||||
|
@ -223,6 +216,13 @@ contract LendingPoolCollateralManager is VersionedInitializable, LendingPoolStor
|
|||
);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -306,8 +306,8 @@ contract LendingPoolCollateralManager is VersionedInitializable, LendingPoolStor
|
|||
.principalCurrencyPrice
|
||||
.mul(purchaseAmount)
|
||||
.mul(10**vars.collateralDecimals)
|
||||
.div(vars.collateralPrice.mul(10**vars.principalDecimals))
|
||||
.percentMul(vars.liquidationBonus);
|
||||
.percentMul(vars.liquidationBonus)
|
||||
.div(vars.collateralPrice.mul(10**vars.principalDecimals));
|
||||
|
||||
if (vars.maxAmountCollateralToLiquidate > userCollateralBalance) {
|
||||
collateralAmount = userCollateralBalance;
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.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 {Errors} from '../libraries/helpers/Errors.sol';
|
||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||
|
@ -200,7 +201,6 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
|
||||
/**
|
||||
* @dev initializes a reserve
|
||||
* @param asset the address of the reserve to be initialized
|
||||
* @param aTokenImpl the address of the aToken contract implementation
|
||||
* @param stableDebtTokenImpl the address of the stable debt token contract
|
||||
* @param variableDebtTokenImpl the address of the variable debt token contract
|
||||
|
@ -208,13 +208,35 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param interestRateStrategyAddress the address of the interest rate strategy contract for this reserve
|
||||
**/
|
||||
function initReserve(
|
||||
address asset,
|
||||
address aTokenImpl,
|
||||
address stableDebtTokenImpl,
|
||||
address variableDebtTokenImpl,
|
||||
uint8 underlyingAssetDecimals,
|
||||
address interestRateStrategyAddress
|
||||
) public onlyAaveAdmin {
|
||||
address asset = ITokenConfiguration(aTokenImpl).UNDERLYING_ASSET_ADDRESS();
|
||||
|
||||
require(
|
||||
address(pool) == ITokenConfiguration(aTokenImpl).POOL(),
|
||||
Errors.INVALID_ATOKEN_POOL_ADDRESS
|
||||
);
|
||||
require(
|
||||
address(pool) == ITokenConfiguration(stableDebtTokenImpl).POOL(),
|
||||
Errors.INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS
|
||||
);
|
||||
require(
|
||||
address(pool) == ITokenConfiguration(variableDebtTokenImpl).POOL(),
|
||||
Errors.INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS
|
||||
);
|
||||
require(
|
||||
asset == ITokenConfiguration(stableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
|
||||
Errors.INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
|
||||
);
|
||||
require(
|
||||
asset == ITokenConfiguration(variableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
|
||||
Errors.INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
|
||||
);
|
||||
|
||||
address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals);
|
||||
|
||||
address stableDebtTokenProxyAddress = _initTokenWithProxy(
|
||||
|
|
|
@ -45,13 +45,14 @@ library Errors {
|
|||
string public constant INVALID_EQUAL_ASSETS_TO_SWAP = '56';
|
||||
string public constant NO_MORE_RESERVES_ALLOWED = '59';
|
||||
string public constant INVALID_FLASH_LOAN_EXECUTOR_RETURN = '60';
|
||||
string public constant INCONSISTENT_FLASHLOAN_PARAMS = '69';
|
||||
|
||||
// require error messages - aToken - DebtTokens
|
||||
string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool'
|
||||
string public constant CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself'
|
||||
string public constant TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero'
|
||||
string public constant INVALID_MINT_AMOUNT = '53'; //invalid amount to mint
|
||||
string public constant INVALID_BURN_AMOUNT = '54'; //invalid amount to burn
|
||||
string public constant INVALID_MINT_AMOUNT = '61'; //invalid amount to mint
|
||||
string public constant INVALID_BURN_AMOUNT = '62'; //invalid amount to burn
|
||||
|
||||
// require error messages - ReserveLogic
|
||||
string public constant RESERVE_ALREADY_INITIALIZED = '34'; // 'Reserve has already been initialized'
|
||||
|
@ -64,9 +65,15 @@ library Errors {
|
|||
//require error messages - LendingPoolConfiguration
|
||||
string public constant CALLER_NOT_AAVE_ADMIN = '35'; // 'The caller must be the aave admin'
|
||||
string public constant RESERVE_LIQUIDITY_NOT_0 = '36'; // 'The liquidity of the reserve needs to be 0'
|
||||
string public constant INVALID_ATOKEN_POOL_ADDRESS = '63'; // the lending pool in the aToken implementation is not configured correctly
|
||||
string public constant INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = '64'; // the lending pool in the stable debt token implementation is not configured correctly
|
||||
string public constant INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = '65'; // the lending pool in the variable debt token implementation is not configured correctly
|
||||
string public constant INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '66'; // the underlying asset in the stable debt token implementation is not configured correctly
|
||||
string public constant INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '67'; // the underlying asset in the variable debt token implementation is not configured correctly
|
||||
|
||||
//require error messages - LendingPoolAddressesProviderRegistry
|
||||
string public constant PROVIDER_NOT_REGISTERED = '37'; // 'Provider is not registered'
|
||||
string public constant INVALID_ADDRESSES_PROVIDER_ID = '68'; // the addresses provider id needs to be greater than 0
|
||||
|
||||
//return error messages - LendingPoolCollateralManager
|
||||
string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38'; // 'Health factor is not below the threshold'
|
||||
|
|
|
@ -25,7 +25,6 @@ library GenericLogic {
|
|||
using UserConfiguration for UserConfiguration.Map;
|
||||
|
||||
uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1 ether;
|
||||
uint256 public constant HEALTH_FACTOR_CRITICAL_THRESHOLD = 0.98 ether;
|
||||
|
||||
struct balanceDecreaseAllowedLocalVars {
|
||||
uint256 decimals;
|
||||
|
|
|
@ -359,7 +359,9 @@ library ReserveLogic {
|
|||
|
||||
vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor);
|
||||
|
||||
IAToken(reserve.aTokenAddress).mintToTreasury(vars.amountToMint, newLiquidityIndex);
|
||||
if (vars.amountToMint != 0) {
|
||||
IAToken(reserve.aTokenAddress).mintToTreasury(vars.amountToMint, newLiquidityIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -327,11 +327,16 @@ library ValidationLogic {
|
|||
/**
|
||||
* @dev validates a flashloan action
|
||||
* @param mode the flashloan mode (0 = classic flashloan, 1 = open a stable rate loan, 2 = open a variable rate loan)
|
||||
* @param premium the premium paid on the flashloan
|
||||
* @param assets the assets being flashborrowed
|
||||
* @param amounts the amounts for each asset being borrowed
|
||||
**/
|
||||
function validateFlashloan(uint256 mode, uint256 premium) internal pure {
|
||||
require(premium > 0, Errors.REQUESTED_AMOUNT_TOO_SMALL);
|
||||
function validateFlashloan(
|
||||
address[] memory assets,
|
||||
uint256[] memory amounts,
|
||||
uint256 mode
|
||||
) internal pure {
|
||||
require(mode <= uint256(ReserveLogic.InterestRateMode.VARIABLE), Errors.INVALID_FLASHLOAN_MODE);
|
||||
require(assets.length == amounts.length, Errors.INCONSISTENT_FLASHLOAN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,7 @@ library MathUtils {
|
|||
using SafeMath for uint256;
|
||||
using WadRayMath for uint256;
|
||||
|
||||
/// @dev Ignoring leap years
|
||||
uint256 internal constant SECONDS_PER_YEAR = 365 days;
|
||||
|
||||
/**
|
||||
|
@ -25,9 +26,7 @@ library MathUtils {
|
|||
//solium-disable-next-line
|
||||
uint256 timeDifference = block.timestamp.sub(uint256(lastUpdateTimestamp));
|
||||
|
||||
uint256 timeDelta = timeDifference.wadToRay().rayDiv(SECONDS_PER_YEAR.wadToRay());
|
||||
|
||||
return rate.rayMul(timeDelta).add(WadRayMath.ray());
|
||||
return (rate.mul(timeDifference) / SECONDS_PER_YEAR).add(WadRayMath.ray());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,13 +58,9 @@ library WadRayMath {
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint256 result = a * b;
|
||||
uint256 result = a * b + halfWAD;
|
||||
|
||||
require(result / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfWAD;
|
||||
|
||||
require(result >= halfWAD, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfWAD && (result - halfWAD) / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / WAD;
|
||||
}
|
||||
|
@ -80,13 +76,9 @@ library WadRayMath {
|
|||
|
||||
uint256 halfB = b / 2;
|
||||
|
||||
uint256 result = a * WAD;
|
||||
uint256 result = a * WAD + halfB;
|
||||
|
||||
require(result / WAD == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfB;
|
||||
|
||||
require(result >= halfB, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfB && (result - halfB) / WAD == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / b;
|
||||
}
|
||||
|
@ -102,13 +94,9 @@ library WadRayMath {
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint256 result = a * b;
|
||||
uint256 result = a * b + halfRAY;
|
||||
|
||||
require(result / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfRAY;
|
||||
|
||||
require(result >= halfRAY, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfRAY && (result - halfRAY) / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / RAY;
|
||||
}
|
||||
|
@ -124,13 +112,9 @@ library WadRayMath {
|
|||
|
||||
uint256 halfB = b / 2;
|
||||
|
||||
uint256 result = a * RAY;
|
||||
uint256 result = a * RAY + halfB;
|
||||
|
||||
require(result / RAY == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfB;
|
||||
|
||||
require(result >= halfB, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfB && (result - halfB) / RAY == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / b;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
|||
|
||||
ILendingPoolAddressesProvider internal _provider;
|
||||
|
||||
event ExecutedWithFail(address _reserve, uint256 _amount, uint256 _fee);
|
||||
event ExecutedWithSuccess(address _reserve, uint256 _amount, uint256 _fee);
|
||||
event ExecutedWithFail(address[] _assets, uint256[] _amounts, uint256[] _premiums);
|
||||
event ExecutedWithSuccess(address[] _assets, uint256[] _amounts, uint256[] _premiums);
|
||||
|
||||
bool _failExecution;
|
||||
uint256 _amountToApprove;
|
||||
|
@ -44,33 +44,40 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
|||
}
|
||||
|
||||
function executeOperation(
|
||||
address reserve,
|
||||
uint256 amount,
|
||||
uint256 fee,
|
||||
address[] memory assets,
|
||||
uint256[] memory amounts,
|
||||
uint256[] memory premiums,
|
||||
bytes memory params
|
||||
) public override returns (bool) {
|
||||
params;
|
||||
//mint to this contract the specific amount
|
||||
MintableERC20 token = MintableERC20(reserve);
|
||||
|
||||
//check the contract has the specified balance
|
||||
require(amount <= IERC20(reserve).balanceOf(address(this)), 'Invalid balance for the contract');
|
||||
|
||||
uint256 amountToReturn = (_amountToApprove != 0) ? _amountToApprove : amount.add(fee);
|
||||
|
||||
if (_failExecution) {
|
||||
emit ExecutedWithFail(reserve, amount, fee);
|
||||
emit ExecutedWithFail(assets, amounts, premiums);
|
||||
return !_simulateEOA;
|
||||
}
|
||||
|
||||
//execution does not fail - mint tokens and return them to the _destination
|
||||
//note: if the reserve is eth, the mock contract must receive at least _fee ETH before calling executeOperation
|
||||
for (uint256 i = 0; i < assets.length; i++) {
|
||||
//mint to this contract the specific amount
|
||||
MintableERC20 token = MintableERC20(assets[i]);
|
||||
|
||||
token.mint(fee);
|
||||
//check the contract has the specified balance
|
||||
require(
|
||||
amounts[i] <= IERC20(assets[i]).balanceOf(address(this)),
|
||||
'Invalid balance for the contract'
|
||||
);
|
||||
|
||||
IERC20(reserve).approve(_addressesProvider.getLendingPool(), amountToReturn);
|
||||
uint256 amountToReturn = (_amountToApprove != 0)
|
||||
? _amountToApprove
|
||||
: amounts[i].add(premiums[i]);
|
||||
//execution does not fail - mint tokens and return them to the _destination
|
||||
//note: if the reserve is eth, the mock contract must receive at least _fee ETH before calling executeOperation
|
||||
|
||||
emit ExecutedWithSuccess(reserve, amount, fee);
|
||||
token.mint(premiums[i]);
|
||||
|
||||
IERC20(assets[i]).approve(_addressesProvider.getLendingPool(), amountToReturn);
|
||||
}
|
||||
|
||||
emit ExecutedWithSuccess(assets, amounts, premiums);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
pragma solidity ^0.6.8;
|
||||
|
||||
import {IncentivizedERC20} from './IncentivizedERC20.sol';
|
||||
import {LendingPool} from '../lendingpool/LendingPool.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';
|
||||
|
@ -32,7 +32,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
uint256 public constant ATOKEN_REVISION = 0x1;
|
||||
address public immutable UNDERLYING_ASSET_ADDRESS;
|
||||
address public immutable RESERVE_TREASURY_ADDRESS;
|
||||
LendingPool public immutable POOL;
|
||||
ILendingPool public immutable POOL;
|
||||
|
||||
/// @dev owner => next valid nonce to submit with permit()
|
||||
mapping(address => uint256) public _nonces;
|
||||
|
@ -45,7 +45,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
}
|
||||
|
||||
constructor(
|
||||
LendingPool pool,
|
||||
ILendingPool pool,
|
||||
address underlyingAssetAddress,
|
||||
address reserveTreasuryAddress,
|
||||
string memory tokenName,
|
||||
|
|
|
@ -181,10 +181,10 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
|
|||
_balances[recipient] = _balances[recipient].add(amount);
|
||||
|
||||
if (address(_incentivesController) != address(0)) {
|
||||
uint256 totalSupply = _totalSupply;
|
||||
_incentivesController.handleAction(sender, totalSupply, oldSenderBalance);
|
||||
uint256 currentTotalSupply = _totalSupply;
|
||||
_incentivesController.handleAction(sender, currentTotalSupply, oldSenderBalance);
|
||||
if (sender != recipient) {
|
||||
_incentivesController.handleAction(recipient, totalSupply, oldRecipientBalance);
|
||||
_incentivesController.handleAction(recipient, currentTotalSupply, oldRecipientBalance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
_totalSupplyTimestamp = _timestamps[user] = uint40(block.timestamp);
|
||||
|
||||
//calculates the updated average stable rate
|
||||
_avgStableRate = vars
|
||||
vars.currentAvgStableRate = _avgStableRate = vars
|
||||
.currentAvgStableRate
|
||||
.rayMul(vars.previousSupply.wadToRay())
|
||||
.add(rate.rayMul(vars.amountInRay))
|
||||
|
@ -139,7 +139,15 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
// transfer event to track balances
|
||||
emit Transfer(address(0), user, amount);
|
||||
|
||||
emit Mint(user, amount, previousBalance, currentBalance, balanceIncrease, vars.newStableRate);
|
||||
emit Mint(
|
||||
user,
|
||||
amount,
|
||||
previousBalance,
|
||||
currentBalance,
|
||||
balanceIncrease,
|
||||
vars.newStableRate,
|
||||
vars.currentAvgStableRate
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,17 +163,18 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
) = _calculateBalanceIncrease(user);
|
||||
|
||||
uint256 previousSupply = totalSupply();
|
||||
uint256 newStableRate = 0;
|
||||
|
||||
//since the total supply and each single user debt accrue separately,
|
||||
//there might be accumulation errors so that the last borrower repaying
|
||||
//might actually try to repay more than the available debt supply.
|
||||
//in this case we simply set the total supply and the avg stable rate to 0
|
||||
if (previousSupply <= amount) {
|
||||
_avgStableRate = 0;
|
||||
newStableRate = _avgStableRate = 0;
|
||||
_totalSupply = 0;
|
||||
} else {
|
||||
uint256 nextSupply = _totalSupply = previousSupply.sub(amount);
|
||||
_avgStableRate = _avgStableRate
|
||||
newStableRate = _avgStableRate = _avgStableRate
|
||||
.rayMul(previousSupply.wadToRay())
|
||||
.sub(_usersData[user].rayMul(amount.wadToRay()))
|
||||
.rayDiv(nextSupply.wadToRay());
|
||||
|
@ -190,14 +199,13 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
// transfer event to track balances
|
||||
emit Transfer(user, address(0), amount);
|
||||
|
||||
emit Burn(user, amount, previousBalance, currentBalance, balanceIncrease);
|
||||
emit Burn(user, amount, previousBalance, currentBalance, balanceIncrease, newStableRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates the increase in balance since the last user interaction
|
||||
* @param user The address of the user for which the interest is being accumulated
|
||||
* @return The previous principal balance, the new principal balance, the balance increase
|
||||
* and the new user index
|
||||
* @return The previous principal balance, the new principal balance and the balance increase
|
||||
**/
|
||||
function _calculateBalanceIncrease(address user)
|
||||
internal
|
||||
|
|
|
@ -43,7 +43,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET));
|
||||
return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,7 +102,8 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
|||
* @return the total supply
|
||||
**/
|
||||
function totalSupply() public virtual override view returns (uint256) {
|
||||
return super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET));
|
||||
return
|
||||
super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,8 +15,8 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
|
|||
*/
|
||||
|
||||
abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
||||
address internal immutable UNDERLYING_ASSET;
|
||||
ILendingPool internal immutable POOL;
|
||||
address public immutable UNDERLYING_ASSET_ADDRESS;
|
||||
ILendingPool public immutable POOL;
|
||||
mapping(address => uint256) internal _usersData;
|
||||
|
||||
/**
|
||||
|
@ -39,7 +39,7 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
|||
address incentivesController
|
||||
) public IncentivizedERC20(name, symbol, 18, incentivesController) {
|
||||
POOL = ILendingPool(pool);
|
||||
UNDERLYING_ASSET = underlyingAssetAddress;
|
||||
UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,10 +58,6 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
|||
_setDecimals(decimals);
|
||||
}
|
||||
|
||||
function underlyingAssetAddress() public view returns (address) {
|
||||
return UNDERLYING_ASSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Being non transferrable, the debt token does not implement any of the
|
||||
* standard ERC20 functions for transfer and allowance.
|
||||
|
|
|
@ -21,6 +21,7 @@ interface IStableDebtToken {
|
|||
* @param currentBalance the current balance of the user
|
||||
* @param balanceIncrease the debt increase since the last update
|
||||
* @param newRate the rate of the debt after the minting
|
||||
* @param avgStableRate the new average stable rate after the minting
|
||||
**/
|
||||
event Mint(
|
||||
address indexed user,
|
||||
|
@ -28,7 +29,8 @@ interface IStableDebtToken {
|
|||
uint256 previousBalance,
|
||||
uint256 currentBalance,
|
||||
uint256 balanceIncrease,
|
||||
uint256 newRate
|
||||
uint256 newRate,
|
||||
uint256 avgStableRate
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -38,13 +40,15 @@ interface IStableDebtToken {
|
|||
* @param previousBalance the previous balance of the user
|
||||
* @param currentBalance the current balance of the user
|
||||
* @param balanceIncrease the debt increase since the last update
|
||||
* @param avgStableRate the new average stable rate after the minting
|
||||
**/
|
||||
event Burn(
|
||||
address indexed user,
|
||||
uint256 amount,
|
||||
uint256 previousBalance,
|
||||
uint256 currentBalance,
|
||||
uint256 balanceIncrease
|
||||
uint256 balanceIncrease,
|
||||
uint256 avgStableRate
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
13
contracts/tokenization/interfaces/ITokenConfiguration.sol
Normal file
13
contracts/tokenization/interfaces/ITokenConfiguration.sol
Normal file
|
@ -0,0 +1,13 @@
|
|||
pragma solidity ^0.6;
|
||||
|
||||
/**
|
||||
* @title ITokenConfiguration
|
||||
* @author Aave
|
||||
* @dev common interface between aTokens and debt tokens to fetch the
|
||||
* token configuration
|
||||
**/
|
||||
interface ITokenConfiguration {
|
||||
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
|
||||
|
||||
function POOL() external view returns (address);
|
||||
}
|
|
@ -27,8 +27,8 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xd7e3C4b2CE495066dE1923c268D68A844bD7Ae13",
|
||||
"deployer": "0x6b40a028d2Ab94e5f6d3793F32D326CDf724Bb1D"
|
||||
"address": "0xF9a2E6D57c691f3aa5269858178a13Ef06378579",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"LendingPoolAddressesProviderRegistry": {
|
||||
|
@ -45,8 +45,8 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x83c7A0E78e8eee2108a87d7a6770f22BAcb68b5A",
|
||||
"deployer": "0x6b40a028d2Ab94e5f6d3793F32D326CDf724Bb1D"
|
||||
"address": "0xf3266d89e6742fAE2C35D05eD549cd4e117300a7",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"FeeProvider": {
|
||||
|
@ -76,7 +76,7 @@
|
|||
"address": "0x9Ec55627757348b322c8dD0865D704649bFa0c7b"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x1339f3c1FfF00D0FD8946187fdC61F0ef0fFe786"
|
||||
"address": "0x1aae278bCcdb95817c7A546d752fC662F09b6DBa"
|
||||
}
|
||||
},
|
||||
"LendingPoolDataProvider": {
|
||||
|
@ -92,7 +92,7 @@
|
|||
"address": "0x3EE716e38f21e5FC16BFDB773db24D63C637A5d8"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xB43CCfF1148bb5ab2104E2ee68A7c30cDEBb9A9C"
|
||||
"address": "0x8E05A3054cb736258FaF4638D07058cE6e294d2C"
|
||||
}
|
||||
},
|
||||
"PriceOracle": {
|
||||
|
@ -173,8 +173,8 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xc4e3d83AEd3D3c60Cf4b238F634014cE103F6fa1",
|
||||
"deployer": "0x6b40a028d2Ab94e5f6d3793F32D326CDf724Bb1D"
|
||||
"address": "0x47341CE48FfE1cbD91991578B880a18c45cdB5CA",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"LendingPoolLiquidationManager": {
|
||||
|
@ -235,7 +235,7 @@
|
|||
},
|
||||
"WalletBalanceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4",
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
@ -580,8 +580,8 @@
|
|||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xE4566ce19626826360f4faD941418e2849fC3685",
|
||||
"deployer": "0x6b40a028d2Ab94e5f6d3793F32D326CDf724Bb1D"
|
||||
"address": "0xfF28b837352d9531bAb6dFF3650D7831192117F7",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"StableDebtToken": {
|
||||
|
@ -598,8 +598,8 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x0043967C1Cf13c4Ff3Bc38109054D5a97C147B4A",
|
||||
"deployer": "0x6b40a028d2Ab94e5f6d3793F32D326CDf724Bb1D"
|
||||
"address": "0x0EDc241FdA0dF39EB1B9eB1236217BBe72Ab911D",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"VariableDebtToken": {
|
||||
|
@ -616,8 +616,8 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xdF75B68c75c30D177f4Dbd47cBcb5E2E4f3cf8F9",
|
||||
"deployer": "0x6b40a028d2Ab94e5f6d3793F32D326CDf724Bb1D"
|
||||
"address": "0x293f5BcC66762c28a5d3Bd8512a799D457F5296D",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"AToken": {
|
||||
|
@ -634,13 +634,13 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x1A23ADa7218e0a66b7368E12E379Ea88d7a68a27",
|
||||
"deployer": "0x6b40a028d2Ab94e5f6d3793F32D326CDf724Bb1D"
|
||||
"address": "0xf303Ae6F24C29D94E367fdb5C7aE04D32BEbF13E",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"MockAToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x392E5355a0e88Bd394F717227c752670fb3a8020",
|
||||
"address": "0x3bDA11B584dDff7F66E0cFe1da1562c92B45db60",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
@ -668,7 +668,7 @@
|
|||
},
|
||||
"MockStableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460",
|
||||
"address": "0x392E5355a0e88Bd394F717227c752670fb3a8020",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
@ -682,7 +682,7 @@
|
|||
},
|
||||
"MockVariableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0xEBAB67ee3ef604D5c250A53b4b8fcbBC6ec3007C",
|
||||
"address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
|
|
@ -2,6 +2,8 @@ version: '3.5'
|
|||
|
||||
services:
|
||||
contracts-env:
|
||||
env_file:
|
||||
- .env
|
||||
build:
|
||||
context: ./
|
||||
working_dir: /src
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {Contract, Signer, utils, ethers} from 'ethers';
|
||||
import {CommonsConfig} from '../config/commons';
|
||||
import {getDb, BRE} from './misc-utils';
|
||||
import {getDb, BRE, waitForTx} from './misc-utils';
|
||||
import {
|
||||
tEthereumAddress,
|
||||
eContractid,
|
||||
|
@ -103,7 +103,7 @@ export const deployContract = async <ContractType extends Contract>(
|
|||
const contract = (await (await BRE.ethers.getContractFactory(contractName)).deploy(
|
||||
...args
|
||||
)) as ContractType;
|
||||
|
||||
await waitForTx(contract.deployTransaction);
|
||||
await registerContractInJsonDb(<eContractid>contractName, contract);
|
||||
return contract;
|
||||
};
|
||||
|
@ -207,6 +207,7 @@ export const deployLendingPool = async (verify?: boolean) => {
|
|||
);
|
||||
const factory = await linkLibrariesToArtifact(lendingPoolArtifact);
|
||||
const lendingPool = await factory.deploy();
|
||||
await waitForTx(lendingPool.deployTransaction);
|
||||
const instance = (await lendingPool.deployed()) as LendingPool;
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.LendingPool, instance.address, []);
|
||||
|
@ -837,7 +838,7 @@ export const initReserves = async (
|
|||
stableRateSlope2,
|
||||
},
|
||||
] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex];
|
||||
console.log('deploy def reserve');
|
||||
console.log('deploy the interest rate strategy for ', assetSymbol);
|
||||
const rateStrategyContract = await deployDefaultReserveInterestRateStrategy(
|
||||
[
|
||||
lendingPoolAddressesProvider.address,
|
||||
|
@ -850,7 +851,7 @@ export const initReserves = async (
|
|||
verify
|
||||
);
|
||||
|
||||
console.log('deploy stable deb totken ', assetSymbol);
|
||||
console.log('deploy the stable debt totken for ', assetSymbol);
|
||||
const stableDebtToken = await deployStableDebtToken(
|
||||
[
|
||||
`Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
|
@ -862,7 +863,7 @@ export const initReserves = async (
|
|||
verify
|
||||
);
|
||||
|
||||
console.log('deploy var deb totken ', assetSymbol);
|
||||
console.log('deploy the variable debt totken for ', assetSymbol);
|
||||
const variableDebtToken = await deployVariableDebtToken(
|
||||
[
|
||||
`Aave variable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
|
@ -874,7 +875,7 @@ export const initReserves = async (
|
|||
verify
|
||||
);
|
||||
|
||||
console.log('deploy a token ', assetSymbol);
|
||||
console.log('deploy the aToken for ', assetSymbol);
|
||||
const aToken = await deployGenericAToken(
|
||||
[
|
||||
lendingPool.address,
|
||||
|
@ -894,9 +895,8 @@ export const initReserves = async (
|
|||
}
|
||||
}
|
||||
|
||||
console.log('init reserve currency ', assetSymbol);
|
||||
console.log('initialize the reserve ', assetSymbol);
|
||||
await lendingPoolConfigurator.initReserve(
|
||||
tokenAddress,
|
||||
aToken.address,
|
||||
stableDebtToken.address,
|
||||
variableDebtToken.address,
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
import {exit} from 'process';
|
||||
import fs from 'fs';
|
||||
import globby from 'globby';
|
||||
import {file} from 'tmp-promise';
|
||||
import {BRE} from './misc-utils';
|
||||
|
||||
const listSolidityFiles = (dir: string) => globby(`${dir}/**/*.sol`);
|
||||
|
||||
const fatalErrors = [
|
||||
`The address provided as argument contains a contract, but its bytecode`,
|
||||
`Daily limit of 100 source code submissions reached`,
|
||||
];
|
||||
|
||||
export const SUPPORTED_ETHERSCAN_NETWORKS = ['main', 'ropsten', 'kovan'];
|
||||
|
||||
export const getEtherscanPath = async (contractName: string) => {
|
||||
const compilerInput = await BRE.run('compile:get-compiler-input');
|
||||
const paths = Object.keys(compilerInput.sources);
|
||||
const paths = await listSolidityFiles(BRE.config.paths.sources);
|
||||
const path = paths.find((p) => p.includes(contractName));
|
||||
if (!path) {
|
||||
throw new Error(
|
||||
|
@ -79,12 +86,22 @@ export const runTaskWithRetry = async (
|
|||
cleanup();
|
||||
} else {
|
||||
cleanup();
|
||||
console.error('[ERROR] Errors after all the retries, check the logs for more information.');
|
||||
console.error(
|
||||
'[ETHERSCAN][ERROR] Errors after all the retries, check the logs for more information.'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
counter--;
|
||||
console.info(`[INFO] Retrying attemps: ${counter}.`);
|
||||
console.error('[ERROR]', error.message);
|
||||
console.info(`[ETHERSCAN][[INFO] Retrying attemps: ${counter}.`);
|
||||
console.error('[ETHERSCAN][[ERROR]', error.message);
|
||||
|
||||
if (fatalErrors.some((fatalError) => error.message.includes(fatalError))) {
|
||||
console.error(
|
||||
'[ETHERSCAN][[ERROR] Fatal error detected, skip retries and resume deployment.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await runTaskWithRetry(task, params, counter, msDelay, cleanup);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ import {iMultiPoolsAssets, IReserveParams, tEthereumAddress} from './types';
|
|||
import {LendingPool} from '../types/LendingPool';
|
||||
import {LendingPoolConfigurator} from '../types/LendingPoolConfigurator';
|
||||
import {AaveProtocolTestHelpers} from '../types/AaveProtocolTestHelpers';
|
||||
import {waitForTx} from './misc-utils';
|
||||
|
||||
export const enableReservesToBorrow = async (
|
||||
reservesParams: iMultiPoolsAssets<IReserveParams>,
|
||||
|
@ -29,7 +30,14 @@ export const enableReservesToBorrow = async (
|
|||
continue;
|
||||
}
|
||||
|
||||
await lendingPoolConfigurator.enableBorrowingOnReserve(tokenAddress, stableBorrowRateEnabled);
|
||||
console.log('Enabling borrowing on reserve ', assetSymbol);
|
||||
|
||||
await waitForTx(
|
||||
await lendingPoolConfigurator.enableBorrowingOnReserve(
|
||||
tokenAddress,
|
||||
stableBorrowRateEnabled
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`Enabling reserve for borrowings for ${assetSymbol} failed with error ${e}. Skipped.`
|
||||
|
@ -66,11 +74,15 @@ export const enableReservesAsCollateral = async (
|
|||
}
|
||||
|
||||
try {
|
||||
await lendingPoolConfigurator.enableReserveAsCollateral(
|
||||
tokenAddress,
|
||||
baseLTVAsCollateral,
|
||||
liquidationThreshold,
|
||||
liquidationBonus
|
||||
console.log(`Enabling reserve ${assetSymbol} as collateral`);
|
||||
|
||||
await waitForTx(
|
||||
await lendingPoolConfigurator.enableReserveAsCollateral(
|
||||
tokenAddress,
|
||||
baseLTVAsCollateral,
|
||||
liquidationThreshold,
|
||||
liquidationBonus
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(
|
||||
|
|
|
@ -41,7 +41,7 @@ export const increaseTime = async (secondsToIncrease: number) => {
|
|||
await BRE.ethers.provider.send('evm_mine', []);
|
||||
};
|
||||
|
||||
export const waitForTx = async (tx: ContractTransaction) => await tx.wait();
|
||||
export const waitForTx = async (tx: ContractTransaction) => await tx.wait(1);
|
||||
|
||||
export const filterMapBy = (raw: {[key: string]: any}, fn: (key: string) => boolean) =>
|
||||
Object.keys(raw)
|
||||
|
|
|
@ -30,7 +30,7 @@ export const setInitialMarketRatesInRatesOracle = async (
|
|||
const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[
|
||||
assetAddressIndex
|
||||
];
|
||||
await lendingRateOracleInstance.setMarketBorrowRate(assetAddress, borrowRate);
|
||||
await waitForTx(await lendingRateOracleInstance.setMarketBorrowRate(assetAddress, borrowRate));
|
||||
console.log('added Market Borrow Rate for: ', assetSymbol);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -108,6 +108,7 @@ export enum ProtocolErrors {
|
|||
|
||||
//require error messages - LendingPoolAddressesProviderRegistry
|
||||
PROVIDER_NOT_REGISTERED = '37', // 'Provider is not registered'
|
||||
INVALID_ADDRESSES_PROVIDER_ID = '68',
|
||||
|
||||
//return error messages - LendingPoolCollateralManager
|
||||
HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38', // 'Health factor is not below the threshold'
|
||||
|
|
134
package-lock.json
generated
134
package-lock.json
generated
|
@ -2094,9 +2094,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz",
|
||||
"integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==",
|
||||
"version": "6.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
|
||||
"integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/resolve": {
|
||||
|
@ -2889,12 +2889,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"buidler-gas-reporter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/buidler-gas-reporter/-/buidler-gas-reporter-0.1.3.tgz",
|
||||
"integrity": "sha512-3Q27K52iGEghJ4icDdkV/67iJiRCaiZ39E2LLCBNZgx5NvltI5Q7oR3RVyCGO/m3SZBcj418zC8p7yeyj/jFdw==",
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/buidler-gas-reporter/-/buidler-gas-reporter-0.1.4.tgz",
|
||||
"integrity": "sha512-objSu/tGggxKDmlpZViM9uEKRSo7vXxBsPv+vXegre1AWapJXQNfJPtBmrNvnT5Ixl8pecWSRXsfO95nJAn4yw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eth-gas-reporter": "^0.2.13"
|
||||
"eth-gas-reporter": "^0.2.18"
|
||||
}
|
||||
},
|
||||
"buidler-typechain": {
|
||||
|
@ -4108,13 +4108,13 @@
|
|||
}
|
||||
},
|
||||
"eth-gas-reporter": {
|
||||
"version": "0.2.17",
|
||||
"resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.17.tgz",
|
||||
"integrity": "sha512-MsrUqeXTAFU9QEdAIdaVu+QeU1XwFsKvPDEC68iheppVR5xUP11h4SyPhSRZiGfOzXr1CfTtPM/B6wPGtt7/LA==",
|
||||
"version": "0.2.18",
|
||||
"resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.18.tgz",
|
||||
"integrity": "sha512-P6LQ1QmU9bqU4zmd01Ws/b2EWAD5rT771U0wyJ/c+fKE6RdE9ks8KzjdR1zjosV2uilMfqVTtrBrXveCOnaTyQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@ethersproject/abi": "^5.0.0-beta.146",
|
||||
"@solidity-parser/parser": "^0.5.2",
|
||||
"@solidity-parser/parser": "^0.8.0",
|
||||
"cli-table3": "^0.5.0",
|
||||
"colors": "^1.1.2",
|
||||
"ethereumjs-util": "6.2.0",
|
||||
|
@ -4130,6 +4130,27 @@
|
|||
"sync-request": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@solidity-parser/parser": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.1.tgz",
|
||||
"integrity": "sha512-DF7H6T8I4lo2IZOE2NZwt3631T8j1gjpQLjmvY2xBNK50c4ltslR4XPKwT6RkeSd4+xCAK0GHC/k7sbRDBE4Yw==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
|
||||
"integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
"brorand": "^1.0.1",
|
||||
"hash.js": "^1.0.0",
|
||||
"hmac-drbg": "^1.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
"minimalistic-assert": "^1.0.0",
|
||||
"minimalistic-crypto-utils": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ethereumjs-util": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz",
|
||||
|
@ -4146,37 +4167,20 @@
|
|||
}
|
||||
},
|
||||
"ethers": {
|
||||
"version": "4.0.47",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.47.tgz",
|
||||
"integrity": "sha512-hssRYhngV4hiDNeZmVU/k5/E8xmLG8UpcNUzg6mb7lqhgpFPH/t7nuv20RjRrEf0gblzvi2XwR5Te+V3ZFc9pQ==",
|
||||
"version": "4.0.48",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz",
|
||||
"integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aes-js": "3.0.0",
|
||||
"bn.js": "^4.4.0",
|
||||
"elliptic": "6.5.2",
|
||||
"elliptic": "6.5.3",
|
||||
"hash.js": "1.1.3",
|
||||
"js-sha3": "0.5.7",
|
||||
"scrypt-js": "2.0.4",
|
||||
"setimmediate": "1.0.4",
|
||||
"uuid": "2.0.1",
|
||||
"xmlhttprequest": "1.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"elliptic": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz",
|
||||
"integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
"brorand": "^1.0.1",
|
||||
"hash.js": "^1.0.0",
|
||||
"hmac-drbg": "^1.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
"minimalistic-assert": "^1.0.0",
|
||||
"minimalistic-crypto-utils": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"hash.js": {
|
||||
|
@ -21040,18 +21044,16 @@
|
|||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "10.0.2",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz",
|
||||
"integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==",
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
|
||||
"integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/glob": "^7.1.1",
|
||||
"array-union": "^2.1.0",
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.0.3",
|
||||
"glob": "^7.1.3",
|
||||
"ignore": "^5.1.1",
|
||||
"merge2": "^1.2.3",
|
||||
"fast-glob": "^3.1.1",
|
||||
"ignore": "^5.1.4",
|
||||
"merge2": "^1.3.0",
|
||||
"slash": "^3.0.0"
|
||||
}
|
||||
},
|
||||
|
@ -21254,9 +21256,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.17.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.26.tgz",
|
||||
"integrity": "sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw==",
|
||||
"version": "10.17.43",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.43.tgz",
|
||||
"integrity": "sha512-F7xV2kxZGb3seVP3UQt3msHcoDCtDi8WNO/UCzNLhRwaYVT4yJO1ndcV+vCTnY+jiAVqyLZq/VJbRE/AhwqEag==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
@ -23738,21 +23740,29 @@
|
|||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
|
||||
"integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
|
||||
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.15"
|
||||
"lodash": "^4.17.19"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"request-promise-native": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz",
|
||||
"integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==",
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
|
||||
"integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"request-promise-core": "1.1.3",
|
||||
"request-promise-core": "1.1.4",
|
||||
"stealthy-require": "^1.1.1",
|
||||
"tough-cookie": "^2.3.3"
|
||||
}
|
||||
|
@ -24247,6 +24257,22 @@
|
|||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "10.0.2",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz",
|
||||
"integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/glob": "^7.1.1",
|
||||
"array-union": "^2.1.0",
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.0.3",
|
||||
"glob": "^7.1.3",
|
||||
"ignore": "^5.1.1",
|
||||
"merge2": "^1.2.3",
|
||||
"slash": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
|
||||
|
@ -24732,9 +24758,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "8.10.61",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz",
|
||||
"integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q==",
|
||||
"version": "8.10.65",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.65.tgz",
|
||||
"integrity": "sha512-xdcqtQl1g3p/49kmcj7ZixPWOcNHA1tYNz+uN0PJEcgtN6zywK74aacTnd3eFGPuBpD7kK8vowmMRkUt6jHU/Q==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"aave:evm:dev:migration": "buidler aave:dev",
|
||||
"aave:evm:full:migration": "buidler aave:full",
|
||||
"aave:kovan:dev:migration": "npm run buidler:kovan -- aave:dev --verify",
|
||||
"aave:kovan:full:migration": "npm run buidler:kovan -- aave:full",
|
||||
"aave:kovan:full:migration": "npm run buidler:kovan -- aave:full --verify",
|
||||
"aave:ropsten:dev:migration": "npm run buidler:ropsten -- aave:dev --verify",
|
||||
"aave:ropsten:full:migration": "npm run buidler:ropsten -- aave:full --verify",
|
||||
"aave:main:dev:migration": "npm run buidler:main -- aave:dev --verify",
|
||||
|
@ -59,7 +59,7 @@
|
|||
"@types/mocha": "7.0.2",
|
||||
"@types/node": "14.0.5",
|
||||
"bignumber.js": "9.0.0",
|
||||
"buidler-gas-reporter": "^0.1.3",
|
||||
"buidler-gas-reporter": "^0.1.4",
|
||||
"buidler-typechain": "0.1.1",
|
||||
"chai": "4.2.0",
|
||||
"chai-bignumber": "3.0.0",
|
||||
|
@ -68,6 +68,7 @@
|
|||
"ethereum-waffle": "3.0.2",
|
||||
"ethereumjs-util": "7.0.2",
|
||||
"ethers": "5.0.8",
|
||||
"globby": "^11.0.1",
|
||||
"husky": "^4.2.5",
|
||||
"lowdb": "1.0.0",
|
||||
"prettier": "^2.0.5",
|
||||
|
|
|
@ -18,6 +18,15 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => {
|
|||
);
|
||||
});
|
||||
|
||||
it('tries to register an addresses provider with id 0', async () => {
|
||||
const {users, registry} = testEnv;
|
||||
const {INVALID_ADDRESSES_PROVIDER_ID} = ProtocolErrors;
|
||||
|
||||
await expect(registry.registerAddressesProvider(users[2].address, '0')).to.be.revertedWith(
|
||||
INVALID_ADDRESSES_PROVIDER_ID
|
||||
);
|
||||
});
|
||||
|
||||
it('Registers a new mock addresses provider', async () => {
|
||||
const {users, registry} = testEnv;
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
await pool.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
ethers.utils.parseEther('0.8'),
|
||||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
0,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -77,8 +77,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
const reserveDataBefore = await helpersContract.getReserveData(weth.address);
|
||||
const txResult = await pool.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
'1000720000000000000',
|
||||
[weth.address],
|
||||
['1000720000000000000'],
|
||||
0,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -108,8 +108,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
.connect(caller.signer)
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
ethers.utils.parseEther('0.8'),
|
||||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
0,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -128,8 +128,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
.connect(caller.signer)
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
ethers.utils.parseEther('0.8'),
|
||||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
0,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -148,8 +148,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
.connect(caller.signer)
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
ethers.utils.parseEther('0.8'),
|
||||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
4,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -176,8 +176,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
.connect(caller.signer)
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
ethers.utils.parseEther('0.8'),
|
||||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
2,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -193,22 +193,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
const callerDebt = await wethDebtToken.balanceOf(caller.address);
|
||||
|
||||
expect(callerDebt.toString()).to.be.equal('800720000000000000', 'Invalid user debt');
|
||||
});
|
||||
|
||||
it('tries to take a very small flashloan, which would result in 0 fees (revert expected)', async () => {
|
||||
const {pool, weth} = testEnv;
|
||||
|
||||
await expect(
|
||||
pool.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
'1', //1 wei loan
|
||||
2,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).to.be.revertedWith(REQUESTED_AMOUNT_TOO_SMALL);
|
||||
expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt');
|
||||
});
|
||||
|
||||
it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => {
|
||||
|
@ -217,8 +202,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
await expect(
|
||||
pool.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
weth.address,
|
||||
'1004415000000000000', //slightly higher than the available liquidity
|
||||
[weth.address],
|
||||
['1004415000000000000'], //slightly higher than the available liquidity
|
||||
2,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -231,7 +216,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
const {pool, deployer, weth} = testEnv;
|
||||
|
||||
await expect(
|
||||
pool.flashLoan(deployer.address, weth.address, '1000000000000000000', 2, '0x10', '0')
|
||||
pool.flashLoan(deployer.address, [weth.address], ['1000000000000000000'], 2, '0x10', '0')
|
||||
).to.be.reverted;
|
||||
});
|
||||
|
||||
|
@ -257,8 +242,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
await pool.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
usdc.address,
|
||||
flashloanAmount,
|
||||
[usdc.address],
|
||||
[flashloanAmount],
|
||||
0,
|
||||
'0x10',
|
||||
'0'
|
||||
|
@ -297,7 +282,14 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
await expect(
|
||||
pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, usdc.address, flashloanAmount, 2, '0x10', '0')
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[usdc.address],
|
||||
[flashloanAmount],
|
||||
2,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).to.be.revertedWith(COLLATERAL_BALANCE_IS_0);
|
||||
});
|
||||
|
||||
|
@ -320,7 +312,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
await pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, usdc.address, flashloanAmount, 2, '0x10', '0');
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], 2, '0x10', '0');
|
||||
const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(
|
||||
usdc.address
|
||||
);
|
||||
|
@ -332,7 +324,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
const callerDebt = await usdcDebtToken.balanceOf(caller.address);
|
||||
|
||||
expect(callerDebt.toString()).to.be.equal('500450000', 'Invalid user debt');
|
||||
expect(callerDebt.toString()).to.be.equal('500000000', 'Invalid user debt');
|
||||
});
|
||||
|
||||
it('Caller deposits 1000 DAI as collateral, Takes a WETH flashloan with mode = 0, does not approve the transfer of the funds', async () => {
|
||||
|
@ -355,7 +347,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
await expect(
|
||||
pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, weth.address, flashAmount, 0, '0x10', '0')
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 0, '0x10', '0')
|
||||
).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL);
|
||||
});
|
||||
|
||||
|
@ -370,7 +362,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
await pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, weth.address, flashAmount, 1, '0x10', '0');
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0');
|
||||
|
||||
const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address);
|
||||
|
||||
|
@ -381,6 +373,6 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
const callerDebt = await wethDebtToken.balanceOf(caller.address);
|
||||
|
||||
expect(callerDebt.toString()).to.be.equal('800720000000000000', 'Invalid user debt');
|
||||
expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1153,11 +1153,12 @@ const calcLinearInterest = (
|
|||
currentTimestamp: BigNumber,
|
||||
lastUpdateTimestamp: BigNumber
|
||||
) => {
|
||||
const timeDifference = currentTimestamp.minus(lastUpdateTimestamp).wadToRay();
|
||||
const timeDifference = currentTimestamp.minus(lastUpdateTimestamp);
|
||||
|
||||
const timeDelta = timeDifference.rayDiv(new BigNumber(ONE_YEAR).wadToRay());
|
||||
|
||||
const cumulatedInterest = rate.rayMul(timeDelta).plus(RAY);
|
||||
const cumulatedInterest = rate
|
||||
.multipliedBy(timeDifference)
|
||||
.dividedBy(new BigNumber(ONE_YEAR))
|
||||
.plus(RAY);
|
||||
|
||||
return cumulatedInterest;
|
||||
};
|
||||
|
|
|
@ -186,7 +186,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
await expect(
|
||||
pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, weth.address, flashAmount, 1, '0x10', '0')
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0')
|
||||
).revertedWith(IS_PAUSED);
|
||||
|
||||
// Unpause pool
|
||||
|
|
Loading…
Reference in New Issue
Block a user