removal of TokenDistributor, FeeProvider and FlashLoanVars

This commit is contained in:
andyk 2020-08-19 18:56:51 +03:00
parent 7d23041849
commit d60f7b6272
16 changed files with 76 additions and 474 deletions

View File

@ -25,7 +25,6 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
event PriceOracleUpdated(address indexed newAddress);
event LendingRateOracleUpdated(address indexed newAddress);
event FeeProviderUpdated(address indexed newAddress);
event TokenDistributorUpdated(address indexed newAddress);
event ProxyCreated(bytes32 id, address indexed newAddress);
@ -146,15 +145,6 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
emit LendingRateOracleUpdated(lendingRateOracle);
}
function getTokenDistributor() external override view returns (address) {
return _addresses[TOKEN_DISTRIBUTOR];
}
function setTokenDistributor(address tokenDistributor) external override onlyOwner {
_addresses[TOKEN_DISTRIBUTOR] = tokenDistributor;
emit TokenDistributorUpdated(tokenDistributor);
}
/**
* @dev internal function to update the implementation of a specific component of the protocol
* @param id the id of the contract to be updated

View File

@ -1,55 +0,0 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
import '../libraries/openzeppelin-upgradeability/VersionedInitializable.sol';
import '../interfaces/IFeeProvider.sol';
import '../libraries/WadRayMath.sol';
/**
* @title FeeProvider contract
* @notice Implements calculation for the fees applied by the protocol
* @author Aave
**/
contract FeeProvider is IFeeProvider, VersionedInitializable {
using WadRayMath for uint256;
// percentage of the fee to be calculated on the loan amount
uint256 public originationFeePercentage;
uint256 public constant FEE_PROVIDER_REVISION = 0x1;
function getRevision() internal override pure returns (uint256) {
return FEE_PROVIDER_REVISION;
}
/**
* @dev initializes the FeeProvider after it's added to the proxy
* @param _addressesProvider the address of the LendingPoolAddressesProvider
*/
function initialize(address _addressesProvider) public initializer {
/// @notice origination fee is set as default as 25 basis points of the loan amount (0.0025%)
originationFeePercentage = 0.0025 * 1e18;
}
/**
* @dev calculates the origination fee for every loan executed on the platform.
* @param _user can be used in the future to apply discount to the origination fee based on the
* _user account (eg. stake AAVE tokens in the lending pool, or deposit > 1M USD etc.)
* @param _amount the amount of the loan
**/
function calculateLoanOriginationFee(address _user, uint256 _amount)
external
override
view
returns (uint256)
{
return _amount.wadMul(originationFeePercentage);
}
/**
* @dev returns the origination fee percentage
**/
function getLoanOriginationFeePercentage() external override view returns (uint256) {
return originationFeePercentage;
}
}

View File

