mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'master' into fix/23
This commit is contained in:
commit
cf39045573
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user