Merge branch 'master' into fix/23

This commit is contained in:
emilio 2020-09-02 17:41:01 +02:00
commit cf39045573
7 changed files with 173 additions and 245 deletions

View File

@ -11,7 +11,7 @@ interface IReserveInterestRateStrategy {
* @dev returns the base variable borrow rate, in rays * @dev returns the base variable borrow rate, in rays
*/ */
function getBaseVariableBorrowRate() external view returns (uint256); function baseVariableBorrowRate() external view returns (uint256);
/** /**
* @dev calculates the liquidity, stable, and variable rates depending on the current utilization rate * @dev calculates the liquidity, stable, and variable rates depending on the current utilization rate

View File

@ -69,23 +69,23 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
* @dev accessors * @dev accessors
*/ */
function getVariableRateSlope1() external view returns (uint256) { function variableRateSlope1() external view returns (uint256) {
return _variableRateSlope1; return _variableRateSlope1;
} }
function getVariableRateSlope2() external view returns (uint256) { function variableRateSlope2() external view returns (uint256) {
return _variableRateSlope2; return _variableRateSlope2;
} }
function getStableRateSlope1() external view returns (uint256) { function stableRateSlope1() external view returns (uint256) {
return _stableRateSlope1; return _stableRateSlope1;
} }
function getStableRateSlope2() external view returns (uint256) { function stableRateSlope2() external view returns (uint256) {
return _stableRateSlope2; return _stableRateSlope2;
} }
function getBaseVariableBorrowRate() external override view returns (uint256) { function baseVariableBorrowRate() external override view returns (uint256) {
return _baseVariableBorrowRate; return _baseVariableBorrowRate;
} }
@ -121,7 +121,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
uint256 currentStableBorrowRate = 0; uint256 currentStableBorrowRate = 0;
uint256 currentLiquidityRate = 0; uint256 currentLiquidityRate = 0;
uint256 utilizationRate = (totalBorrows == 0 && availableLiquidity == 0) uint256 utilizationRate = totalBorrows == 0
? 0 ? 0
: totalBorrows.rayDiv(availableLiquidity.add(totalBorrows)); : totalBorrows.rayDiv(availableLiquidity.add(totalBorrows));
@ -157,9 +157,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
) )
.rayMul(utilizationRate); .rayMul(utilizationRate);
return (currentLiquidityRate, return (currentLiquidityRate, currentStableBorrowRate, currentVariableBorrowRate);
currentStableBorrowRate,
currentVariableBorrowRate);
} }
/** /**

View File

@ -43,18 +43,18 @@ contract LendingPool is VersionedInitializable, ILendingPool {
uint256 public constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 25; uint256 public constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 25;
uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9; uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9;
ILendingPoolAddressesProvider internal addressesProvider; ILendingPoolAddressesProvider internal _addressesProvider;
mapping(address => ReserveLogic.ReserveData) internal _reserves; mapping(address => ReserveLogic.ReserveData) internal _reserves;
mapping(address => UserConfiguration.Map) internal _usersConfig; mapping(address => UserConfiguration.Map) internal _usersConfig;
address[] internal reservesList; address[] internal _reservesList;
/** /**
* @dev only lending pools configurator can use functions affected by this modifier * @dev only lending pools configurator can use functions affected by this modifier
**/ **/
modifier onlyLendingPoolConfigurator { modifier onlyLendingPoolConfigurator {
require(addressesProvider.getLendingPoolConfigurator() == msg.sender, '30'); require(_addressesProvider.getLendingPoolConfigurator() == msg.sender, '30');
_; _;
} }
@ -72,7 +72,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
* @param provider the address of the LendingPoolAddressesProvider registry * @param provider the address of the LendingPoolAddressesProvider registry
**/ **/
function initialize(ILendingPoolAddressesProvider provider) public initializer { function initialize(ILendingPoolAddressesProvider provider) public initializer {
addressesProvider = provider; _addressesProvider = provider;
} }
/** /**
@ -91,37 +91,36 @@ contract LendingPool is VersionedInitializable, ILendingPool {
ValidationLogic.validateDeposit(reserve, amount); ValidationLogic.validateDeposit(reserve, amount);
IAToken aToken = IAToken(reserve.aTokenAddress); address aToken = reserve.aTokenAddress;
bool isFirstDeposit = aToken.balanceOf(msg.sender) == 0;
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
reserve.updateInterestRates(asset, amount, 0); reserve.updateInterestRates(asset, aToken, amount, 0);
bool isFirstDeposit = IAToken(aToken).balanceOf(msg.sender) == 0;
if (isFirstDeposit) { if (isFirstDeposit) {
_usersConfig[msg.sender].setUsingAsCollateral(reserve.index, true); _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, true);
} }
//minting AToken to user 1:1 with the specific exchange rate //minting AToken to user 1:1 with the specific exchange rate
aToken.mint(msg.sender, amount); IAToken(aToken).mint(msg.sender, amount);
//transfer to the aToken contract //transfer to the aToken contract
IERC20(asset).safeTransferFrom(msg.sender, address(aToken), amount); IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);
emit Deposit(asset, msg.sender, amount, referralCode); emit Deposit(asset, msg.sender, amount, referralCode);
} }
/** /**
* @dev withdraws the _reserves of _user. * @dev withdraws the _reserves of user.
* @param asset the address of the reserve * @param asset the address of the reserve
* @param amount the underlying amount to be redeemed * @param amount the underlying amount to be redeemed
**/ **/
function withdraw(address asset, uint256 amount) external override { function withdraw(address asset, uint256 amount) external override {
ReserveLogic.ReserveData storage reserve = _reserves[asset]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
IAToken aToken = IAToken(reserve.aTokenAddress); address aToken = reserve.aTokenAddress;
uint256 userBalance = aToken.balanceOf(msg.sender); uint256 userBalance = IAToken(aToken).balanceOf(msg.sender);
uint256 amountToWithdraw = amount; uint256 amountToWithdraw = amount;
@ -132,24 +131,24 @@ contract LendingPool is VersionedInitializable, ILendingPool {
ValidationLogic.validateWithdraw( ValidationLogic.validateWithdraw(
asset, asset,
address(aToken), aToken,
amountToWithdraw, amountToWithdraw,
userBalance, userBalance,
_reserves, _reserves,
_usersConfig[msg.sender], _usersConfig[msg.sender],
reservesList, _reservesList,
addressesProvider.getPriceOracle() _addressesProvider.getPriceOracle()
); );
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
reserve.updateInterestRates(asset, 0, amountToWithdraw); reserve.updateInterestRates(asset, aToken, 0, amountToWithdraw);
if (amountToWithdraw == userBalance) { if (amountToWithdraw == userBalance) {
_usersConfig[msg.sender].setUsingAsCollateral(reserve.index, false); _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, false);
} }
aToken.burn(msg.sender, msg.sender, amountToWithdraw); IAToken(aToken).burn(msg.sender, msg.sender, amountToWithdraw);
emit Withdraw(asset, msg.sender, amount); emit Withdraw(asset, msg.sender, amount);
} }
@ -220,15 +219,17 @@ contract LendingPool is VersionedInitializable, ILendingPool {
IVariableDebtToken(reserve.variableDebtTokenAddress).mint(vars.user, vars.amount); IVariableDebtToken(reserve.variableDebtTokenAddress).mint(vars.user, vars.amount);
} }
reserve.updateInterestRates(vars.asset, 0, (vars.releaseUnderlying) ? vars.amount : 0); address aToken = reserve.aTokenAddress;
reserve.updateInterestRates(asset, aToken, 0, amount);
if (!userConfig.isBorrowing(reserve.index)) { uint256 reserveIndex = reserve.index;
userConfig.setBorrowing(reserve.index, true); if (!userConfig.isBorrowing(reserveIndex)) {
userConfig.setBorrowing(reserveIndex, true);
} }
//if we reached this point and we need to, we can transfer //if we reached this point and we need to, we can transfer
if (vars.releaseUnderlying) { if (vars.releaseUnderlying) {
IAToken(reserve.aTokenAddress).transferUnderlyingTo(vars.user, vars.amount); IAToken(aToken).transferUnderlyingTo(vars.user, vars.amount);
} }
emit Borrow( emit Borrow(
@ -245,26 +246,26 @@ contract LendingPool is VersionedInitializable, ILendingPool {
/** /**
* @notice repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified). * @notice repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
* @dev the target user is defined by _onBehalfOf. If there is no repayment on behalf of another account, * @dev the target user is defined by onBehalfOf. If there is no repayment on behalf of another account,
* _onBehalfOf must be equal to msg.sender. * onBehalfOf must be equal to msg.sender.
* @param asset the address of the reserve on which the user borrowed * @param asset the address of the reserve on which the user borrowed
* @param amount the amount to repay, or uint256(-1) if the user wants to repay everything * @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
* @param _onBehalfOf the address for which msg.sender is repaying. * @param onBehalfOf the address for which msg.sender is repaying.
**/ **/
function repay( function repay(
address asset, address asset,
uint256 amount, uint256 amount,
uint256 _rateMode, uint256 rateMode,
address _onBehalfOf address onBehalfOf
) external override { ) external override {
ReserveLogic.ReserveData storage reserve = _reserves[asset]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(_onBehalfOf, reserve); (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve);
ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode); ReserveLogic.InterestRateMode interestRateMode = ReserveLogic.InterestRateMode(rateMode);
//default to max amount //default to max amount
uint256 paybackAmount = rateMode == ReserveLogic.InterestRateMode.STABLE uint256 paybackAmount = interestRateMode == ReserveLogic.InterestRateMode.STABLE
? stableDebt ? stableDebt
: variableDebt; : variableDebt;
@ -272,51 +273,59 @@ contract LendingPool is VersionedInitializable, ILendingPool {
paybackAmount = amount; paybackAmount = amount;
} }
ValidationLogic.validateRepay(reserve, amount, rateMode, _onBehalfOf, stableDebt, variableDebt); ValidationLogic.validateRepay(
reserve,
amount,
interestRateMode,
onBehalfOf,
stableDebt,
variableDebt
);
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
//burns an equivalent amount of debt tokens //burns an equivalent amount of debt tokens
if (rateMode == ReserveLogic.InterestRateMode.STABLE) { if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) {
IStableDebtToken(reserve.stableDebtTokenAddress).burn(_onBehalfOf, paybackAmount); IStableDebtToken(reserve.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount);
} else { } else {
IVariableDebtToken(reserve.variableDebtTokenAddress).burn(_onBehalfOf, paybackAmount); IVariableDebtToken(reserve.variableDebtTokenAddress).burn(onBehalfOf, paybackAmount);
} }
reserve.updateInterestRates(asset, paybackAmount, 0); address aToken = reserve.aTokenAddress;
reserve.updateInterestRates(asset, aToken, paybackAmount, 0);
if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) { if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) {
_usersConfig[_onBehalfOf].setBorrowing(reserve.index, false); _usersConfig[onBehalfOf].setBorrowing(reserve.index, false);
} }
IERC20(asset).safeTransferFrom(msg.sender, reserve.aTokenAddress, paybackAmount); IERC20(asset).safeTransferFrom(msg.sender, aToken, paybackAmount);
emit Repay(asset, _onBehalfOf, msg.sender, paybackAmount); emit Repay(asset, onBehalfOf, msg.sender, paybackAmount);
} }
/** /**
* @dev borrowers can user this function to swap between stable and variable borrow rate modes. * @dev borrowers can user this function to swap between stable and variable borrow rate modes.
* @param asset the address of the reserve on which the user borrowed * @param asset the address of the reserve on which the user borrowed
* @param _rateMode the rate mode that the user wants to swap * @param rateMode the rate mode that the user wants to swap
**/ **/
function swapBorrowRateMode(address asset, uint256 _rateMode) external override { function swapBorrowRateMode(address asset, uint256 rateMode) external override nonReentrant {
ReserveLogic.ReserveData storage reserve = _reserves[asset]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve); (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode); ReserveLogic.InterestRateMode interestRateMode = ReserveLogic.InterestRateMode(rateMode);
ValidationLogic.validateSwapRateMode( ValidationLogic.validateSwapRateMode(
reserve, reserve,
_usersConfig[msg.sender], _usersConfig[msg.sender],
stableDebt, stableDebt,
variableDebt, variableDebt,
rateMode interestRateMode
); );
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
if (rateMode == ReserveLogic.InterestRateMode.STABLE) { if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) {
//burn stable rate tokens, mint variable rate tokens //burn stable rate tokens, mint variable rate tokens
IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt); IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt);
IVariableDebtToken(reserve.variableDebtTokenAddress).mint(msg.sender, stableDebt); IVariableDebtToken(reserve.variableDebtTokenAddress).mint(msg.sender, stableDebt);
@ -330,7 +339,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
); );
} }
reserve.updateInterestRates(asset, 0, 0); reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0);
emit Swap(asset, msg.sender); emit Swap(asset, msg.sender);
} }
@ -340,14 +349,14 @@ contract LendingPool is VersionedInitializable, ILendingPool {
* this is regulated by Aave to ensure that the protocol is not abused, and the user is paying a fair * 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. * rate. Anyone can call this function.
* @param asset the address of the reserve * @param asset the address of the reserve
* @param _user the address of the user to be rebalanced * @param user the address of the user to be rebalanced
**/ **/
function rebalanceStableBorrowRate(address asset, address _user) external override { function rebalanceStableBorrowRate(address asset, address user) external override {
ReserveLogic.ReserveData storage reserve = _reserves[asset]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress); IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress);
uint256 stableBorrowBalance = IERC20(address(stableDebtToken)).balanceOf(_user); uint256 stableBorrowBalance = IERC20(address(stableDebtToken)).balanceOf(user);
// user must be borrowing on asset at a stable rate // user must be borrowing on asset at a stable rate
require(stableBorrowBalance > 0, 'User does not have any stable rate loan for this reserve'); require(stableBorrowBalance > 0, 'User does not have any stable rate loan for this reserve');
@ -361,7 +370,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
//2. user stable rate is above the market avg borrow rate of a certain delta, and utilization rate is low. //2. user stable rate is above the market avg borrow rate of a certain delta, and utilization rate is low.
//In this case, the user is paying an interest that is too high, and needs to be rescaled down. //In this case, the user is paying an interest that is too high, and needs to be rescaled down.
uint256 userStableRate = stableDebtToken.getUserStableRate(_user); uint256 userStableRate = stableDebtToken.getUserStableRate(user);
require( require(
userStableRate < reserve.currentLiquidityRate || userStableRate > rebalanceDownRateThreshold, userStableRate < reserve.currentLiquidityRate || userStableRate > rebalanceDownRateThreshold,
@ -372,12 +381,12 @@ contract LendingPool is VersionedInitializable, ILendingPool {
reserve.updateCumulativeIndexesAndTimestamp(); reserve.updateCumulativeIndexesAndTimestamp();
stableDebtToken.burn(_user, stableBorrowBalance); stableDebtToken.burn(user, stableBorrowBalance);
stableDebtToken.mint(_user, stableBorrowBalance, reserve.currentStableBorrowRate); stableDebtToken.mint(user, stableBorrowBalance, reserve.currentStableBorrowRate);
reserve.updateInterestRates(asset, 0, 0); reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0);
emit RebalanceStableBorrowRate(asset, _user); emit RebalanceStableBorrowRate(asset, user);
return; return;
} }
@ -385,9 +394,12 @@ contract LendingPool is VersionedInitializable, ILendingPool {
/** /**
* @dev allows depositors to enable or disable a specific deposit as collateral. * @dev allows depositors to enable or disable a specific deposit as collateral.
* @param asset the address of the reserve * @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 user the deposit as collateral, false otherwise.
**/ **/
function setUserUseReserveAsCollateral(address asset, bool _useAsCollateral) external override { function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)
external
override
{
ReserveLogic.ReserveData storage reserve = _reserves[asset]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
ValidationLogic.validateSetUseReserveAsCollateral( ValidationLogic.validateSetUseReserveAsCollateral(
@ -395,13 +407,13 @@ contract LendingPool is VersionedInitializable, ILendingPool {
asset, asset,
_reserves, _reserves,
_usersConfig[msg.sender], _usersConfig[msg.sender],
reservesList, _reservesList,
addressesProvider.getPriceOracle() _addressesProvider.getPriceOracle()
); );
_usersConfig[msg.sender].setUsingAsCollateral(reserve.index, _useAsCollateral); _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, useAsCollateral);
if (_useAsCollateral) { if (useAsCollateral) {
emit ReserveUsedAsCollateralEnabled(asset, msg.sender); emit ReserveUsedAsCollateralEnabled(asset, msg.sender);
} else { } else {
emit ReserveUsedAsCollateralDisabled(asset, msg.sender); emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
@ -412,29 +424,29 @@ contract LendingPool is VersionedInitializable, ILendingPool {
* @dev users can invoke this function to liquidate an undercollateralized position. * @dev users can invoke this function to liquidate an undercollateralized position.
* @param asset the address of the collateral to liquidated * @param asset the address of the collateral to liquidated
* @param asset the address of the principal reserve * @param asset the address of the principal reserve
* @param _user the address of the borrower * @param user the address of the borrower
* @param _purchaseAmount the amount of principal that the liquidator wants to repay * @param purchaseAmount the amount of principal that the liquidator wants to repay
* @param _receiveAToken true if the liquidators wants to receive the aTokens, false if * @param receiveAToken true if the liquidators wants to receive the aTokens, false if
* he wants to receive the underlying asset directly * he wants to receive the underlying asset directly
**/ **/
function liquidationCall( function liquidationCall(
address _collateral, address collateral,
address asset, address asset,
address _user, address user,
uint256 _purchaseAmount, uint256 purchaseAmount,
bool _receiveAToken bool receiveAToken
) external override { ) external override {
address liquidationManager = addressesProvider.getLendingPoolLiquidationManager(); address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
//solium-disable-next-line //solium-disable-next-line
(bool success, bytes memory result) = liquidationManager.delegatecall( (bool success, bytes memory result) = liquidationManager.delegatecall(
abi.encodeWithSignature( abi.encodeWithSignature(
'liquidationCall(address,address,address,uint256,bool)', 'liquidationCall(address,address,address,uint256,bool)',
_collateral, collateral,
asset, asset,
_user, user,
_purchaseAmount, purchaseAmount,
_receiveAToken receiveAToken
) )
); );
require(success, 'Liquidation call failed'); require(success, 'Liquidation call failed');
@ -644,7 +656,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
); );
} }
function getUserAccountData(address _user) function getUserAccountData(address user)
external external
override override
view view
@ -664,11 +676,11 @@ contract LendingPool is VersionedInitializable, ILendingPool {
currentLiquidationThreshold, currentLiquidationThreshold,
healthFactor healthFactor
) = GenericLogic.calculateUserAccountData( ) = GenericLogic.calculateUserAccountData(
_user, user,
_reserves, _reserves,
_usersConfig[_user], _usersConfig[user],
reservesList, _reservesList,
addressesProvider.getPriceOracle() _addressesProvider.getPriceOracle()
); );
availableBorrowsETH = GenericLogic.calculateAvailableBorrowsETH( availableBorrowsETH = GenericLogic.calculateAvailableBorrowsETH(
@ -678,7 +690,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
); );
} }
function getUserReserveData(address asset, address _user) function getUserReserveData(address asset, address user)
external external
override override
view view
@ -697,20 +709,20 @@ contract LendingPool is VersionedInitializable, ILendingPool {
{ {
ReserveLogic.ReserveData storage reserve = _reserves[asset]; ReserveLogic.ReserveData storage reserve = _reserves[asset];
currentATokenBalance = IERC20(reserve.aTokenAddress).balanceOf(_user); currentATokenBalance = IERC20(reserve.aTokenAddress).balanceOf(user);
(currentStableDebt, currentVariableDebt) = Helpers.getUserCurrentDebt(_user, reserve); (currentStableDebt, currentVariableDebt) = Helpers.getUserCurrentDebt(user, reserve);
(principalStableDebt, principalVariableDebt) = Helpers.getUserPrincipalDebt(_user, reserve); (principalStableDebt, principalVariableDebt) = Helpers.getUserPrincipalDebt(user, reserve);
liquidityRate = reserve.currentLiquidityRate; liquidityRate = reserve.currentLiquidityRate;
stableBorrowRate = IStableDebtToken(reserve.stableDebtTokenAddress).getUserStableRate(_user); stableBorrowRate = IStableDebtToken(reserve.stableDebtTokenAddress).getUserStableRate(user);
stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated( stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated(
_user user
); );
usageAsCollateralEnabled = _usersConfig[_user].isUsingAsCollateral(reserve.index); usageAsCollateralEnabled = _usersConfig[user].isUsingAsCollateral(reserve.index);
variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(_user); variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(user);
} }
function getReserves() external override view returns (address[] memory) { function getReserves() external override view returns (address[] memory) {
return reservesList; return _reservesList;
} }
receive() external payable { receive() external payable {
@ -720,21 +732,21 @@ contract LendingPool is VersionedInitializable, ILendingPool {
/** /**
* @dev initializes a reserve * @dev initializes a reserve
* @param asset the address of the reserve * @param asset the address of the reserve
* @param _aTokenAddress the address of the overlying aToken contract * @param aTokenAddress the address of the overlying aToken contract
* @param _interestRateStrategyAddress the address of the interest rate strategy contract * @param interestRateStrategyAddress the address of the interest rate strategy contract
**/ **/
function initReserve( function initReserve(
address asset, address asset,
address _aTokenAddress, address aTokenAddress,
address _stableDebtAddress, address stableDebtAddress,
address _variableDebtAddress, address variableDebtAddress,
address _interestRateStrategyAddress address interestRateStrategyAddress
) external override onlyLendingPoolConfigurator { ) external override onlyLendingPoolConfigurator {
_reserves[asset].init( _reserves[asset].init(
_aTokenAddress, aTokenAddress,
_stableDebtAddress, stableDebtAddress,
_variableDebtAddress, variableDebtAddress,
_interestRateStrategyAddress interestRateStrategyAddress
); );
_addReserveToList(asset); _addReserveToList(asset);
} }
@ -779,13 +791,13 @@ contract LendingPool is VersionedInitializable, ILendingPool {
**/ **/
function _addReserveToList(address asset) internal { function _addReserveToList(address asset) internal {
bool reserveAlreadyAdded = false; bool reserveAlreadyAdded = false;
for (uint256 i = 0; i < reservesList.length; i++) for (uint256 i = 0; i < _reservesList.length; i++)
if (reservesList[i] == asset) { if (_reservesList[i] == asset) {
reserveAlreadyAdded = true; reserveAlreadyAdded = true;
} }
if (!reserveAlreadyAdded) { if (!reserveAlreadyAdded) {
_reserves[asset].index = uint8(reservesList.length); _reserves[asset].index = uint8(_reservesList.length);
reservesList.push(asset); _reservesList.push(asset);
} }
} }
@ -831,8 +843,8 @@ contract LendingPool is VersionedInitializable, ILendingPool {
amount, amount,
_reserves, _reserves,
_usersConfig[user], _usersConfig[user],
reservesList, _reservesList,
addressesProvider.getPriceOracle() _addressesProvider.getPriceOracle()
); );
} }
@ -840,13 +852,13 @@ contract LendingPool is VersionedInitializable, ILendingPool {
* @dev returns the list of the initialized reserves * @dev returns the list of the initialized reserves
**/ **/
function getReservesList() external view returns (address[] memory) { function getReservesList() external view returns (address[] memory) {
return reservesList; return _reservesList;
} }
/** /**
* @dev returns the addresses provider * @dev returns the addresses provider
**/ **/
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider) { function getAddressesProvider() external view returns (ILendingPoolAddressesProvider) {
return addressesProvider; return _addressesProvider;
} }
} }

View File

@ -164,10 +164,10 @@ contract LendingPoolConfigurator is VersionedInitializable {
/** /**
* @dev emitted when the implementation of a variable debt token is upgraded * @dev emitted when the implementation of a variable debt token is upgraded
* @param asset the address of the reserve * @param asset the address of the reserve
* @param _proxy the variable debt token proxy address * @param proxy the variable debt token proxy address
* @param _implementation the new aToken implementation * @param implementation the new aToken implementation
**/ **/
event VariableDebtTokenUpgraded(address asset, address _proxy, address _implementation); event VariableDebtTokenUpgraded(address asset, address proxy, address implementation);
ILendingPoolAddressesProvider internal addressesProvider; ILendingPoolAddressesProvider internal addressesProvider;
ILendingPool internal pool; ILendingPool internal pool;
@ -211,10 +211,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
uint8 underlyingAssetDecimals, uint8 underlyingAssetDecimals,
address interestRateStrategyAddress address interestRateStrategyAddress
) public onlyLendingPoolManager { ) public onlyLendingPoolManager {
address aTokenProxyAddress = _initTokenWithProxy( address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals);
aTokenImpl,
underlyingAssetDecimals
);
address stableDebtTokenProxyAddress = _initTokenWithProxy( address stableDebtTokenProxyAddress = _initTokenWithProxy(
stableDebtTokenImpl, stableDebtTokenImpl,
@ -280,6 +277,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
emit StableDebtTokenUpgraded(asset, stableDebtToken, implementation); emit StableDebtTokenUpgraded(asset, stableDebtToken, implementation);
} }
/** /**
* @dev updates the variable debt token implementation for the asset * @dev updates the variable debt token implementation for the asset
* @param asset the address of the reserve to be updated * @param asset the address of the reserve to be updated
@ -349,12 +347,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
pool.setConfiguration(asset, currentConfig.data); pool.setConfiguration(asset, currentConfig.data);
emit ReserveEnabledAsCollateral( emit ReserveEnabledAsCollateral(asset, ltv, liquidationThreshold, liquidationBonus);
asset,
ltv,
liquidationThreshold,
liquidationBonus
);
} }
/** /**
@ -553,10 +546,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param implementation the address of the implementation * @param implementation the address of the implementation
* @param decimals the decimals of the token * @param decimals the decimals of the token
**/ **/
function _initTokenWithProxy( function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) {
address implementation,
uint8 decimals
) internal returns (address) {
InitializableAdminUpgradeabilityProxy proxy = new InitializableAdminUpgradeabilityProxy(); InitializableAdminUpgradeabilityProxy proxy = new InitializableAdminUpgradeabilityProxy();
bytes memory params = abi.encodeWithSignature( bytes memory params = abi.encodeWithSignature(

View File

@ -134,7 +134,9 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
); );
} }
vars.userCollateralBalance = IERC20(collateralReserve.aTokenAddress).balanceOf(user); vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress);
vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user);
vars.isCollateralEnabled = vars.isCollateralEnabled =
collateralReserve.configuration.getLiquidationThreshold() > 0 && collateralReserve.configuration.getLiquidationThreshold() > 0 &&
@ -190,8 +192,6 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
vars.actualAmountToLiquidate = vars.principalAmountNeeded; vars.actualAmountToLiquidate = vars.principalAmountNeeded;
} }
vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress);
//if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve //if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve
if (!receiveAToken) { if (!receiveAToken) {
uint256 currentAvailableCollateral = IERC20(collateral).balanceOf( uint256 currentAvailableCollateral = IERC20(collateral).balanceOf(
@ -207,7 +207,12 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
//update the principal reserve //update the principal reserve
principalReserve.updateCumulativeIndexesAndTimestamp(); principalReserve.updateCumulativeIndexesAndTimestamp();
principalReserve.updateInterestRates(principal, vars.actualAmountToLiquidate, 0); principalReserve.updateInterestRates(
principal,
principalReserve.aTokenAddress,
vars.actualAmountToLiquidate,
0
);
if (vars.userVariableDebt >= vars.actualAmountToLiquidate) { if (vars.userVariableDebt >= vars.actualAmountToLiquidate) {
IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn( IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
@ -233,7 +238,12 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
//updating collateral reserve //updating collateral reserve
collateralReserve.updateCumulativeIndexesAndTimestamp(); collateralReserve.updateCumulativeIndexesAndTimestamp();
collateralReserve.updateInterestRates(collateral, 0, vars.maxCollateralToLiquidate); collateralReserve.updateInterestRates(
collateral,
address(vars.collateralAtoken),
0,
vars.maxCollateralToLiquidate
);
//burn the equivalent amount of atoken //burn the equivalent amount of atoken
vars.collateralAtoken.burn(user, msg.sender, vars.maxCollateralToLiquidate); vars.collateralAtoken.burn(user, msg.sender, vars.maxCollateralToLiquidate);
@ -281,8 +291,8 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
* @return principalAmountNeeded the purchase amount * @return principalAmountNeeded the purchase amount
**/ **/
function calculateAvailableCollateralToLiquidate( function calculateAvailableCollateralToLiquidate(
ReserveLogic.ReserveData storage _collateralReserve, ReserveLogic.ReserveData storage collateralReserve,
ReserveLogic.ReserveData storage _principalReserve, ReserveLogic.ReserveData storage principalReserve,
address collateralAddress, address collateralAddress,
address principalAddress, address principalAddress,
uint256 purchaseAmount, uint256 purchaseAmount,
@ -298,10 +308,10 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
vars.collateralPrice = oracle.getAssetPrice(collateralAddress); vars.collateralPrice = oracle.getAssetPrice(collateralAddress);
vars.principalCurrencyPrice = oracle.getAssetPrice(principalAddress); vars.principalCurrencyPrice = oracle.getAssetPrice(principalAddress);
(, , vars.liquidationBonus, vars.collateralDecimals) = _collateralReserve (, , vars.liquidationBonus, vars.collateralDecimals) = collateralReserve
.configuration .configuration
.getParams(); .getParams();
vars.principalDecimals = _principalReserve.configuration.getDecimals(); vars.principalDecimals = principalReserve.configuration.getDecimals();
//this is the maximum possible amount of the selected collateral that can be liquidated, given the //this is the maximum possible amount of the selected collateral that can be liquidated, given the
//max amount of principal currency that is available for liquidation. //max amount of principal currency that is available for liquidation.

View File

@ -126,18 +126,18 @@ library ReserveLogic {
IERC20(reserve.variableDebtTokenAddress).totalSupply() > 0 || IERC20(reserve.variableDebtTokenAddress).totalSupply() > 0 ||
IERC20(reserve.stableDebtTokenAddress).totalSupply() > 0 IERC20(reserve.stableDebtTokenAddress).totalSupply() > 0
) { ) {
uint40 lastUpdateTimestamp = reserve.lastUpdateTimestamp;
uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest( uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest(
reserve.currentLiquidityRate, reserve.currentLiquidityRate,
reserve.lastUpdateTimestamp lastUpdateTimestamp
); );
reserve.lastLiquidityIndex = cumulatedLiquidityInterest.rayMul( reserve.lastLiquidityIndex = cumulatedLiquidityInterest.rayMul(reserve.lastLiquidityIndex);
reserve.lastLiquidityIndex
);
uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest( uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest(
reserve.currentVariableBorrowRate, reserve.currentVariableBorrowRate,
reserve.lastUpdateTimestamp lastUpdateTimestamp
); );
reserve.lastVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul( reserve.lastVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(
reserve.lastVariableBorrowIndex reserve.lastVariableBorrowIndex
@ -164,9 +164,7 @@ library ReserveLogic {
uint256 cumulatedLiquidity = amountToLiquidityRatio.add(WadRayMath.ray()); uint256 cumulatedLiquidity = amountToLiquidityRatio.add(WadRayMath.ray());
reserve.lastLiquidityIndex = cumulatedLiquidity.rayMul( reserve.lastLiquidityIndex = cumulatedLiquidity.rayMul(reserve.lastLiquidityIndex);
reserve.lastLiquidityIndex
);
} }
/** /**
@ -208,21 +206,20 @@ library ReserveLogic {
function updateInterestRates( function updateInterestRates(
ReserveData storage reserve, ReserveData storage reserve,
address reserveAddress, address reserveAddress,
address aTokenAddress,
uint256 liquidityAdded, uint256 liquidityAdded,
uint256 liquidityTaken uint256 liquidityTaken
) internal { ) internal {
uint256 currentAvgStableRate = IStableDebtToken(reserve.stableDebtTokenAddress) uint256 currentAvgStableRate = IStableDebtToken(reserve.stableDebtTokenAddress)
.getAverageStableRate(); .getAverageStableRate();
uint256 balance = IERC20(reserveAddress).balanceOf(reserve.aTokenAddress);
( (
uint256 newLiquidityRate, uint256 newLiquidityRate,
uint256 newStableRate, uint256 newStableRate,
uint256 newVariableRate uint256 newVariableRate
) = IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).calculateInterestRates( ) = IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).calculateInterestRates(
reserveAddress, reserveAddress,
balance.add(liquidityAdded).sub(liquidityTaken), IERC20(reserveAddress).balanceOf(aTokenAddress).add(liquidityAdded).sub(liquidityTaken),
IERC20(reserve.stableDebtTokenAddress).totalSupply(), IERC20(reserve.stableDebtTokenAddress).totalSupply(),
IERC20(reserve.variableDebtTokenAddress).totalSupply(), IERC20(reserve.variableDebtTokenAddress).totalSupply(),
currentAvgStableRate currentAvgStableRate

View File

@ -7,15 +7,14 @@ import {
EXCESS_UTILIZATION_RATE, EXCESS_UTILIZATION_RATE,
ZERO_ADDRESS, ZERO_ADDRESS,
} from '../../../helpers/constants'; } from '../../../helpers/constants';
import {IReserveParams, iAavePoolAssets, RateMode} from '../../../helpers/types'; import { IReserveParams, iAavePoolAssets, RateMode } from '../../../helpers/types';
import './math'; import './math';
import {ReserveData, UserReserveData} from './interfaces'; import { ReserveData, UserReserveData } from './interfaces';
export const strToBN = (amount: string): BigNumber => new BigNumber(amount); export const strToBN = (amount: string): BigNumber => new BigNumber(amount);
interface Configuration { interface Configuration {
reservesParams: iAavePoolAssets<IReserveParams>; reservesParams: iAavePoolAssets<IReserveParams>;
ethereumAddress: string;
} }
export const configuration: Configuration = <Configuration>{}; export const configuration: Configuration = <Configuration>{};
@ -66,17 +65,7 @@ export const calcExpectedUserDataAfterDeposit = (
} }
expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex;
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited);
if (reserveDataBeforeAction.address === configuration.ethereumAddress) {
// console.log("** ETH CASE ****")
expectedUserData.walletBalance = userDataBeforeAction.walletBalance
.minus(txCost)
.minus(amountDeposited);
} else {
// console.log("** TOKEN CASE ****")
// console.log(userDataBeforeAction.walletBalance.toString())
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(amountDeposited);
}
expectedUserData.principalATokenBalance = expectedUserData.currentATokenBalance = calcExpectedATokenBalance( expectedUserData.principalATokenBalance = expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction, reserveDataBeforeAction,
@ -171,14 +160,7 @@ export const calcExpectedUserDataAfterWithdraw = (
} }
expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex; expectedUserData.variableBorrowIndex = userDataBeforeAction.variableBorrowIndex;
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn);
if (reserveDataBeforeAction.address === configuration.ethereumAddress) {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance
.minus(txCost)
.plus(amountWithdrawn);
} else {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountWithdrawn);
}
expectedUserData.redirectedBalance = userDataBeforeAction.redirectedBalance; expectedUserData.redirectedBalance = userDataBeforeAction.redirectedBalance;
@ -600,13 +582,7 @@ export const calcExpectedUserDataAfterBorrow = (
userDataBeforeAction.redirectionAddressRedirectedBalance; userDataBeforeAction.redirectionAddressRedirectedBalance;
expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex; expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex;
if (reserveDataBeforeAction.address === configuration.ethereumAddress) { expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed);
expectedUserData.walletBalance = userDataBeforeAction.walletBalance
.minus(txCost)
.plus(amountBorrowed);
} else {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.plus(amountBorrowed);
}
return expectedUserData; return expectedUserData;
}; };
@ -657,8 +633,7 @@ export const calcExpectedUserDataAfterRepay = (
expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber( expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber(
'0' '0'
); );
} } else {
else{
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate; expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
expectedUserData.stableRateLastUpdated = txTimestamp; expectedUserData.stableRateLastUpdated = txTimestamp;
} }
@ -697,14 +672,7 @@ export const calcExpectedUserDataAfterRepay = (
expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex; expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex;
if (user === onBehalfOf) { if (user === onBehalfOf) {
//if user repaid for himself, update the wallet balances expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaid);
if (reserveDataBeforeAction.address === configuration.ethereumAddress) {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance
.minus(txCost)
.minus(totalRepaid);
} else {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(totalRepaid);
}
} else { } else {
//wallet balance didn't change //wallet balance didn't change
expectedUserData.walletBalance = userDataBeforeAction.walletBalance; expectedUserData.walletBalance = userDataBeforeAction.walletBalance;
@ -719,14 +687,10 @@ export const calcExpectedUserDataAfterSetUseAsCollateral = (
userDataBeforeAction: UserReserveData, userDataBeforeAction: UserReserveData,
txCost: BigNumber txCost: BigNumber
): UserReserveData => { ): UserReserveData => {
const expectedUserData = {...userDataBeforeAction}; const expectedUserData = { ...userDataBeforeAction };
expectedUserData.usageAsCollateralEnabled = useAsCollateral; expectedUserData.usageAsCollateralEnabled = useAsCollateral;
if (reserveDataBeforeAction.address === configuration.ethereumAddress) {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(txCost);
}
return expectedUserData; return expectedUserData;
}; };
@ -829,7 +793,7 @@ export const calcExpectedUserDataAfterSwapRateMode = (
txCost: BigNumber, txCost: BigNumber,
txTimestamp: BigNumber txTimestamp: BigNumber
): UserReserveData => { ): UserReserveData => {
const expectedUserData = {...userDataBeforeAction}; const expectedUserData = { ...userDataBeforeAction };
const variableBorrowBalance = calcExpectedVariableDebtTokenBalance( const variableBorrowBalance = calcExpectedVariableDebtTokenBalance(
reserveDataBeforeAction, reserveDataBeforeAction,
@ -892,9 +856,6 @@ export const calcExpectedUserDataAfterSwapRateMode = (
expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate;
if (reserveDataBeforeAction.address === configuration.ethereumAddress) {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(txCost);
}
return expectedUserData; return expectedUserData;
}; };
@ -976,7 +937,7 @@ export const calcExpectedUserDataAfterStableRateRebalance = (
txCost: BigNumber, txCost: BigNumber,
txTimestamp: BigNumber txTimestamp: BigNumber
): UserReserveData => { ): UserReserveData => {
const expectedUserData = {...userDataBeforeAction}; const expectedUserData = { ...userDataBeforeAction };
expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance( expectedUserData.principalVariableDebt = calcExpectedVariableDebtTokenBalance(
reserveDataBeforeAction, reserveDataBeforeAction,
@ -1000,12 +961,6 @@ export const calcExpectedUserDataAfterStableRateRebalance = (
expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate; expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate;
if (reserveDataBeforeAction.address === configuration.ethereumAddress) {
expectedUserData.walletBalance = userDataBeforeAction.walletBalance.minus(txCost);
}
expectedUserData.liquidityRate = expectedDataAfterAction.liquidityRate;
expectedUserData.currentATokenBalance = calcExpectedATokenBalance( expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction, reserveDataBeforeAction,
userDataBeforeAction, userDataBeforeAction,
@ -1037,8 +992,8 @@ export const calcExpectedUsersDataAfterRedirectInterest = (
txCost: BigNumber, txCost: BigNumber,
txTimestamp: BigNumber txTimestamp: BigNumber
): UserReserveData[] => { ): UserReserveData[] => {
const expectedFromData = {...fromDataBeforeAction}; const expectedFromData = { ...fromDataBeforeAction };
const expectedToData = {...toDataBeforeAction}; const expectedToData = { ...toDataBeforeAction };
expectedFromData.currentStableDebt = calcExpectedStableDebtTokenBalance( expectedFromData.currentStableDebt = calcExpectedStableDebtTokenBalance(
fromDataBeforeAction, fromDataBeforeAction,
@ -1069,12 +1024,6 @@ export const calcExpectedUsersDataAfterRedirectInterest = (
txTimestamp txTimestamp
); );
if (isFromExecutingTx) {
if (reserveDataBeforeAction.address === configuration.ethereumAddress) {
expectedFromData.walletBalance = fromDataBeforeAction.walletBalance.minus(txCost);
}
}
expectedToData.redirectedBalance = toDataBeforeAction.redirectedBalance.plus( expectedToData.redirectedBalance = toDataBeforeAction.redirectedBalance.plus(
expectedFromData.currentATokenBalance expectedFromData.currentATokenBalance
); );
@ -1215,7 +1164,7 @@ export const calcExpectedVariableDebtTokenBalance = (
) => { ) => {
const debt = calcExpectedReserveNormalizedDebt(reserveDataBeforeAction, currentTimestamp); const debt = calcExpectedReserveNormalizedDebt(reserveDataBeforeAction, currentTimestamp);
const {principalVariableDebt, variableBorrowIndex} = userDataBeforeAction; const { principalVariableDebt, variableBorrowIndex } = userDataBeforeAction;
if (variableBorrowIndex.eq(0)) { if (variableBorrowIndex.eq(0)) {
return principalVariableDebt; return principalVariableDebt;
@ -1228,7 +1177,7 @@ export const calcExpectedStableDebtTokenBalance = (
userDataBeforeAction: UserReserveData, userDataBeforeAction: UserReserveData,
currentTimestamp: BigNumber currentTimestamp: BigNumber
) => { ) => {
const {principalStableDebt, stableBorrowRate, stableRateLastUpdated} = userDataBeforeAction; const { principalStableDebt, stableBorrowRate, stableRateLastUpdated } = userDataBeforeAction;
if ( if (
stableBorrowRate.eq(0) || stableBorrowRate.eq(0) ||
@ -1301,7 +1250,7 @@ const calcExpectedInterestRates = (
totalBorrowsVariable: BigNumber, totalBorrowsVariable: BigNumber,
averageStableBorrowRate: BigNumber averageStableBorrowRate: BigNumber
): BigNumber[] => { ): BigNumber[] => {
const {reservesParams} = configuration; const { reservesParams } = configuration;
const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol); const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol);
const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[ const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[
@ -1391,7 +1340,7 @@ const calcExpectedReserveNormalizedIncome = (
reserveData: ReserveData, reserveData: ReserveData,
currentTimestamp: BigNumber currentTimestamp: BigNumber
) => { ) => {
const {liquidityRate, liquidityIndex, lastUpdateTimestamp} = reserveData; const { liquidityRate, liquidityIndex, lastUpdateTimestamp } = reserveData;
//if utilization rate is 0, nothing to compound //if utilization rate is 0, nothing to compound
if (liquidityRate.eq('0')) { if (liquidityRate.eq('0')) {
@ -1413,7 +1362,7 @@ const calcExpectedReserveNormalizedDebt = (
reserveData: ReserveData, reserveData: ReserveData,
currentTimestamp: BigNumber currentTimestamp: BigNumber
) => { ) => {
const {variableBorrowRate, variableBorrowIndex, lastUpdateTimestamp} = reserveData; const { variableBorrowRate, variableBorrowIndex, lastUpdateTimestamp } = reserveData;
//if utilization rate is 0, nothing to compound //if utilization rate is 0, nothing to compound
if (variableBorrowRate.eq('0')) { if (variableBorrowRate.eq('0')) {
@ -1472,31 +1421,3 @@ const calcExpectedVariableBorrowIndex = (reserveData: ReserveData, timestamp: Bi
return cumulatedInterest.rayMul(reserveData.variableBorrowIndex); return cumulatedInterest.rayMul(reserveData.variableBorrowIndex);
}; };
export const calculateHealthFactorFromBalances = (
collateralBalanceETH: BigNumber,
borrowBalanceETH: BigNumber,
currentLiquidationThreshold: BigNumber
): BigNumber => {
if (borrowBalanceETH.eq(0)) {
return strToBN('-1'); // invalid number
}
return collateralBalanceETH.multipliedBy(currentLiquidationThreshold).div(borrowBalanceETH);
};
const calculateAvailableBorrowsETH = (
collateralBalanceETH: BigNumber,
borrowBalanceETH: BigNumber,
currentLtv: BigNumber
): BigNumber => {
if (currentLtv.eq(0)) {
return strToBN('0');
}
let availableBorrowsETH = collateralBalanceETH.multipliedBy(currentLtv);
if (availableBorrowsETH.lt(borrowBalanceETH)) {
return strToBN('0');
}
availableBorrowsETH = availableBorrowsETH.minus(borrowBalanceETH);
const borrowFee = availableBorrowsETH.multipliedBy(0.0025);
return availableBorrowsETH.minus(borrowFee);
};