@ -1,222 +0,0 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
import '@openzeppelin/contracts/math/SafeMath.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol';
import '@openzeppelin/contracts/utils/ReentrancyGuard.sol';
import '../libraries/openzeppelin-upgradeability/VersionedInitializable.sol';
import '../interfaces/IExchangeAdapter.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import {PercentageMath} from '../libraries/PercentageMath.sol';
/// @title TokenDistributor
/// @author Aave
/// @notice Receives tokens and manages the distribution amongst receivers
/// The usage is as follows:
/// - The distribution addresses and percentages are set up on construction
/// - The Kyber Proxy is approved for a list of tokens in construction, which will be later burnt
/// - At any moment, anyone can call distribute() with a list of token addresses in order to distribute
/// the accumulated token amounts and/or ETH in this contract to all the receivers with percentages
/// - If the address(0) is used as receiver, this contract will trade in Kyber to tokenToBurn (LEND)
/// and burn it (sending to address(0) the tokenToBurn)
contract TokenDistributor is ReentrancyGuard, VersionedInitializable {
using SafeMath for uint256;
using PercentageMath for uint256;
using SafeERC20 for IERC20;
struct Distribution {
address[] receivers;
uint256[] percentages;
}
event DistributionUpdated(address[] receivers, uint256[] percentages);
event Distributed(address receiver, uint256 percentage, uint256 amount);
event Setup(address tokenToBurn, IExchangeAdapter exchangeAdapter, address _recipientBurn);
event Burn(uint256 amount);
uint256 public constant IMPLEMENTATION_REVISION = 0x3;
/// @notice DEPRECATED
uint256 public constant MAX_UINT = 2**256 - 1;
/// @notice DEPRECATED
uint256 public constant MAX_UINT_MINUS_ONE = (2**256 - 1) - 1;
/// @notice DEPRECATED
uint256 public constant MIN_CONVERSION_RATE = 1;
/// @notice DEPRECATED
address public constant KYBER_ETH_MOCK_ADDRESS = address(
0x00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
);
/// @notice Defines how tokens and ETH are distributed on each call to .distribute()
Distribution private distribution;
/// @notice Instead of using 100 for percentages, higher base to have more precision in the distribution
uint256 public constant DISTRIBUTION_BASE = 10000;
/// @notice The address of the token to burn (LEND token)
address public tokenToBurn;
/// @notice Address to send tokens to "burn".
/// Because of limitations on OZ ERC20, on dev it's needed to use the 0x00000...1 address instead of address(0)
/// So this param needs to be received on construction
address public recipientBurn;
/// @notice Smart contract implementing the logic to interact with a particular exchange.
/// Will be called by DELEGATECALL
IExchangeAdapter public exchangeAdapter;
/// @notice Called by the proxy when setting this contract as implementation
function initialize(
address _recipientBurn,
address _tokenToBurn,
IExchangeAdapter _exchangeAdapter,
address[] memory _receivers,
uint256[] memory _percentages,
IERC20[] memory _tokens
) public initializer {
recipientBurn = _recipientBurn;
tokenToBurn = _tokenToBurn;
exchangeAdapter = _exchangeAdapter;
internalSetTokenDistribution(_receivers, _percentages);
approveExchange(_tokens);
emit Setup(_tokenToBurn, _exchangeAdapter, _recipientBurn);
}
/// @notice In order to receive ETH transfers
receive() external payable {}
/// @notice "Infinite" approval for all the tokens initialized
/// @param _tokens List of IERC20 to approve
function approveExchange(IERC20[] memory _tokens) public {
(bool _success, ) = address(exchangeAdapter).delegatecall(
abi.encodeWithSelector(exchangeAdapter.approveExchange.selector, _tokens)
);
}
/// @notice Distributes the whole balance of a list of _tokens balances in this contract
/// @param _tokens list of ERC20 tokens to distribute
function distribute(IERC20[] memory _tokens) public {
for (uint256 i = 0; i < _tokens.length; i++) {
uint256 _balanceToDistribute = _tokens[i].balanceOf(address(this));
if (_balanceToDistribute <= 0) {
continue;
}
internalDistributeTokenWithAmount(_tokens[i], _balanceToDistribute);
}
}
/// @notice Distributes specific amounts of a list of _tokens
/// @param _tokens list of ERC20 tokens to distribute
/// @param _amounts list of amounts to distribute per token
function distributeWithAmounts(IERC20[] memory _tokens, uint256[] memory _amounts) public {
for (uint256 i = 0; i < _tokens.length; i++) {
internalDistributeTokenWithAmount(_tokens[i], _amounts[i]);
}
}
/// @notice Distributes specific total balance's percentages of a list of _tokens
/// @param _tokens list of ERC20 tokens to distribute
/// @param _percentages list of percentages to distribute per token
function distributeWithPercentages(IERC20[] memory _tokens, uint256[] memory _percentages)
public
{
for (uint256 i = 0; i < _tokens.length; i++) {
uint256 _amountToDistribute = _tokens[i].balanceOf(address(this)).percentMul(
_percentages[i]
);
if (_amountToDistribute <= 0) {
continue;
}
internalDistributeTokenWithAmount(_tokens[i], _amountToDistribute);
}
}
/// @notice Sets _receivers addresses with _percentages for each one
/// @param _receivers Array of addresses receiving a percentage of the distribution, both user addresses
/// or contracts
/// @param _percentages Array of percentages each _receivers member will get
function internalSetTokenDistribution(address[] memory _receivers, uint256[] memory _percentages)
internal
{
require(_receivers.length == _percentages.length, 'Array lengths should be equal');
distribution = Distribution({receivers: _receivers, percentages: _percentages});
emit DistributionUpdated(_receivers, _percentages);
}
/// @notice Distributes a specific amount of a token owned by this contract
/// @param _token The ERC20 token to distribute
/// @param _amountToDistribute The specific amount to distribute
function internalDistributeTokenWithAmount(IERC20 _token, uint256 _amountToDistribute) internal {
address _tokenAddress = address(_token);
Distribution memory _distribution = distribution;
for (uint256 j = 0; j < _distribution.receivers.length; j++) {
uint256 _amount = _amountToDistribute.mul(_distribution.percentages[j]).div(
DISTRIBUTION_BASE
);
//avoid transfers/burns of 0 tokens
if (_amount == 0) {
continue;
}
if (_distribution.receivers[j] != address(0)) {
_token.safeTransfer(_distribution.receivers[j], _amount);
emit Distributed(_distribution.receivers[j], _distribution.percentages[j], _amount);
} else {
uint256 _amountToBurn = _amount;
// If the token to burn is already tokenToBurn, we don't trade, burning directly
if (_tokenAddress != tokenToBurn) {
(bool _success, bytes memory _result) = address(exchangeAdapter).delegatecall(
abi.encodeWithSelector(
exchangeAdapter.exchange.selector,
_tokenAddress,
tokenToBurn,
_amount,
10
)
);
require(_success, 'ERROR_ON_EXCHANGE');
_amountToBurn = abi.decode(_result, (uint256));
}
_burn(_amountToBurn);
}
}
}
/// @notice Internal function to send _amount of tokenToBurn to the 0x0 address
/// @param _amount The amount to burn
function _burn(uint256 _amount) internal {
require(
IERC20(tokenToBurn).transfer(recipientBurn, _amount),
'INTERNAL_BURN. Reverted transfer to recipientBurn address'
);
emit Burn(_amount);
}
/// @notice Returns the receivers and percentages of the contract Distribution
/// @return receivers array of addresses and percentages array on uints
function getDistribution()
public
view
returns (address[] memory receivers, uint256[] memory percentages)
{
receivers = distribution.receivers;
percentages = distribution.percentages;
}
/// @notice Gets the revision number of the contract
/// @return The revision numeric reference
function getRevision() internal override pure returns (uint256) {
return IMPLEMENTATION_REVISION;
}
}

View File

@ -1,16 +0,0 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
/**
* @title IFeeProvider interface
* @notice Interface for the Aave fee provider.
**/
interface IFeeProvider {
function calculateLoanOriginationFee(address _user, uint256 _amount)
external
view
returns (uint256);
function getLoanOriginationFeePercentage() external view returns (uint256);
}

View File

@ -15,10 +15,6 @@ interface ILendingPoolAddressesProvider {
function setLendingPoolConfiguratorImpl(address configurator) external;
function getTokenDistributor() external view returns (address);
function setTokenDistributor(address tokenDistributor) external;
function getFeeProvider() external view returns (address);
function setFeeProviderImpl(address feeProvider) external;

View File

@ -20,7 +20,6 @@ import '../libraries/UserConfiguration.sol';
import '../tokenization/interfaces/IStableDebtToken.sol';
import '../tokenization/interfaces/IVariableDebtToken.sol';
import '../interfaces/IFeeProvider.sol';
import '../flashloan/interfaces/IFlashLoanReceiver.sol';
import './LendingPoolLiquidationManager.sol';
import '../interfaces/IPriceOracleGetter.sol';
@ -45,10 +44,8 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
uint256 private constant REBALANCE_DOWN_RATE_DELTA = (1e27) / 5;
uint256 private constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 25;
uint256 private constant FLASHLOAN_FEE_TOTAL = 9;
uint256 private constant FLASHLOAN_FEE_PROTOCOL = 3000;
LendingPoolAddressesProvider public addressesProvider;
IFeeProvider feeProvider;
using SafeERC20 for IERC20;
mapping(address => ReserveLogic.ReserveData) internal reserves;
@ -162,7 +159,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
* @param _reserve the address of the reserve
* @param _amount the amount requested
* @param _totalFee the total fee on the amount
* @param _protocolFee the part of the fee for the protocol
* @param _timestamp the timestamp of the action
**/
event FlashLoan(
@ -170,7 +166,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
address indexed _reserve,
uint256 _amount,
uint256 _totalFee,
uint256 _protocolFee,
uint256 _timestamp
);
@ -246,7 +241,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
**/
function initialize(LendingPoolAddressesProvider _addressesProvider) public initializer {
addressesProvider = _addressesProvider;
feeProvider = IFeeProvider(addressesProvider.getFeeProvider());
}
/**
@ -265,7 +259,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
ValidationLogic.validateDeposit(reserve, _amount);
AToken aToken = AToken(payable(reserve.aTokenAddress));
AToken aToken = AToken(reserve.aTokenAddress);
bool isFirstDeposit = aToken.balanceOf(msg.sender) == 0;
@ -646,15 +640,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
}
}
struct FlashLoanLocalVars {
uint256 availableLiquidityBefore;
uint256 totalFeeBips;
uint256 protocolFeeBips;
uint256 amountFee;
uint256 protocolFee;
address payable aTokenAddress;
}
/**
* @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
@ -669,29 +654,21 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
uint256 _amount,
bytes memory _params
) public nonReentrant {
FlashLoanLocalVars memory vars;
ReserveLogic.ReserveData storage reserve = reserves[_reserve];
vars.aTokenAddress = payable(reserve.aTokenAddress);
address payable aTokenAddress = payable(reserve.aTokenAddress);
//check that the reserve has enough available liquidity
vars.availableLiquidityBefore = IERC20(_reserve).balanceOf(vars.aTokenAddress);
uint256 availableLiquidityBefore = IERC20(_reserve).balanceOf(aTokenAddress);
//calculate amount fee
vars.amountFee = _amount.mul(FLASHLOAN_FEE_TOTAL).div(10000);
//protocol fee is the part of the amountFee reserved for the protocol - the rest goes to depositors
vars.protocolFee = vars.amountFee.mul(FLASHLOAN_FEE_PROTOCOL).div(10000);
uint256 amountFee = _amount.mul(FLASHLOAN_FEE_TOTAL).div(10000);
require(
vars.availableLiquidityBefore >= _amount,
availableLiquidityBefore >= _amount,
'There is not enough liquidity available to borrow'
);
require(
vars.amountFee > 0 && vars.protocolFee > 0,
'The requested amount is too small for a FlashLoan.'
);
require(amountFee > 0, 'The requested amount is too small for a FlashLoan.');
//get the FlashLoanReceiver instance
IFlashLoanReceiver receiver = IFlashLoanReceiver(_receiver);
@ -699,34 +676,23 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
address payable userPayable = address(uint160(_receiver));
//transfer funds to the receiver
AToken(vars.aTokenAddress).transferUnderlyingTo(userPayable, _amount);
AToken(aTokenAddress).transferUnderlyingTo(userPayable, _amount);
//execute action of the receiver
receiver.executeOperation(_reserve, vars.aTokenAddress, _amount, vars.amountFee, _params);
receiver.executeOperation(_reserve, aTokenAddress, _amount, amountFee, _params);
//check that the actual balance of the core contract includes the returned amount
uint256 availableLiquidityAfter = IERC20(_reserve).balanceOf(vars.aTokenAddress);
uint256 availableLiquidityAfter = IERC20(_reserve).balanceOf(aTokenAddress);
require(
availableLiquidityAfter == vars.availableLiquidityBefore.add(vars.amountFee),
availableLiquidityAfter == availableLiquidityBefore.add(amountFee),
'The actual balance of the protocol is inconsistent'
);
reserve.updateStateOnFlashLoan(
_reserve,
vars.availableLiquidityBefore,
vars.amountFee.sub(vars.protocolFee),
vars.protocolFee
);
//transfer funds to the receiver
AToken(vars.aTokenAddress).transferUnderlyingTo(
addressesProvider.getTokenDistributor(),
vars.protocolFee
);
reserve.updateStateOnFlashLoan(_reserve, availableLiquidityBefore, amountFee);
//solium-disable-next-line
emit FlashLoan(_receiver, _reserve, _amount, vars.amountFee, vars.protocolFee, block.timestamp);
emit FlashLoan(_receiver, _reserve, _amount, amountFee, block.timestamp);
}
/**

View File

@ -39,7 +39,6 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
using UserConfiguration for UserConfiguration.Map;
LendingPoolAddressesProvider public addressesProvider;
IFeeProvider feeProvider;
mapping(address => ReserveLogic.ReserveData) internal reserves;
mapping(address => UserConfiguration.Map) internal usersConfig;

View File

@ -11,7 +11,6 @@ import {UserConfiguration} from './UserConfiguration.sol';
import {WadRayMath} from './WadRayMath.sol';
import {PercentageMath} from './PercentageMath.sol';
import '../interfaces/IPriceOracleGetter.sol';
import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
import '@nomiclabs/buidler/console.sol';
/**
@ -60,8 +59,10 @@ library GenericLogic {
address[] calldata _reserves,
address _oracle
) external view returns (bool) {
if (!_userConfig.isBorrowingAny() || !_userConfig.isUsingAsCollateral(_reservesData[_reserve].index)) {
if (
!_userConfig.isBorrowingAny() ||
!_userConfig.isUsingAsCollateral(_reservesData[_reserve].index)
) {
return true;
}

View File

@ -8,7 +8,6 @@ import {ReserveLogic} from './ReserveLogic.sol';
import {WadRayMath} from './WadRayMath.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
/**
* @title ReserveConfiguration library

View File

@ -5,7 +5,7 @@ import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {MathUtils} from './MathUtils.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
import {ReserveConfiguration} from './ReserveConfiguration.sol';
@ -227,8 +227,7 @@ library ReserveLogic {
ReserveData storage _reserve,
address _reserveAddress,
uint256 _availableLiquidityBefore,
uint256 _income,
uint256 _protocolFee
uint256 _income
) external {
//compounding the cumulated interest
_reserve.updateCumulativeIndexesAndTimestamp();
@ -252,8 +251,7 @@ library ReserveLogic {
view
returns (uint256)
{
return
IERC20(_reserveAddress).balanceOf(address(this)).add(_reserve.getTotalBorrows());
return IERC20(_reserveAddress).balanceOf(address(this)).add(_reserve.getTotalBorrows());
}
/**

View File

@ -5,7 +5,6 @@ import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {WadRayMath} from './WadRayMath.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
/**
* @title UserConfiguration library
@ -20,39 +19,43 @@ library UserConfiguration {
}
/**
* @dev sets if the user is borrowing the reserve identified by _reserveIndex
* @param _self the configuration object
* @param _reserveIndex the index of the reserve in the bitmap
* @param _borrowing true if the user is borrowing the reserve, false otherwise
**/
* @dev sets if the user is borrowing the reserve identified by _reserveIndex
* @param _self the configuration object
* @param _reserveIndex the index of the reserve in the bitmap
* @param _borrowing true if the user is borrowing the reserve, false otherwise
**/
function setBorrowing(
UserConfiguration.Map storage _self,
uint256 _reserveIndex,
bool _borrowing
) internal {
_self.data = (_self.data & ~(1 << _reserveIndex*2)) | uint256(_borrowing ? 1 : 0) << (_reserveIndex * 2);
_self.data =
(_self.data & ~(1 << (_reserveIndex * 2))) |
(uint256(_borrowing ? 1 : 0) << (_reserveIndex * 2));
}
/**
* @dev sets if the user is using as collateral the reserve identified by _reserveIndex
* @param _self the configuration object
* @param _reserveIndex the index of the reserve in the bitmap
* @param _usingAsCollateral true if the user is usin the reserve as collateral, false otherwise
**/
* @dev sets if the user is using as collateral the reserve identified by _reserveIndex
* @param _self the configuration object
* @param _reserveIndex the index of the reserve in the bitmap
* @param _usingAsCollateral true if the user is usin the reserve as collateral, false otherwise
**/
function setUsingAsCollateral(
UserConfiguration.Map storage _self,
uint256 _reserveIndex,
bool _usingAsCollateral
) internal {
_self.data = (_self.data & ~(1 << _reserveIndex*2+1)) | uint256(_usingAsCollateral ? 1 : 0) << (_reserveIndex * 2 + 1);
_self.data =
(_self.data & ~(1 << (_reserveIndex * 2 + 1))) |
(uint256(_usingAsCollateral ? 1 : 0) << (_reserveIndex * 2 + 1));
}
/**
* @dev used to validate if a user has been using the reserve for borrowing or as collateral
* @param _self the configuration object
* @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
**/
* @dev used to validate if a user has been using the reserve for borrowing or as collateral
* @param _self the configuration object
* @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)
internal
view
@ -62,11 +65,11 @@ library UserConfiguration {
}
/**
* @dev used to validate if a user has been using the reserve for borrowing
* @param _self the configuration object
* @param _reserveIndex the index of the reserve in the bitmap
* @return true if the user has been using a reserve for borrowing, false otherwise
**/
* @dev used to validate if a user has been using the reserve for borrowing
* @param _self the configuration object
* @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)
internal
view
@ -76,11 +79,11 @@ library UserConfiguration {
}
/**
* @dev used to validate if a user has been using the reserve as collateral
* @param _self the configuration object
* @param _reserveIndex the index of the reserve in the bitmap
* @return true if the user has been using a reserve as collateral, false otherwise
**/
* @dev used to validate if a user has been using the reserve as collateral
* @param _self the configuration object
* @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)
internal
view
@ -90,20 +93,20 @@ library UserConfiguration {
}
/**
* @dev used to validate if a user has been borrowing from any reserve
* @param _self the configuration object
* @return true if the user has been borrowing any reserve, false otherwise
**/
* @dev used to validate if a user has been borrowing from any reserve
* @param _self the configuration object
* @return true if the user has been borrowing any reserve, false otherwise
**/
function isBorrowingAny(UserConfiguration.Map memory _self) internal view returns (bool) {
return _self.data & BORROWING_MASK != 0;
}
/**
* @dev used to validate if a user has not been using any reserve
* @param _self the configuration object
* @return true if the user has been borrowing any reserve, false otherwise
**/
function isEmpty(UserConfiguration.Map memory _self) internal view returns(bool) {
* @dev used to validate if a user has not been using any reserve
* @param _self the configuration object
* @return true if the user has been borrowing any reserve, false otherwise
**/
function isEmpty(UserConfiguration.Map memory _self) internal view returns (bool) {
return _self.data == 0;
}
}

View File

@ -13,7 +13,6 @@ import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import {ReserveConfiguration} from './ReserveConfiguration.sol';
import {UserConfiguration} from './UserConfiguration.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
import '@nomiclabs/buidler/console.sol';
/**

View File

@ -146,7 +146,8 @@
},
"TokenDistributor": {
"buidlerevm": {
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4"
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4"
@ -164,7 +165,7 @@
},
"MockFlashLoanReceiver": {
"buidlerevm": {
"address": "0x3bDA11B584dDff7F66E0cFe1da1562c92B45db60"
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10"
},
"localhost": {
"address": "0x3bDA11B584dDff7F66E0cFe1da1562c92B45db60"
@ -172,7 +173,7 @@
},
"WalletBalanceProvider": {
"buidlerevm": {
"address": "0x392E5355a0e88Bd394F717227c752670fb3a8020",
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -412,7 +413,7 @@
},
"AaveProtocolTestHelpers": {
"buidlerevm": {
"address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460"
"address": "0xC6bA6049F86d528698B5924B8fC2FE7289D38578"
},
"localhost": {
"address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460"
@ -450,7 +451,7 @@
},
"MockAToken": {
"buidlerevm": {
"address": "0xD4B5A49d5bA242572ec3f4A8E52B97a10AF2543a",
"address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -470,7 +471,7 @@
},
"MockStableDebtToken": {
"buidlerevm": {
"address": "0x6aaF7e94e099291a94ed8E245c90f4766CE9bB7C",
"address": "0xEBAB67ee3ef604D5c250A53b4b8fcbBC6ec3007C",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {
@ -480,7 +481,7 @@
},
"MockVariableDebtToken": {
"buidlerevm": {
"address": "0x40A939911b662656C0EE71c19B954DB1911Dc8e3",
"address": "0xBE36BE5680244Ae1A6F983E4A6f6E1c142cdAbe3",
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
},
"localhost": {

View File

@ -23,7 +23,6 @@ import {MockAggregator} from '../types/MockAggregator';
import {LendingRateOracle} from '../types/LendingRateOracle';
import {DefaultReserveInterestRateStrategy} from '../types/DefaultReserveInterestRateStrategy';
import {LendingPoolLiquidationManager} from '../types/LendingPoolLiquidationManager';
import {TokenDistributor} from '../types/TokenDistributor';
import {InitializableAdminUpgradeabilityProxy} from '../types/InitializableAdminUpgradeabilityProxy';
import {MockFlashLoanReceiver} from '../types/MockFlashLoanReceiver';
import {WalletBalanceProvider} from '../types/WalletBalanceProvider';
@ -206,9 +205,6 @@ export const deployLendingPoolLiquidationManager = async () => {
return (await liquidationManager.deployed()) as LendingPoolLiquidationManager;
};
export const deployTokenDistributor = async () =>
await deployContract<TokenDistributor>(eContractid.TokenDistributor, []);
export const deployInitializableAdminUpgradeabilityProxy = async () =>
await deployContract<InitializableAdminUpgradeabilityProxy>(
eContractid.InitializableAdminUpgradeabilityProxy,
@ -402,14 +398,6 @@ export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => {
);
};
export const getTokenDistributor = async (address?: tEthereumAddress) => {
return await getContract<TokenDistributor>(
eContractid.TokenDistributor,
address ||
(await getDb().get(`${eContractid.TokenDistributor}.${BRE.network.name}`).value()).address
);
};
export const getLendingRateOracle = async (address?: tEthereumAddress) => {
return await getContract<LendingRateOracle>(
eContractid.LendingRateOracle,

View File

@ -14,8 +14,6 @@ import {
deployLendingRateOracle,
deployDefaultReserveInterestRateStrategy,
deployLendingPoolLiquidationManager,
deployTokenDistributor,
deployInitializableAdminUpgradeabilityProxy,
deployMockFlashLoanReceiver,
deployWalletBalancerProvider,
getFeeProvider,
@ -29,7 +27,7 @@ import {
deployGenericAToken,
} from '../helpers/contracts-helpers';
import {LendingPoolAddressesProvider} from '../types/LendingPoolAddressesProvider';
import {Wallet, ContractTransaction, ethers, Signer} from 'ethers';
import {ContractTransaction, Signer} from 'ethers';
import {
TokenContractId,
eContractid,
@ -62,7 +60,7 @@ import path from 'path';
import fs from 'fs';
['misc'].forEach((folder) => {
const tasksPath = path.join('/src/', 'tasks', folder);
const tasksPath = path.join(__dirname, '../', 'tasks', folder);
fs.readdirSync(tasksPath).forEach((task) => require(`${tasksPath}/${task}`));
});
@ -509,29 +507,6 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
await addressesProvider.setLendingPoolLiquidationManager(liquidationManager.address)
);
const {receivers, percentages} = getFeeDistributionParamsCommon(lendingPoolManager);
const tokenDistributorImpl = await deployTokenDistributor();
const tokenDistributorProxy = await deployInitializableAdminUpgradeabilityProxy();
const implementationParams = tokenDistributorImpl.interface.encodeFunctionData('initialize', [
ZERO_ADDRESS,
tokensAddressesWithoutUsd.LEND,
'0x0000000000000000000000000000000000000000', // TODO: finish removal
receivers,
percentages,
Object.values(tokensAddressesWithoutUsd),
]);
await waitForTx(
await tokenDistributorProxy['initialize(address,address,bytes)'](
tokenDistributorImpl.address,
await secondaryWallet.getAddress(),
implementationParams
)
);
await waitForTx(await addressesProvider.setTokenDistributor(tokenDistributorProxy.address));
await insertContractAddressInDb(eContractid.TokenDistributor, tokenDistributorProxy.address);
const mockFlashLoanReceiver = await deployMockFlashLoanReceiver(addressesProvider.address);
await insertContractAddressInDb(eContractid.MockFlashLoanReceiver, mockFlashLoanReceiver.address);

View File

@ -1,14 +1,8 @@
import {TestEnv, makeSuite} from './helpers/make-suite';
import {APPROVAL_AMOUNT_LENDING_POOL, oneRay} from '../helpers/constants';
import {
convertToCurrencyDecimals,
getMockFlashLoanReceiver,
getTokenDistributor,
} from '../helpers/contracts-helpers';
import {convertToCurrencyDecimals, getMockFlashLoanReceiver} from '../helpers/contracts-helpers';
import {ethers} from 'ethers';
import {MockFlashLoanReceiver} from '../types/MockFlashLoanReceiver';
import {TokenDistributor} from '../types/TokenDistributor';
import {BRE} from '../helpers/misc-utils';
import {ProtocolErrors} from '../helpers/types';
import BigNumber from 'bignumber.js';
@ -16,7 +10,6 @@ const {expect} = require('chai');
makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver;
let _tokenDistributor = {} as TokenDistributor;
const {
INCONSISTENT_PROTOCOL_BALANCE,
TOO_SMALL_FLASH_LOAN,
@ -25,7 +18,6 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
before(async () => {
_mockFlashLoanReceiver = await getMockFlashLoanReceiver();
_tokenDistributor = await getTokenDistributor();
});
it('Deposits ETH into the reserve', async () => {
@ -60,16 +52,13 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
.plus(reserveData.totalBorrowsStable.toString())
.plus(reserveData.totalBorrowsVariable.toString());
const tokenDistributorBalance = await weth.balanceOf(_tokenDistributor.address);
expect(totalLiquidity.toString()).to.be.equal('1000504000000000000');
expect(totalLiquidity.toString()).to.be.equal('1000720000000000000');
expect(currentLiquidityRate.toString()).to.be.equal('0');
expect(currentLiquidityIndex.toString()).to.be.equal('1000504000000000000000000000');
expect(tokenDistributorBalance).to.be.equal('216000000000000');
expect(currentLiquidityIndex.toString()).to.be.equal('1000720000000000000000000000');
});
it('Takes an ETH flashloan as big as the available liquidity', async () => {
const {pool, deployer, weth} = testEnv;
const {pool, weth} = testEnv;
const txResult = await pool.flashLoan(
_mockFlashLoanReceiver.address,
@ -79,7 +68,6 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
);
const reserveData = await pool.getReserveData(weth.address);
const tokenDistributorBalance = await weth.balanceOf(_tokenDistributor.address);
const currentLiqudityRate = reserveData.liquidityRate;
const currentLiquidityIndex = reserveData.liquidityIndex;
@ -88,10 +76,9 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
.plus(reserveData.totalBorrowsStable.toString())
.plus(reserveData.totalBorrowsVariable.toString());
expect(totalLiquidity.toString()).to.be.equal('1001134317520000000');
expect(totalLiquidity.toString()).to.be.equal('1001620454000000000');
expect(currentLiqudityRate.toString()).to.be.equal('0');
expect(currentLiquidityIndex.toString()).to.be.equal('1001134317520000000000000000');
expect(tokenDistributorBalance.toString()).to.be.equal('486136080000000');
});
it('Takes WETH flashloan, does not return the funds (revert expected)', async () => {
@ -180,22 +167,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
const currentLiquidityIndex = reserveData.liquidityIndex.toString();
const currentUserBalance = userData.currentATokenBalance.toString();
const expectedLiquidity = ethers.utils.parseEther('1000.315');
const tokenDistributorBalance = await dai.balanceOf(_tokenDistributor.address);
const expectedLiquidity = ethers.utils.parseEther('1000.450');
expect(totalLiquidity).to.be.equal(expectedLiquidity, 'Invalid total liquidity');
expect(currentLiqudityRate).to.be.equal('0', 'Invalid liquidity rate');
expect(currentLiquidityIndex).to.be.equal(
new BigNumber('1.000315').multipliedBy(oneRay).toFixed(),
new BigNumber('1.00045').multipliedBy(oneRay).toFixed(),
'Invalid liquidity index'
);
expect(currentUserBalance.toString()).to.be.equal(expectedLiquidity, 'Invalid user balance');
expect(tokenDistributorBalance.toString()).to.be.equal(
ethers.utils.parseEther('0.135'),
'Invalid token distributor balance'
);
});
it('Takes out a 500 DAI flashloan, does not return the funds (revert expected)', async () => {