mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'fix/22' into 'master'
Resolve "FIx the libraries folder to follow our internal guidelines" Closes #22 See merge request aave-tech/protocol-v2!27
This commit is contained in:
commit
45cb9ab680
|
@ -43,7 +43,7 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
|
||||||
* @param pool the new lending pool implementation
|
* @param pool the new lending pool implementation
|
||||||
**/
|
**/
|
||||||
function setLendingPoolImpl(address pool) external override onlyOwner {
|
function setLendingPoolImpl(address pool) external override onlyOwner {
|
||||||
_updateImplementation(LENDING_POOL, pool);
|
_updateImpl(LENDING_POOL, pool);
|
||||||
emit LendingPoolUpdated(pool);
|
emit LendingPoolUpdated(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
|
||||||
* @param configurator the new lending pool configurator implementation
|
* @param configurator the new lending pool configurator implementation
|
||||||
**/
|
**/
|
||||||
function setLendingPoolConfiguratorImpl(address configurator) external override onlyOwner {
|
function setLendingPoolConfiguratorImpl(address configurator) external override onlyOwner {
|
||||||
_updateImplementation(LENDING_POOL_CONFIGURATOR, configurator);
|
_updateImpl(LENDING_POOL_CONFIGURATOR, configurator);
|
||||||
emit LendingPoolConfiguratorUpdated(configurator);
|
emit LendingPoolConfiguratorUpdated(configurator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
|
||||||
* @param id the id of the contract to be updated
|
* @param id the id of the contract to be updated
|
||||||
* @param newAddress the address of the new implementation
|
* @param newAddress the address of the new implementation
|
||||||
**/
|
**/
|
||||||
function _updateImplementation(bytes32 id, address newAddress) internal {
|
function _updateImpl(bytes32 id, address newAddress) internal {
|
||||||
address payable proxyAddress = payable(_addresses[id]);
|
address payable proxyAddress = payable(_addresses[id]);
|
||||||
|
|
||||||
InitializableAdminUpgradeabilityProxy proxy = InitializableAdminUpgradeabilityProxy(
|
InitializableAdminUpgradeabilityProxy proxy = InitializableAdminUpgradeabilityProxy(
|
||||||
|
|
|
@ -20,7 +20,7 @@ abstract contract FlashLoanReceiverBase is IFlashLoanReceiver {
|
||||||
|
|
||||||
receive() external payable {}
|
receive() external payable {}
|
||||||
|
|
||||||
function transferFundsBackInternal(
|
function _transferFundsBack(
|
||||||
address reserve,
|
address reserve,
|
||||||
address destination,
|
address destination,
|
||||||
uint256 amount
|
uint256 amount
|
||||||
|
|
|
@ -149,7 +149,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentLiquidityRate = getOverallBorrowRateInternal(
|
currentLiquidityRate = _getOverallBorrowRate(
|
||||||
totalBorrowsStable,
|
totalBorrowsStable,
|
||||||
totalBorrowsVariable,
|
totalBorrowsVariable,
|
||||||
currentVariableBorrowRate,
|
currentVariableBorrowRate,
|
||||||
|
@ -170,7 +170,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
|
||||||
* @param currentAverageStableBorrowRate the weighted average of all the stable rate borrows
|
* @param currentAverageStableBorrowRate the weighted average of all the stable rate borrows
|
||||||
* @return the weighted averaged borrow rate
|
* @return the weighted averaged borrow rate
|
||||||
**/
|
**/
|
||||||
function getOverallBorrowRateInternal(
|
function _getOverallBorrowRate(
|
||||||
uint256 totalBorrowsStable,
|
uint256 totalBorrowsStable,
|
||||||
uint256 totalBorrowsVariable,
|
uint256 totalBorrowsVariable,
|
||||||
uint256 currentVariableBorrowRate,
|
uint256 currentVariableBorrowRate,
|
||||||
|
|
|
@ -242,7 +242,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
|
||||||
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(_onBehalfOf, reserve);
|
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(_onBehalfOf, reserve);
|
||||||
|
|
||||||
ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode);
|
ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode);
|
||||||
|
|
||||||
//default to max amount
|
//default to max amount
|
||||||
uint256 paybackAmount = rateMode == ReserveLogic.InterestRateMode.STABLE
|
uint256 paybackAmount = rateMode == ReserveLogic.InterestRateMode.STABLE
|
||||||
? stableDebt
|
? stableDebt
|
||||||
|
@ -254,13 +254,11 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
|
||||||
|
|
||||||
ValidationLogic.validateRepay(
|
ValidationLogic.validateRepay(
|
||||||
reserve,
|
reserve,
|
||||||
asset,
|
|
||||||
amount,
|
amount,
|
||||||
rateMode,
|
rateMode,
|
||||||
_onBehalfOf,
|
_onBehalfOf,
|
||||||
stableDebt,
|
stableDebt,
|
||||||
variableDebt,
|
variableDebt
|
||||||
paybackAmount
|
|
||||||
);
|
);
|
||||||
|
|
||||||
reserve.updateCumulativeIndexesAndTimestamp();
|
reserve.updateCumulativeIndexesAndTimestamp();
|
||||||
|
@ -492,7 +490,18 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
|
||||||
'The actual balance of the protocol is inconsistent'
|
'The actual balance of the protocol is inconsistent'
|
||||||
);
|
);
|
||||||
|
|
||||||
reserve.updateStateOnFlashLoan(asset, availableLiquidityBefore, amountFee);
|
//compounding the cumulated interest
|
||||||
|
reserve.updateCumulativeIndexesAndTimestamp();
|
||||||
|
|
||||||
|
uint256 totalLiquidityBefore = availableLiquidityBefore
|
||||||
|
.add(IERC20(reserve.variableDebtTokenAddress).totalSupply())
|
||||||
|
.add(IERC20(reserve.stableDebtTokenAddress).totalSupply());
|
||||||
|
|
||||||
|
//compounding the received fee into the reserve
|
||||||
|
reserve.cumulateToLiquidityIndex(totalLiquidityBefore, amountFee);
|
||||||
|
|
||||||
|
//refresh interest rates
|
||||||
|
reserve.updateInterestRates(asset, amountFee, 0);
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
emit FlashLoan(receiverAddress, asset, amount, amountFee);
|
emit FlashLoan(receiverAddress, asset, amount, amountFee);
|
||||||
|
@ -580,8 +589,8 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool {
|
||||||
reserve.currentVariableBorrowRate,
|
reserve.currentVariableBorrowRate,
|
||||||
reserve.currentStableBorrowRate,
|
reserve.currentStableBorrowRate,
|
||||||
IStableDebtToken(reserve.stableDebtTokenAddress).getAverageStableRate(),
|
IStableDebtToken(reserve.stableDebtTokenAddress).getAverageStableRate(),
|
||||||
reserve.lastLiquidityCumulativeIndex,
|
reserve.lastLiquidityIndex,
|
||||||
reserve.lastVariableBorrowCumulativeIndex,
|
reserve.lastVariableBorrowIndex,
|
||||||
reserve.lastUpdateTimestamp
|
reserve.lastUpdateTimestamp
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,174 +36,171 @@ library ReserveConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets the Loan to Value of the reserve
|
* @dev sets the Loan to Value of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _ltv the new ltv
|
* @param ltv the new ltv
|
||||||
**/
|
**/
|
||||||
function setLtv(ReserveConfiguration.Map memory _self, uint256 _ltv) internal {
|
function setLtv(ReserveConfiguration.Map memory self, uint256 ltv) internal pure {
|
||||||
_self.data = (_self.data & LTV_MASK) | _ltv;
|
self.data = (self.data & LTV_MASK) | ltv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the Loan to Value of the reserve
|
* @dev gets the Loan to Value of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the loan to value
|
* @return the loan to value
|
||||||
**/
|
**/
|
||||||
function getLtv(ReserveConfiguration.Map storage _self) internal view returns (uint256) {
|
function getLtv(ReserveConfiguration.Map storage self) internal view returns (uint256) {
|
||||||
return _self.data & ~LTV_MASK;
|
return self.data & ~LTV_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets the liquidation threshold of the reserve
|
* @dev sets the liquidation threshold of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _threshold the new liquidation threshold
|
* @param threshold the new liquidation threshold
|
||||||
**/
|
**/
|
||||||
function setLiquidationThreshold(ReserveConfiguration.Map memory _self, uint256 _threshold)
|
function setLiquidationThreshold(ReserveConfiguration.Map memory self, uint256 threshold)
|
||||||
internal
|
internal
|
||||||
|
pure
|
||||||
{
|
{
|
||||||
_self.data = (_self.data & LIQUIDATION_THRESHOLD_MASK) | (_threshold << 16);
|
self.data = (self.data & LIQUIDATION_THRESHOLD_MASK) | (threshold << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the Loan to Value of the reserve
|
* @dev gets the Loan to Value of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the liquidation threshold
|
* @return the liquidation threshold
|
||||||
**/
|
**/
|
||||||
function getLiquidationThreshold(ReserveConfiguration.Map storage _self)
|
function getLiquidationThreshold(ReserveConfiguration.Map storage self)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
return (_self.data & ~LIQUIDATION_THRESHOLD_MASK) >> 16;
|
return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets the liquidation bonus of the reserve
|
* @dev sets the liquidation bonus of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _bonus the new liquidation bonus
|
* @param bonus the new liquidation bonus
|
||||||
**/
|
**/
|
||||||
function setLiquidationBonus(ReserveConfiguration.Map memory _self, uint256 _bonus) internal {
|
function setLiquidationBonus(ReserveConfiguration.Map memory self, uint256 bonus) internal pure {
|
||||||
_self.data = (_self.data & LIQUIDATION_BONUS_MASK) | (_bonus << 32);
|
self.data = (self.data & LIQUIDATION_BONUS_MASK) | (bonus << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the liquidation bonus of the reserve
|
* @dev gets the liquidation bonus of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the liquidation bonus
|
* @return the liquidation bonus
|
||||||
**/
|
**/
|
||||||
function getLiquidationBonus(ReserveConfiguration.Map storage _self)
|
function getLiquidationBonus(ReserveConfiguration.Map storage self)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
return (_self.data & ~LIQUIDATION_BONUS_MASK) >> 32;
|
return (self.data & ~LIQUIDATION_BONUS_MASK) >> 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets the decimals of the underlying asset of the reserve
|
* @dev sets the decimals of the underlying asset of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _decimals the decimals
|
* @param decimals the decimals
|
||||||
**/
|
**/
|
||||||
function setDecimals(ReserveConfiguration.Map memory _self, uint256 _decimals) internal {
|
function setDecimals(ReserveConfiguration.Map memory self, uint256 decimals) internal pure {
|
||||||
_self.data = (_self.data & DECIMALS_MASK) | (_decimals << 48);
|
self.data = (self.data & DECIMALS_MASK) | (decimals << 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the decimals of the underlying asset of the reserve
|
* @dev gets the decimals of the underlying asset of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the decimals of the asset
|
* @return the decimals of the asset
|
||||||
**/
|
**/
|
||||||
function getDecimals(ReserveConfiguration.Map storage _self) internal view returns (uint256) {
|
function getDecimals(ReserveConfiguration.Map storage self) internal view returns (uint256) {
|
||||||
return (_self.data & ~DECIMALS_MASK) >> 48;
|
return (self.data & ~DECIMALS_MASK) >> 48;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets the active state of the reserve
|
* @dev sets the active state of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _active the active state
|
* @param active the active state
|
||||||
**/
|
**/
|
||||||
function setActive(ReserveConfiguration.Map memory _self, bool _active) internal {
|
function setActive(ReserveConfiguration.Map memory self, bool active) internal {
|
||||||
_self.data = (_self.data & ACTIVE_MASK) | (uint256(_active ? 1 : 0) << 56);
|
self.data = (self.data & ACTIVE_MASK) | (uint256(active ? 1 : 0) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the active state of the reserve
|
* @dev gets the active state of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the active state
|
* @return the active state
|
||||||
**/
|
**/
|
||||||
function getActive(ReserveConfiguration.Map storage _self) internal view returns (bool) {
|
function getActive(ReserveConfiguration.Map storage self) internal view returns (bool) {
|
||||||
return ((_self.data & ~ACTIVE_MASK) >> 56) != 0;
|
return ((self.data & ~ACTIVE_MASK) >> 56) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets the frozen state of the reserve
|
* @dev sets the frozen state of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _frozen the frozen state
|
* @param frozen the frozen state
|
||||||
**/
|
**/
|
||||||
function setFrozen(ReserveConfiguration.Map memory _self, bool _frozen) internal {
|
function setFrozen(ReserveConfiguration.Map memory self, bool frozen) internal pure {
|
||||||
_self.data = (_self.data & FROZEN_MASK) | (uint256(_frozen ? 1 : 0) << 57);
|
self.data = (self.data & FROZEN_MASK) | (uint256(frozen ? 1 : 0) << 57);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the frozen state of the reserve
|
* @dev gets the frozen state of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the frozen state
|
* @return the frozen state
|
||||||
**/
|
**/
|
||||||
function getFrozen(ReserveConfiguration.Map storage _self) internal view returns (bool) {
|
function getFrozen(ReserveConfiguration.Map storage self) internal view returns (bool) {
|
||||||
return ((_self.data & ~FROZEN_MASK) >> 57) != 0;
|
return ((self.data & ~FROZEN_MASK) >> 57) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev enables or disables borrowing on the reserve
|
* @dev enables or disables borrowing on the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _enabled true if the borrowing needs to be enabled, false otherwise
|
* @param enabled true if the borrowing needs to be enabled, false otherwise
|
||||||
**/
|
**/
|
||||||
function setBorrowingEnabled(ReserveConfiguration.Map memory _self, bool _enabled) internal {
|
function setBorrowingEnabled(ReserveConfiguration.Map memory self, bool enabled) internal pure {
|
||||||
_self.data = (_self.data & BORROWING_MASK) | (uint256(_enabled ? 1 : 0) << 58);
|
self.data = (self.data & BORROWING_MASK) | (uint256(enabled ? 1 : 0) << 58);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the borrowing state of the reserve
|
* @dev gets the borrowing state of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the borrowing state
|
* @return the borrowing state
|
||||||
**/
|
**/
|
||||||
function getBorrowingEnabled(ReserveConfiguration.Map storage _self)
|
function getBorrowingEnabled(ReserveConfiguration.Map storage self) internal view returns (bool) {
|
||||||
internal
|
return ((self.data & ~BORROWING_MASK) >> 58) != 0;
|
||||||
view
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return ((_self.data & ~BORROWING_MASK) >> 58) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev enables or disables stable rate borrowing on the reserve
|
* @dev enables or disables stable rate borrowing on the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @param _enabled true if the stable rate borrowing needs to be enabled, false otherwise
|
* @param enabled true if the stable rate borrowing needs to be enabled, false otherwise
|
||||||
**/
|
**/
|
||||||
function setStableRateBorrowingEnabled(ReserveConfiguration.Map memory _self, bool _enabled)
|
function setStableRateBorrowingEnabled(ReserveConfiguration.Map memory self, bool enabled)
|
||||||
internal
|
internal pure
|
||||||
{
|
{
|
||||||
_self.data = (_self.data & STABLE_BORROWING_MASK) | (uint256(_enabled ? 1 : 0) << 59);
|
self.data = (self.data & STABLE_BORROWING_MASK) | (uint256(enabled ? 1 : 0) << 59);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the stable rate borrowing state of the reserve
|
* @dev gets the stable rate borrowing state of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the stable rate borrowing state
|
* @return the stable rate borrowing state
|
||||||
**/
|
**/
|
||||||
function getStableRateBorrowingEnabled(ReserveConfiguration.Map storage _self)
|
function getStableRateBorrowingEnabled(ReserveConfiguration.Map storage self)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
return ((_self.data & ~STABLE_BORROWING_MASK) >> 59) != 0;
|
return ((self.data & ~STABLE_BORROWING_MASK) >> 59) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the configuration flags of the reserve
|
* @dev gets the configuration flags of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the state flags representing active, freezed, borrowing enabled, stableRateBorrowing enabled
|
* @return the state flags representing active, freezed, borrowing enabled, stableRateBorrowing enabled
|
||||||
**/
|
**/
|
||||||
function getFlags(ReserveConfiguration.Map storage _self)
|
function getFlags(ReserveConfiguration.Map storage self)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (
|
returns (
|
||||||
|
@ -213,7 +210,7 @@ library ReserveConfiguration {
|
||||||
bool
|
bool
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint256 dataLocal = _self.data;
|
uint256 dataLocal = self.data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(dataLocal & ~ACTIVE_MASK) >> 56 != 0,
|
(dataLocal & ~ACTIVE_MASK) >> 56 != 0,
|
||||||
|
@ -225,10 +222,10 @@ library ReserveConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the configuration paramters of the reserve
|
* @dev gets the configuration paramters of the reserve
|
||||||
* @param _self the reserve configuration
|
* @param self the reserve configuration
|
||||||
* @return the state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals
|
* @return the state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals
|
||||||
**/
|
**/
|
||||||
function getParams(ReserveConfiguration.Map storage _self)
|
function getParams(ReserveConfiguration.Map storage self)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (
|
returns (
|
||||||
|
@ -238,7 +235,7 @@ library ReserveConfiguration {
|
||||||
uint256
|
uint256
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint256 dataLocal = _self.data;
|
uint256 dataLocal = self.data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
dataLocal & ~LTV_MASK,
|
dataLocal & ~LTV_MASK,
|
||||||
|
|
|
@ -18,94 +18,94 @@ library UserConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets if the user is borrowing the reserve identified by _reserveIndex
|
* @dev sets if the user is borrowing the reserve identified by reserveIndex
|
||||||
* @param _self the configuration object
|
* @param self the configuration object
|
||||||
* @param _reserveIndex the index of the reserve in the bitmap
|
* @param reserveIndex the index of the reserve in the bitmap
|
||||||
* @param _borrowing true if the user is borrowing the reserve, false otherwise
|
* @param borrowing true if the user is borrowing the reserve, false otherwise
|
||||||
**/
|
**/
|
||||||
function setBorrowing(
|
function setBorrowing(
|
||||||
UserConfiguration.Map storage _self,
|
UserConfiguration.Map storage self,
|
||||||
uint256 _reserveIndex,
|
uint256 reserveIndex,
|
||||||
bool _borrowing
|
bool borrowing
|
||||||
) internal {
|
) internal {
|
||||||
_self.data =
|
self.data =
|
||||||
(_self.data & ~(1 << (_reserveIndex * 2))) |
|
(self.data & ~(1 << (reserveIndex * 2))) |
|
||||||
(uint256(_borrowing ? 1 : 0) << (_reserveIndex * 2));
|
(uint256(borrowing ? 1 : 0) << (reserveIndex * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets if the user is using as collateral the reserve identified by _reserveIndex
|
* @dev sets if the user is using as collateral the reserve identified by reserveIndex
|
||||||
* @param _self the configuration object
|
* @param self the configuration object
|
||||||
* @param _reserveIndex the index of the reserve in the bitmap
|
* @param reserveIndex the index of the reserve in the bitmap
|
||||||
* @param _usingAsCollateral true if the user is usin the reserve as collateral, false otherwise
|
* @param _usingAsCollateral true if the user is usin the reserve as collateral, false otherwise
|
||||||
**/
|
**/
|
||||||
function setUsingAsCollateral(
|
function setUsingAsCollateral(
|
||||||
UserConfiguration.Map storage _self,
|
UserConfiguration.Map storage self,
|
||||||
uint256 _reserveIndex,
|
uint256 reserveIndex,
|
||||||
bool _usingAsCollateral
|
bool _usingAsCollateral
|
||||||
) internal {
|
) internal {
|
||||||
_self.data =
|
self.data =
|
||||||
(_self.data & ~(1 << (_reserveIndex * 2 + 1))) |
|
(self.data & ~(1 << (reserveIndex * 2 + 1))) |
|
||||||
(uint256(_usingAsCollateral ? 1 : 0) << (_reserveIndex * 2 + 1));
|
(uint256(_usingAsCollateral ? 1 : 0) << (reserveIndex * 2 + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev used to validate if a user has been using the reserve for borrowing or as collateral
|
* @dev used to validate if a user has been using the reserve for borrowing or as collateral
|
||||||
* @param _self the configuration object
|
* @param self the configuration object
|
||||||
* @param _reserveIndex the index of the reserve in the bitmap
|
* @param reserveIndex the index of the reserve in the bitmap
|
||||||
* @return true if the user has been using a reserve for borrowing or as collateral, false otherwise
|
* @return true if the user has been using a reserve for borrowing or as collateral, false otherwise
|
||||||
**/
|
**/
|
||||||
function isUsingAsCollateralOrBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex)
|
function isUsingAsCollateralOrBorrowing(UserConfiguration.Map memory self, uint256 reserveIndex)
|
||||||
internal
|
internal
|
||||||
view
|
pure
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
return (_self.data >> (_reserveIndex * 2)) & 3 != 0;
|
return (self.data >> (reserveIndex * 2)) & 3 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev used to validate if a user has been using the reserve for borrowing
|
* @dev used to validate if a user has been using the reserve for borrowing
|
||||||
* @param _self the configuration object
|
* @param self the configuration object
|
||||||
* @param _reserveIndex the index of the reserve in the bitmap
|
* @param reserveIndex the index of the reserve in the bitmap
|
||||||
* @return true if the user has been using a reserve for borrowing, false otherwise
|
* @return true if the user has been using a reserve for borrowing, false otherwise
|
||||||
**/
|
**/
|
||||||
function isBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex)
|
function isBorrowing(UserConfiguration.Map memory self, uint256 reserveIndex)
|
||||||
internal
|
internal
|
||||||
view
|
pure
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
return (_self.data >> (_reserveIndex * 2)) & 1 != 0;
|
return (self.data >> (reserveIndex * 2)) & 1 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev used to validate if a user has been using the reserve as collateral
|
* @dev used to validate if a user has been using the reserve as collateral
|
||||||
* @param _self the configuration object
|
* @param self the configuration object
|
||||||
* @param _reserveIndex the index of the reserve in the bitmap
|
* @param reserveIndex the index of the reserve in the bitmap
|
||||||
* @return true if the user has been using a reserve as collateral, false otherwise
|
* @return true if the user has been using a reserve as collateral, false otherwise
|
||||||
**/
|
**/
|
||||||
function isUsingAsCollateral(UserConfiguration.Map memory _self, uint256 _reserveIndex)
|
function isUsingAsCollateral(UserConfiguration.Map memory self, uint256 reserveIndex)
|
||||||
internal
|
internal
|
||||||
view
|
pure
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
return (_self.data >> (_reserveIndex * 2 + 1)) & 1 != 0;
|
return (self.data >> (reserveIndex * 2 + 1)) & 1 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev used to validate if a user has been borrowing from any reserve
|
* @dev used to validate if a user has been borrowing from any reserve
|
||||||
* @param _self the configuration object
|
* @param self the configuration object
|
||||||
* @return true if the user has been borrowing any reserve, false otherwise
|
* @return true if the user has been borrowing any reserve, false otherwise
|
||||||
**/
|
**/
|
||||||
function isBorrowingAny(UserConfiguration.Map memory _self) internal view returns (bool) {
|
function isBorrowingAny(UserConfiguration.Map memory self) internal pure returns (bool) {
|
||||||
return _self.data & BORROWING_MASK != 0;
|
return self.data & BORROWING_MASK != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev used to validate if a user has not been using any reserve
|
* @dev used to validate if a user has not been using any reserve
|
||||||
* @param _self the configuration object
|
* @param self the configuration object
|
||||||
* @return true if the user has been borrowing any reserve, false otherwise
|
* @return true if the user has been borrowing any reserve, false otherwise
|
||||||
**/
|
**/
|
||||||
function isEmpty(UserConfiguration.Map memory _self) internal view returns (bool) {
|
function isEmpty(UserConfiguration.Map memory self) internal pure returns (bool) {
|
||||||
return _self.data == 0;
|
return self.data == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,35 +12,35 @@ import {ReserveLogic} from '../logic/ReserveLogic.sol';
|
||||||
library Helpers {
|
library Helpers {
|
||||||
/**
|
/**
|
||||||
* @dev fetches the user current stable and variable debt balances
|
* @dev fetches the user current stable and variable debt balances
|
||||||
* @param _user the user
|
* @param user the user
|
||||||
* @param _reserve the reserve object
|
* @param reserve the reserve object
|
||||||
* @return the stable and variable debt balance
|
* @return the stable and variable debt balance
|
||||||
**/
|
**/
|
||||||
function getUserCurrentDebt(address _user, ReserveLogic.ReserveData storage _reserve)
|
function getUserCurrentDebt(address user, ReserveLogic.ReserveData storage reserve)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint256, uint256)
|
returns (uint256, uint256)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
DebtTokenBase(_reserve.stableDebtTokenAddress).balanceOf(_user),
|
DebtTokenBase(reserve.stableDebtTokenAddress).balanceOf(user),
|
||||||
DebtTokenBase(_reserve.variableDebtTokenAddress).balanceOf(_user)
|
DebtTokenBase(reserve.variableDebtTokenAddress).balanceOf(user)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev fetches the user principal stable and variable debt balances
|
* @dev fetches the user principal stable and variable debt balances
|
||||||
* @param _user the user
|
* @param user the user
|
||||||
* @param _reserve the reserve object
|
* @param reserve the reserve object
|
||||||
* @return the stable and variable debt balance
|
* @return the stable and variable debt balance
|
||||||
**/
|
**/
|
||||||
function getUserPrincipalDebt(address _user, ReserveLogic.ReserveData storage _reserve)
|
function getUserPrincipalDebt(address user, ReserveLogic.ReserveData storage reserve)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint256, uint256)
|
returns (uint256, uint256)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
DebtTokenBase(_reserve.stableDebtTokenAddress).principalBalanceOf(_user),
|
DebtTokenBase(reserve.stableDebtTokenAddress).principalBalanceOf(user),
|
||||||
DebtTokenBase(_reserve.variableDebtTokenAddress).principalBalanceOf(_user)
|
DebtTokenBase(reserve.variableDebtTokenAddress).principalBalanceOf(user)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,23 +43,27 @@ library GenericLogic {
|
||||||
/**
|
/**
|
||||||
* @dev check if a specific balance decrease is allowed
|
* @dev check if a specific balance decrease is allowed
|
||||||
* (i.e. doesn't bring the user borrow position health factor under HEALTH_FACTOR_LIQUIDATION_THRESHOLD)
|
* (i.e. doesn't bring the user borrow position health factor under HEALTH_FACTOR_LIQUIDATION_THRESHOLD)
|
||||||
* @param _reserve the address of the reserve
|
* @param asset the address of the reserve
|
||||||
* @param _user the address of the user
|
* @param user the address of the user
|
||||||
* @param _amount the amount to decrease
|
* @param amount the amount to decrease
|
||||||
|
* @param reservesData the data of all the reserves
|
||||||
|
* @param userConfig the user configuration
|
||||||
|
* @param reserves the list of all the active reserves
|
||||||
|
* @param oracle the address of the oracle contract
|
||||||
* @return true if the decrease of the balance is allowed
|
* @return true if the decrease of the balance is allowed
|
||||||
**/
|
**/
|
||||||
function balanceDecreaseAllowed(
|
function balanceDecreaseAllowed(
|
||||||
address _reserve,
|
address asset,
|
||||||
address _user,
|
address user,
|
||||||
uint256 _amount,
|
uint256 amount,
|
||||||
mapping(address => ReserveLogic.ReserveData) storage _reservesData,
|
mapping(address => ReserveLogic.ReserveData) storage reservesData,
|
||||||
UserConfiguration.Map calldata _userConfig,
|
UserConfiguration.Map calldata userConfig,
|
||||||
address[] calldata _reserves,
|
address[] calldata reserves,
|
||||||
address _oracle
|
address oracle
|
||||||
) external view returns (bool) {
|
) external view returns (bool) {
|
||||||
if (
|
if (
|
||||||
!_userConfig.isBorrowingAny() ||
|
!userConfig.isBorrowingAny() ||
|
||||||
!_userConfig.isUsingAsCollateral(_reservesData[_reserve].index)
|
!userConfig.isUsingAsCollateral(reservesData[asset].index)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +71,7 @@ library GenericLogic {
|
||||||
// Usage of a memory struct of vars to avoid "Stack too deep" errors due to local variables
|
// Usage of a memory struct of vars to avoid "Stack too deep" errors due to local variables
|
||||||
balanceDecreaseAllowedLocalVars memory vars;
|
balanceDecreaseAllowedLocalVars memory vars;
|
||||||
|
|
||||||
(vars.ltv, , , vars.decimals) = _reservesData[_reserve].configuration.getParams();
|
(vars.ltv, , , vars.decimals) = reservesData[asset].configuration.getParams();
|
||||||
|
|
||||||
if (vars.ltv == 0) {
|
if (vars.ltv == 0) {
|
||||||
return true; //if reserve is not used as collateral, no reasons to block the transfer
|
return true; //if reserve is not used as collateral, no reasons to block the transfer
|
||||||
|
@ -79,13 +83,13 @@ library GenericLogic {
|
||||||
,
|
,
|
||||||
vars.currentLiquidationThreshold,
|
vars.currentLiquidationThreshold,
|
||||||
|
|
||||||
) = calculateUserAccountData(_user, _reservesData, _userConfig, _reserves, _oracle);
|
) = calculateUserAccountData(user, reservesData, userConfig, reserves, oracle);
|
||||||
|
|
||||||
if (vars.borrowBalanceETH == 0) {
|
if (vars.borrowBalanceETH == 0) {
|
||||||
return true; //no borrows - no reasons to block the transfer
|
return true; //no borrows - no reasons to block the transfer
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.amountToDecreaseETH = IPriceOracleGetter(_oracle).getAssetPrice(_reserve).mul(_amount).div(
|
vars.amountToDecreaseETH = IPriceOracleGetter(oracle).getAssetPrice(asset).mul(amount).div(
|
||||||
10**vars.decimals
|
10**vars.decimals
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -137,20 +141,20 @@ library GenericLogic {
|
||||||
* @dev calculates the user data across the reserves.
|
* @dev calculates the user data across the reserves.
|
||||||
* this includes the total liquidity/collateral/borrow balances in ETH,
|
* this includes the total liquidity/collateral/borrow balances in ETH,
|
||||||
* the average Loan To Value, the average Liquidation Ratio, and the Health factor.
|
* the average Loan To Value, the average Liquidation Ratio, and the Health factor.
|
||||||
* @param _user the address of the user
|
* @param user the address of the user
|
||||||
* @param _reservesData data of all the reserves
|
* @param reservesData data of all the reserves
|
||||||
* @param _userConfig the configuration of the user
|
* @param userConfig the configuration of the user
|
||||||
* @param _reserves the list of the available reserves
|
* @param reserves the list of the available reserves
|
||||||
* @param _oracle the price oracle address
|
* @param oracle the price oracle address
|
||||||
* @return the total collateral and total borrow balance of the user in ETH, the avg ltv and liquidation threshold and the HF
|
* @return the total collateral and total borrow balance of the user in ETH, the avg ltv and liquidation threshold and the HF
|
||||||
* also the average Ltv, liquidation threshold, and the health factor
|
* also the average Ltv, liquidation threshold, and the health factor
|
||||||
**/
|
**/
|
||||||
function calculateUserAccountData(
|
function calculateUserAccountData(
|
||||||
address _user,
|
address user,
|
||||||
mapping(address => ReserveLogic.ReserveData) storage _reservesData,
|
mapping(address => ReserveLogic.ReserveData) storage reservesData,
|
||||||
UserConfiguration.Map memory _userConfig,
|
UserConfiguration.Map memory userConfig,
|
||||||
address[] memory _reserves,
|
address[] memory reserves,
|
||||||
address _oracle
|
address oracle
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
|
@ -164,26 +168,26 @@ library GenericLogic {
|
||||||
{
|
{
|
||||||
CalculateUserAccountDataVars memory vars;
|
CalculateUserAccountDataVars memory vars;
|
||||||
|
|
||||||
if (_userConfig.isEmpty()) {
|
if (userConfig.isEmpty()) {
|
||||||
return (0, 0, 0, 0, uint256(-1));
|
return (0, 0, 0, 0, uint256(-1));
|
||||||
}
|
}
|
||||||
for (vars.i = 0; vars.i < _reserves.length; vars.i++) {
|
for (vars.i = 0; vars.i < reserves.length; vars.i++) {
|
||||||
if (!_userConfig.isUsingAsCollateralOrBorrowing(vars.i)) {
|
if (!userConfig.isUsingAsCollateralOrBorrowing(vars.i)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.currentReserveAddress = _reserves[vars.i];
|
vars.currentReserveAddress = reserves[vars.i];
|
||||||
ReserveLogic.ReserveData storage currentReserve = _reservesData[vars.currentReserveAddress];
|
ReserveLogic.ReserveData storage currentReserve = reservesData[vars.currentReserveAddress];
|
||||||
|
|
||||||
(vars.ltv, vars.liquidationThreshold, , vars.decimals) = currentReserve
|
(vars.ltv, vars.liquidationThreshold, , vars.decimals) = currentReserve
|
||||||
.configuration
|
.configuration
|
||||||
.getParams();
|
.getParams();
|
||||||
|
|
||||||
vars.tokenUnit = 10**vars.decimals;
|
vars.tokenUnit = 10**vars.decimals;
|
||||||
vars.reserveUnitPrice = IPriceOracleGetter(_oracle).getAssetPrice(vars.currentReserveAddress);
|
vars.reserveUnitPrice = IPriceOracleGetter(oracle).getAssetPrice(vars.currentReserveAddress);
|
||||||
|
|
||||||
if (vars.ltv != 0 && _userConfig.isUsingAsCollateral(vars.i)) {
|
if (vars.ltv != 0 && userConfig.isUsingAsCollateral(vars.i)) {
|
||||||
vars.compoundedLiquidityBalance = IERC20(currentReserve.aTokenAddress).balanceOf(_user);
|
vars.compoundedLiquidityBalance = IERC20(currentReserve.aTokenAddress).balanceOf(user);
|
||||||
|
|
||||||
uint256 liquidityBalanceETH = vars
|
uint256 liquidityBalanceETH = vars
|
||||||
.reserveUnitPrice
|
.reserveUnitPrice
|
||||||
|
@ -198,12 +202,12 @@ library GenericLogic {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_userConfig.isBorrowing(vars.i)) {
|
if (userConfig.isBorrowing(vars.i)) {
|
||||||
vars.compoundedBorrowBalance = IERC20(currentReserve.stableDebtTokenAddress).balanceOf(
|
vars.compoundedBorrowBalance = IERC20(currentReserve.stableDebtTokenAddress).balanceOf(
|
||||||
_user
|
user
|
||||||
);
|
);
|
||||||
vars.compoundedBorrowBalance = vars.compoundedBorrowBalance.add(
|
vars.compoundedBorrowBalance = vars.compoundedBorrowBalance.add(
|
||||||
IERC20(currentReserve.variableDebtTokenAddress).balanceOf(_user)
|
IERC20(currentReserve.variableDebtTokenAddress).balanceOf(user)
|
||||||
);
|
);
|
||||||
|
|
||||||
vars.totalBorrowBalanceETH = vars.totalBorrowBalanceETH.add(
|
vars.totalBorrowBalanceETH = vars.totalBorrowBalanceETH.add(
|
||||||
|
@ -244,7 +248,7 @@ library GenericLogic {
|
||||||
uint256 collateralBalanceETH,
|
uint256 collateralBalanceETH,
|
||||||
uint256 borrowBalanceETH,
|
uint256 borrowBalanceETH,
|
||||||
uint256 liquidationThreshold
|
uint256 liquidationThreshold
|
||||||
) internal view returns (uint256) {
|
) internal pure returns (uint256) {
|
||||||
if (borrowBalanceETH == 0) return uint256(-1);
|
if (borrowBalanceETH == 0) return uint256(-1);
|
||||||
|
|
||||||
return (collateralBalanceETH.percentMul(liquidationThreshold)).wadDiv(borrowBalanceETH);
|
return (collateralBalanceETH.percentMul(liquidationThreshold)).wadDiv(borrowBalanceETH);
|
||||||
|
@ -263,7 +267,7 @@ library GenericLogic {
|
||||||
uint256 collateralBalanceETH,
|
uint256 collateralBalanceETH,
|
||||||
uint256 borrowBalanceETH,
|
uint256 borrowBalanceETH,
|
||||||
uint256 ltv
|
uint256 ltv
|
||||||
) external view returns (uint256) {
|
) internal pure returns (uint256) {
|
||||||
uint256 availableBorrowsETH = collateralBalanceETH.percentMul(ltv); //ltv is in percentage
|
uint256 availableBorrowsETH = collateralBalanceETH.percentMul(ltv); //ltv is in percentage
|
||||||
|
|
||||||
if (availableBorrowsETH < borrowBalanceETH) {
|
if (availableBorrowsETH < borrowBalanceETH) {
|
||||||
|
|
|
@ -23,7 +23,6 @@ library ReserveLogic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Emitted when the state of a reserve is updated
|
* @dev Emitted when the state of a reserve is updated
|
||||||
* @dev NOTE: This event replaces the Deprecated ReserveUpdated() event, which didn't emit the average stable borrow rate
|
|
||||||
* @param reserve the address of the reserve
|
* @param reserve the address of the reserve
|
||||||
* @param liquidityRate the new liquidity rate
|
* @param liquidityRate the new liquidity rate
|
||||||
* @param stableBorrowRate the new stable borrow rate
|
* @param stableBorrowRate the new stable borrow rate
|
||||||
|
@ -50,7 +49,7 @@ library ReserveLogic {
|
||||||
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
|
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
|
||||||
struct ReserveData {
|
struct ReserveData {
|
||||||
//the liquidity index. Expressed in ray
|
//the liquidity index. Expressed in ray
|
||||||
uint256 lastLiquidityCumulativeIndex;
|
uint256 lastLiquidityIndex;
|
||||||
//the current supply rate. Expressed in ray
|
//the current supply rate. Expressed in ray
|
||||||
uint256 currentLiquidityRate;
|
uint256 currentLiquidityRate;
|
||||||
//the current variable borrow rate. Expressed in ray
|
//the current variable borrow rate. Expressed in ray
|
||||||
|
@ -58,7 +57,7 @@ library ReserveLogic {
|
||||||
//the current stable borrow rate. Expressed in ray
|
//the current stable borrow rate. Expressed in ray
|
||||||
uint256 currentStableBorrowRate;
|
uint256 currentStableBorrowRate;
|
||||||
//variable borrow index. Expressed in ray
|
//variable borrow index. Expressed in ray
|
||||||
uint256 lastVariableBorrowCumulativeIndex;
|
uint256 lastVariableBorrowIndex;
|
||||||
//stores the reserve configuration
|
//stores the reserve configuration
|
||||||
ReserveConfiguration.Map configuration;
|
ReserveConfiguration.Map configuration;
|
||||||
address aTokenAddress;
|
address aTokenAddress;
|
||||||
|
@ -74,21 +73,21 @@ library ReserveLogic {
|
||||||
* @dev returns the ongoing normalized income for the reserve.
|
* @dev returns the ongoing normalized income for the reserve.
|
||||||
* a value of 1e27 means there is no income. As time passes, the income is accrued.
|
* a value of 1e27 means there is no income. As time passes, the income is accrued.
|
||||||
* A value of 2*1e27 means for each unit of assset two units of income have been accrued.
|
* A value of 2*1e27 means for each unit of assset two units of income have been accrued.
|
||||||
* @param _reserve the reserve object
|
* @param reserve the reserve object
|
||||||
* @return the normalized income. expressed in ray
|
* @return the normalized income. expressed in ray
|
||||||
**/
|
**/
|
||||||
function getNormalizedIncome(ReserveData storage _reserve) internal view returns (uint256) {
|
function getNormalizedIncome(ReserveData storage reserve) internal view returns (uint256) {
|
||||||
uint40 timestamp = _reserve.lastUpdateTimestamp;
|
uint40 timestamp = reserve.lastUpdateTimestamp;
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
if (timestamp == uint40(block.timestamp)) {
|
if (timestamp == uint40(block.timestamp)) {
|
||||||
//if the index was updated in the same block, no need to perform any calculation
|
//if the index was updated in the same block, no need to perform any calculation
|
||||||
return _reserve.lastLiquidityCumulativeIndex;
|
return reserve.lastLiquidityIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 cumulated = MathUtils
|
uint256 cumulated = MathUtils
|
||||||
.calculateLinearInterest(_reserve.currentLiquidityRate, timestamp)
|
.calculateLinearInterest(reserve.currentLiquidityRate, timestamp)
|
||||||
.rayMul(_reserve.lastLiquidityCumulativeIndex);
|
.rayMul(reserve.lastLiquidityIndex);
|
||||||
|
|
||||||
return cumulated;
|
return cumulated;
|
||||||
}
|
}
|
||||||
|
@ -97,21 +96,21 @@ library ReserveLogic {
|
||||||
* @dev returns the ongoing normalized variable debt for the reserve.
|
* @dev returns the ongoing normalized variable debt for the reserve.
|
||||||
* a value of 1e27 means there is no debt. As time passes, the income is accrued.
|
* a value of 1e27 means there is no debt. As time passes, the income is accrued.
|
||||||
* A value of 2*1e27 means that the debt of the reserve is double the initial amount.
|
* A value of 2*1e27 means that the debt of the reserve is double the initial amount.
|
||||||
* @param _reserve the reserve object
|
* @param reserve the reserve object
|
||||||
* @return the normalized variable debt. expressed in ray
|
* @return the normalized variable debt. expressed in ray
|
||||||
**/
|
**/
|
||||||
function getNormalizedDebt(ReserveData storage _reserve) internal view returns (uint256) {
|
function getNormalizedDebt(ReserveData storage reserve) internal view returns (uint256) {
|
||||||
uint40 timestamp = _reserve.lastUpdateTimestamp;
|
uint40 timestamp = reserve.lastUpdateTimestamp;
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
if (timestamp == uint40(block.timestamp)) {
|
if (timestamp == uint40(block.timestamp)) {
|
||||||
//if the index was updated in the same block, no need to perform any calculation
|
//if the index was updated in the same block, no need to perform any calculation
|
||||||
return _reserve.lastVariableBorrowCumulativeIndex;
|
return reserve.lastVariableBorrowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 cumulated = MathUtils
|
uint256 cumulated = MathUtils
|
||||||
.calculateCompoundedInterest(_reserve.currentVariableBorrowRate, timestamp)
|
.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp)
|
||||||
.rayMul(_reserve.lastVariableBorrowCumulativeIndex);
|
.rayMul(reserve.lastVariableBorrowIndex);
|
||||||
|
|
||||||
return cumulated;
|
return cumulated;
|
||||||
}
|
}
|
||||||
|
@ -119,153 +118,128 @@ library ReserveLogic {
|
||||||
/**
|
/**
|
||||||
* @dev Updates the liquidity cumulative index Ci and variable borrow cumulative index Bvc. Refer to the whitepaper for
|
* @dev Updates the liquidity cumulative index Ci and variable borrow cumulative index Bvc. Refer to the whitepaper for
|
||||||
* a formal specification.
|
* a formal specification.
|
||||||
* @param _self the reserve object
|
* @param reserve the reserve object
|
||||||
**/
|
**/
|
||||||
function updateCumulativeIndexesAndTimestamp(ReserveData storage _self) internal {
|
function updateCumulativeIndexesAndTimestamp(ReserveData storage reserve) internal {
|
||||||
//only cumulating if there is any income being produced
|
//only cumulating if there is any income being produced
|
||||||
if (
|
if (
|
||||||
IERC20(_self.variableDebtTokenAddress).totalSupply() > 0 ||
|
IERC20(reserve.variableDebtTokenAddress).totalSupply() > 0 ||
|
||||||
IERC20(_self.stableDebtTokenAddress).totalSupply() > 0
|
IERC20(reserve.stableDebtTokenAddress).totalSupply() > 0
|
||||||
) {
|
) {
|
||||||
uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest(
|
uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest(
|
||||||
_self.currentLiquidityRate,
|
reserve.currentLiquidityRate,
|
||||||
_self.lastUpdateTimestamp
|
reserve.lastUpdateTimestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
_self.lastLiquidityCumulativeIndex = cumulatedLiquidityInterest.rayMul(
|
reserve.lastLiquidityIndex = cumulatedLiquidityInterest.rayMul(
|
||||||
_self.lastLiquidityCumulativeIndex
|
reserve.lastLiquidityIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest(
|
uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest(
|
||||||
_self.currentVariableBorrowRate,
|
reserve.currentVariableBorrowRate,
|
||||||
_self.lastUpdateTimestamp
|
reserve.lastUpdateTimestamp
|
||||||
);
|
);
|
||||||
_self.lastVariableBorrowCumulativeIndex = cumulatedVariableBorrowInterest.rayMul(
|
reserve.lastVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(
|
||||||
_self.lastVariableBorrowCumulativeIndex
|
reserve.lastVariableBorrowIndex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
_self.lastUpdateTimestamp = uint40(block.timestamp);
|
reserve.lastUpdateTimestamp = uint40(block.timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev accumulates a predefined amount of asset to the reserve as a fixed, one time income. Used for example to accumulate
|
* @dev accumulates a predefined amount of asset to the reserve as a fixed, one time income. Used for example to accumulate
|
||||||
* the flashloan fee to the reserve, and spread it through the depositors.
|
* the flashloan fee to the reserve, and spread it through the depositors.
|
||||||
* @param _self the reserve object
|
* @param reserve the reserve object
|
||||||
* @param _totalLiquidity the total liquidity available in the reserve
|
* @param totalLiquidity the total liquidity available in the reserve
|
||||||
* @param _amount the amount to accomulate
|
* @param amount the amount to accomulate
|
||||||
**/
|
**/
|
||||||
function cumulateToLiquidityIndex(
|
function cumulateToLiquidityIndex(
|
||||||
ReserveData storage _self,
|
ReserveData storage reserve,
|
||||||
uint256 _totalLiquidity,
|
uint256 totalLiquidity,
|
||||||
uint256 _amount
|
uint256 amount
|
||||||
) internal {
|
) internal {
|
||||||
uint256 amountToLiquidityRatio = _amount.wadToRay().rayDiv(_totalLiquidity.wadToRay());
|
uint256 amountToLiquidityRatio = amount.wadToRay().rayDiv(totalLiquidity.wadToRay());
|
||||||
|
|
||||||
uint256 cumulatedLiquidity = amountToLiquidityRatio.add(WadRayMath.ray());
|
uint256 cumulatedLiquidity = amountToLiquidityRatio.add(WadRayMath.ray());
|
||||||
|
|
||||||
_self.lastLiquidityCumulativeIndex = cumulatedLiquidity.rayMul(
|
reserve.lastLiquidityIndex = cumulatedLiquidity.rayMul(
|
||||||
_self.lastLiquidityCumulativeIndex
|
reserve.lastLiquidityIndex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev initializes a reserve
|
* @dev initializes a reserve
|
||||||
* @param _self the reserve object
|
* @param reserve the reserve object
|
||||||
* @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 init(
|
function init(
|
||||||
ReserveData storage _self,
|
ReserveData storage reserve,
|
||||||
address _aTokenAddress,
|
address aTokenAddress,
|
||||||
address _stableDebtAddress,
|
address stableDebtTokenAddress,
|
||||||
address _variableDebtAddress,
|
address variableDebtTokenAddress,
|
||||||
address _interestRateStrategyAddress
|
address interestRateStrategyAddress
|
||||||
) external {
|
) external {
|
||||||
require(_self.aTokenAddress == address(0), 'Reserve has already been initialized');
|
require(reserve.aTokenAddress == address(0), 'Reserve has already been initialized');
|
||||||
if (_self.lastLiquidityCumulativeIndex == 0) {
|
if (reserve.lastLiquidityIndex == 0) {
|
||||||
//if the reserve has not been initialized yet
|
//if the reserve has not been initialized yet
|
||||||
_self.lastLiquidityCumulativeIndex = WadRayMath.ray();
|
reserve.lastLiquidityIndex = WadRayMath.ray();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_self.lastVariableBorrowCumulativeIndex == 0) {
|
if (reserve.lastVariableBorrowIndex == 0) {
|
||||||
_self.lastVariableBorrowCumulativeIndex = WadRayMath.ray();
|
reserve.lastVariableBorrowIndex = WadRayMath.ray();
|
||||||
}
|
}
|
||||||
|
|
||||||
_self.aTokenAddress = _aTokenAddress;
|
reserve.aTokenAddress = aTokenAddress;
|
||||||
_self.stableDebtTokenAddress = _stableDebtAddress;
|
reserve.stableDebtTokenAddress = stableDebtTokenAddress;
|
||||||
_self.variableDebtTokenAddress = _variableDebtAddress;
|
reserve.variableDebtTokenAddress = variableDebtTokenAddress;
|
||||||
_self.interestRateStrategyAddress = _interestRateStrategyAddress;
|
reserve.interestRateStrategyAddress = interestRateStrategyAddress;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev updates the state of the core as a result of a flashloan action
|
|
||||||
* @param _reserve the address of the reserve in which the flashloan is happening
|
|
||||||
* @param _income the income of the protocol as a result of the action
|
|
||||||
**/
|
|
||||||
function updateStateOnFlashLoan(
|
|
||||||
ReserveData storage _reserve,
|
|
||||||
address _reserveAddress,
|
|
||||||
uint256 _availableLiquidityBefore,
|
|
||||||
uint256 _income
|
|
||||||
) external {
|
|
||||||
//compounding the cumulated interest
|
|
||||||
_reserve.updateCumulativeIndexesAndTimestamp();
|
|
||||||
|
|
||||||
uint256 totalLiquidityBefore = _availableLiquidityBefore
|
|
||||||
.add(IERC20(_reserve.variableDebtTokenAddress).totalSupply())
|
|
||||||
.add(IERC20(_reserve.stableDebtTokenAddress).totalSupply());
|
|
||||||
|
|
||||||
//compounding the received fee into the reserve
|
|
||||||
_reserve.cumulateToLiquidityIndex(totalLiquidityBefore, _income);
|
|
||||||
|
|
||||||
//refresh interest rates
|
|
||||||
updateInterestRates(_reserve, _reserveAddress, _income, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Updates the reserve current stable borrow rate Rf, the current variable borrow rate Rv and the current liquidity rate Rl.
|
* @dev Updates the reserve current stable borrow rate Rf, the current variable borrow rate Rv and the current liquidity rate Rl.
|
||||||
* Also updates the lastUpdateTimestamp value. Please refer to the whitepaper for further information.
|
* Also updates the lastUpdateTimestamp value. Please refer to the whitepaper for further information.
|
||||||
* @param _reserve the address of the reserve to be updated
|
* @param reserve the address of the reserve to be updated
|
||||||
* @param _liquidityAdded the amount of liquidity added to the protocol (deposit or repay) in the previous action
|
* @param liquidityAdded the amount of liquidity added to the protocol (deposit or repay) in the previous action
|
||||||
* @param _liquidityTaken the amount of liquidity taken from the protocol (redeem or borrow)
|
* @param liquidityTaken the amount of liquidity taken from the protocol (redeem or borrow)
|
||||||
**/
|
**/
|
||||||
function updateInterestRates(
|
function updateInterestRates(
|
||||||
ReserveData storage _reserve,
|
ReserveData storage reserve,
|
||||||
address _reserveAddress,
|
address reserveAddress,
|
||||||
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 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),
|
balance.add(liquidityAdded).sub(liquidityTaken),
|
||||||
IERC20(_reserve.stableDebtTokenAddress).totalSupply(),
|
IERC20(reserve.stableDebtTokenAddress).totalSupply(),
|
||||||
IERC20(_reserve.variableDebtTokenAddress).totalSupply(),
|
IERC20(reserve.variableDebtTokenAddress).totalSupply(),
|
||||||
currentAvgStableRate
|
currentAvgStableRate
|
||||||
);
|
);
|
||||||
|
|
||||||
_reserve.currentLiquidityRate = newLiquidityRate;
|
reserve.currentLiquidityRate = newLiquidityRate;
|
||||||
_reserve.currentStableBorrowRate = newStableRate;
|
reserve.currentStableBorrowRate = newStableRate;
|
||||||
_reserve.currentVariableBorrowRate = newVariableRate;
|
reserve.currentVariableBorrowRate = newVariableRate;
|
||||||
|
|
||||||
emit ReserveDataUpdated(
|
emit ReserveDataUpdated(
|
||||||
_reserveAddress,
|
reserveAddress,
|
||||||
newLiquidityRate,
|
newLiquidityRate,
|
||||||
newStableRate,
|
newStableRate,
|
||||||
currentAvgStableRate,
|
currentAvgStableRate,
|
||||||
newVariableRate,
|
newVariableRate,
|
||||||
_reserve.lastLiquidityCumulativeIndex,
|
reserve.lastLiquidityIndex,
|
||||||
_reserve.lastVariableBorrowCumulativeIndex
|
reserve.lastVariableBorrowIndex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,54 +29,54 @@ library ValidationLogic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev validates a deposit.
|
* @dev validates a deposit.
|
||||||
* @param _reserve the reserve state on which the user is depositing
|
* @param reserve the reserve state on which the user is depositing
|
||||||
* @param _amount the amount to be deposited
|
* @param amount the amount to be deposited
|
||||||
*/
|
*/
|
||||||
function validateDeposit(ReserveLogic.ReserveData storage _reserve, uint256 _amount)
|
function validateDeposit(ReserveLogic.ReserveData storage reserve, uint256 amount)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
{
|
{
|
||||||
(bool isActive, bool isFreezed, , ) = _reserve.configuration.getFlags();
|
(bool isActive, bool isFreezed, , ) = reserve.configuration.getFlags();
|
||||||
|
|
||||||
require(_amount > 0, 'Amount must be greater than 0');
|
require(amount > 0, 'Amount must be greater than 0');
|
||||||
require(isActive, 'Action requires an active reserve');
|
require(isActive, 'Action requires an active reserve');
|
||||||
require(!isFreezed, 'Action requires an unfreezed reserve');
|
require(!isFreezed, 'Action requires an unfreezed reserve');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev validates a withdraw action.
|
* @dev validates a withdraw action.
|
||||||
* @param _reserveAddress the address of the reserve
|
* @param reserveAddress the address of the reserve
|
||||||
* @param _aTokenAddress the address of the aToken for the reserve
|
* @param aTokenAddress the address of the aToken for the reserve
|
||||||
* @param _amount the amount to be withdrawn
|
* @param amount the amount to be withdrawn
|
||||||
* @param _userBalance the balance of the user
|
* @param userBalance the balance of the user
|
||||||
*/
|
*/
|
||||||
function validateWithdraw(
|
function validateWithdraw(
|
||||||
address _reserveAddress,
|
address reserveAddress,
|
||||||
address _aTokenAddress,
|
address aTokenAddress,
|
||||||
uint256 _amount,
|
uint256 amount,
|
||||||
uint256 _userBalance,
|
uint256 userBalance,
|
||||||
mapping(address => ReserveLogic.ReserveData) storage _reservesData,
|
mapping(address => ReserveLogic.ReserveData) storage reservesData,
|
||||||
UserConfiguration.Map storage _userConfig,
|
UserConfiguration.Map storage userConfig,
|
||||||
address[] calldata _reserves,
|
address[] calldata reserves,
|
||||||
address _oracle
|
address oracle
|
||||||
) external view {
|
) external view {
|
||||||
require(_amount > 0, 'Amount must be greater than 0');
|
require(amount > 0, 'Amount must be greater than 0');
|
||||||
|
|
||||||
uint256 currentAvailableLiquidity = IERC20(_reserveAddress).balanceOf(address(_aTokenAddress));
|
uint256 currentAvailableLiquidity = IERC20(reserveAddress).balanceOf(address(aTokenAddress));
|
||||||
|
|
||||||
require(currentAvailableLiquidity >= _amount, '4');
|
require(currentAvailableLiquidity >= amount, '4');
|
||||||
|
|
||||||
require(_amount <= _userBalance, 'User cannot withdraw more than the available balance');
|
require(amount <= userBalance, 'User cannot withdraw more than the available balance');
|
||||||
|
|
||||||
require(
|
require(
|
||||||
GenericLogic.balanceDecreaseAllowed(
|
GenericLogic.balanceDecreaseAllowed(
|
||||||
_reserveAddress,
|
reserveAddress,
|
||||||
msg.sender,
|
msg.sender,
|
||||||
_userBalance,
|
userBalance,
|
||||||
_reservesData,
|
reservesData,
|
||||||
_userConfig,
|
userConfig,
|
||||||
_reserves,
|
reserves,
|
||||||
_oracle
|
oracle
|
||||||
),
|
),
|
||||||
'Transfer cannot be allowed.'
|
'Transfer cannot be allowed.'
|
||||||
);
|
);
|
||||||
|
@ -105,29 +105,29 @@ library ValidationLogic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev validates a borrow.
|
* @dev validates a borrow.
|
||||||
* @param _reserve the reserve state from which the user is borrowing
|
* @param reserve the reserve state from which the user is borrowing
|
||||||
* @param _reserveAddress the address of the reserve
|
* @param reserveAddress the address of the reserve
|
||||||
* @param _amount the amount to be borrowed
|
* @param amount the amount to be borrowed
|
||||||
* @param _amountInETH the amount to be borrowed, in ETH
|
* @param amountInETH the amount to be borrowed, in ETH
|
||||||
* @param _interestRateMode the interest rate mode at which the user is borrowing
|
* @param interestRateMode the interest rate mode at which the user is borrowing
|
||||||
* @param _maxStableLoanPercent the max amount of the liquidity that can be borrowed at stable rate, in percentage
|
* @param maxStableLoanPercent the max amount of the liquidity that can be borrowed at stable rate, in percentage
|
||||||
* @param _reservesData the state of all the reserves
|
* @param reservesData the state of all the reserves
|
||||||
* @param _userConfig the state of the user for the specific reserve
|
* @param userConfig the state of the user for the specific reserve
|
||||||
* @param _reserves the addresses of all the active reserves
|
* @param reserves the addresses of all the active reserves
|
||||||
* @param _oracle the price oracle
|
* @param oracle the price oracle
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function validateBorrow(
|
function validateBorrow(
|
||||||
ReserveLogic.ReserveData storage _reserve,
|
ReserveLogic.ReserveData storage reserve,
|
||||||
address _reserveAddress,
|
address reserveAddress,
|
||||||
uint256 _amount,
|
uint256 amount,
|
||||||
uint256 _amountInETH,
|
uint256 amountInETH,
|
||||||
uint256 _interestRateMode,
|
uint256 interestRateMode,
|
||||||
uint256 _maxStableLoanPercent,
|
uint256 maxStableLoanPercent,
|
||||||
mapping(address => ReserveLogic.ReserveData) storage _reservesData,
|
mapping(address => ReserveLogic.ReserveData) storage reservesData,
|
||||||
UserConfiguration.Map storage _userConfig,
|
UserConfiguration.Map storage userConfig,
|
||||||
address[] calldata _reserves,
|
address[] calldata reserves,
|
||||||
address _oracle
|
address oracle
|
||||||
) external view {
|
) external view {
|
||||||
ValidateBorrowLocalVars memory vars;
|
ValidateBorrowLocalVars memory vars;
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ library ValidationLogic {
|
||||||
vars.isFreezed,
|
vars.isFreezed,
|
||||||
vars.borrowingEnabled,
|
vars.borrowingEnabled,
|
||||||
vars.stableRateBorrowingEnabled
|
vars.stableRateBorrowingEnabled
|
||||||
) = _reserve.configuration.getFlags();
|
) = reserve.configuration.getFlags();
|
||||||
|
|
||||||
require(vars.isActive, 'Action requires an active reserve');
|
require(vars.isActive, 'Action requires an active reserve');
|
||||||
require(!vars.isFreezed, 'Action requires an unfreezed reserve');
|
require(!vars.isFreezed, 'Action requires an unfreezed reserve');
|
||||||
|
@ -145,15 +145,15 @@ library ValidationLogic {
|
||||||
|
|
||||||
//validate interest rate mode
|
//validate interest rate mode
|
||||||
require(
|
require(
|
||||||
uint256(ReserveLogic.InterestRateMode.VARIABLE) == _interestRateMode ||
|
uint256(ReserveLogic.InterestRateMode.VARIABLE) == interestRateMode ||
|
||||||
uint256(ReserveLogic.InterestRateMode.STABLE) == _interestRateMode,
|
uint256(ReserveLogic.InterestRateMode.STABLE) == interestRateMode,
|
||||||
'Invalid interest rate mode selected'
|
'Invalid interest rate mode selected'
|
||||||
);
|
);
|
||||||
|
|
||||||
//check that the amount is available in the reserve
|
//check that the amount is available in the reserve
|
||||||
vars.availableLiquidity = IERC20(_reserveAddress).balanceOf(address(_reserve.aTokenAddress));
|
vars.availableLiquidity = IERC20(reserveAddress).balanceOf(address(reserve.aTokenAddress));
|
||||||
|
|
||||||
require(vars.availableLiquidity >= _amount, '7');
|
require(vars.availableLiquidity >= amount, '7');
|
||||||
|
|
||||||
(
|
(
|
||||||
vars.userCollateralBalanceETH,
|
vars.userCollateralBalanceETH,
|
||||||
|
@ -163,10 +163,10 @@ library ValidationLogic {
|
||||||
vars.healthFactor
|
vars.healthFactor
|
||||||
) = GenericLogic.calculateUserAccountData(
|
) = GenericLogic.calculateUserAccountData(
|
||||||
msg.sender,
|
msg.sender,
|
||||||
_reservesData,
|
reservesData,
|
||||||
_userConfig,
|
userConfig,
|
||||||
_reserves,
|
reserves,
|
||||||
_oracle
|
oracle
|
||||||
);
|
);
|
||||||
|
|
||||||
require(vars.userCollateralBalanceETH > 0, 'The collateral balance is 0');
|
require(vars.userCollateralBalanceETH > 0, 'The collateral balance is 0');
|
||||||
|
@ -174,7 +174,7 @@ library ValidationLogic {
|
||||||
require(vars.healthFactor > GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD, '8');
|
require(vars.healthFactor > GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD, '8');
|
||||||
|
|
||||||
//add the current already borrowed amount to the amount requested to calculate the total collateral needed.
|
//add the current already borrowed amount to the amount requested to calculate the total collateral needed.
|
||||||
vars.amountOfCollateralNeededETH = vars.userBorrowBalanceETH.add(_amountInETH).percentDiv(
|
vars.amountOfCollateralNeededETH = vars.userBorrowBalanceETH.add(amountInETH).percentDiv(
|
||||||
vars.currentLtv
|
vars.currentLtv
|
||||||
); //LTV is calculated in percentage
|
); //LTV is calculated in percentage
|
||||||
|
|
||||||
|
@ -198,88 +198,84 @@ library ValidationLogic {
|
||||||
require(vars.stableRateBorrowingEnabled, '11');
|
require(vars.stableRateBorrowingEnabled, '11');
|
||||||
|
|
||||||
require(
|
require(
|
||||||
!_userConfig.isUsingAsCollateral(_reserve.index) ||
|
!userConfig.isUsingAsCollateral(reserve.index) ||
|
||||||
_reserve.configuration.getLtv() == 0 ||
|
reserve.configuration.getLtv() == 0 ||
|
||||||
_amount > IERC20(_reserve.aTokenAddress).balanceOf(msg.sender),
|
amount > IERC20(reserve.aTokenAddress).balanceOf(msg.sender),
|
||||||
'12'
|
'12'
|
||||||
);
|
);
|
||||||
|
|
||||||
//calculate the max available loan size in stable rate mode as a percentage of the
|
//calculate the max available loan size in stable rate mode as a percentage of the
|
||||||
//available liquidity
|
//available liquidity
|
||||||
uint256 maxLoanSizeStable = vars.availableLiquidity.percentMul(_maxStableLoanPercent);
|
uint256 maxLoanSizeStable = vars.availableLiquidity.percentMul(maxStableLoanPercent);
|
||||||
|
|
||||||
require(_amount <= maxLoanSizeStable, '13');
|
require(amount <= maxLoanSizeStable, '13');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev validates a repay.
|
* @dev validates a repay.
|
||||||
* @param _reserve the reserve state from which the user is repaying
|
* @param reserve the reserve state from which the user is repaying
|
||||||
* @param _reserveAddress the address of the reserve
|
* @param amountSent the amount sent for the repayment. Can be an actual value or uint(-1)
|
||||||
* @param _amountSent the amount sent for the repayment. Can be an actual value or uint(-1)
|
* @param onBehalfOf the address of the user msg.sender is repaying for
|
||||||
* @param _onBehalfOf the address of the user msg.sender is repaying for
|
* @param stableDebt the borrow balance of the user
|
||||||
* @param _stableBorrowBalance the borrow balance of the user
|
* @param variableDebt the borrow balance of the user
|
||||||
* @param _variableBorrowBalance the borrow balance of the user
|
|
||||||
* @param _actualPaybackAmount the actual amount being repaid
|
|
||||||
*/
|
*/
|
||||||
function validateRepay(
|
function validateRepay(
|
||||||
ReserveLogic.ReserveData storage _reserve,
|
ReserveLogic.ReserveData storage reserve,
|
||||||
address _reserveAddress,
|
uint256 amountSent,
|
||||||
uint256 _amountSent,
|
ReserveLogic.InterestRateMode rateMode,
|
||||||
ReserveLogic.InterestRateMode _rateMode,
|
address onBehalfOf,
|
||||||
address _onBehalfOf,
|
uint256 stableDebt,
|
||||||
uint256 _stableBorrowBalance,
|
uint256 variableDebt
|
||||||
uint256 _variableBorrowBalance,
|
|
||||||
uint256 _actualPaybackAmount
|
|
||||||
) external view {
|
) external view {
|
||||||
bool isActive = _reserve.configuration.getActive();
|
bool isActive = reserve.configuration.getActive();
|
||||||
|
|
||||||
require(isActive, 'Action requires an active reserve');
|
require(isActive, 'Action requires an active reserve');
|
||||||
|
|
||||||
require(_amountSent > 0, 'Amount must be greater than 0');
|
require(amountSent > 0, 'Amount must be greater than 0');
|
||||||
|
|
||||||
require(
|
require(
|
||||||
(_stableBorrowBalance > 0 &&
|
(stableDebt > 0 &&
|
||||||
ReserveLogic.InterestRateMode(_rateMode) == ReserveLogic.InterestRateMode.STABLE) ||
|
ReserveLogic.InterestRateMode(rateMode) == ReserveLogic.InterestRateMode.STABLE) ||
|
||||||
(_variableBorrowBalance > 0 &&
|
(variableDebt > 0 &&
|
||||||
ReserveLogic.InterestRateMode(_rateMode) == ReserveLogic.InterestRateMode.VARIABLE),
|
ReserveLogic.InterestRateMode(rateMode) == ReserveLogic.InterestRateMode.VARIABLE),
|
||||||
'16'
|
'16'
|
||||||
);
|
);
|
||||||
|
|
||||||
require(
|
require(
|
||||||
_amountSent != uint256(-1) || msg.sender == _onBehalfOf,
|
amountSent != uint256(-1) || msg.sender == onBehalfOf,
|
||||||
'To repay on behalf of an user an explicit amount to repay is needed'
|
'To repay on behalf of an user an explicit amount to repay is needed'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev validates a swap of borrow rate mode.
|
* @dev validates a swap of borrow rate mode.
|
||||||
* @param _reserve the reserve state on which the user is swapping the rate
|
* @param reserve the reserve state on which the user is swapping the rate
|
||||||
* @param _userConfig the user reserves configuration
|
* @param userConfig the user reserves configuration
|
||||||
* @param _stableBorrowBalance the stable borrow balance of the user
|
* @param stableBorrowBalance the stable borrow balance of the user
|
||||||
* @param _variableBorrowBalance the stable borrow balance of the user
|
* @param variableBorrowBalance the stable borrow balance of the user
|
||||||
* @param _currentRateMode the rate mode of the borrow
|
* @param currentRateMode the rate mode of the borrow
|
||||||
*/
|
*/
|
||||||
function validateSwapRateMode(
|
function validateSwapRateMode(
|
||||||
ReserveLogic.ReserveData storage _reserve,
|
ReserveLogic.ReserveData storage reserve,
|
||||||
UserConfiguration.Map storage _userConfig,
|
UserConfiguration.Map storage userConfig,
|
||||||
uint256 _stableBorrowBalance,
|
uint256 stableBorrowBalance,
|
||||||
uint256 _variableBorrowBalance,
|
uint256 variableBorrowBalance,
|
||||||
ReserveLogic.InterestRateMode _currentRateMode
|
ReserveLogic.InterestRateMode currentRateMode
|
||||||
) external view {
|
) external view {
|
||||||
(bool isActive, bool isFreezed, , bool stableRateEnabled) = _reserve.configuration.getFlags();
|
(bool isActive, bool isFreezed, , bool stableRateEnabled) = reserve.configuration.getFlags();
|
||||||
|
|
||||||
require(isActive, 'Action requires an active reserve');
|
require(isActive, 'Action requires an active reserve');
|
||||||
require(!isFreezed, 'Action requires an unfreezed reserve');
|
require(!isFreezed, 'Action requires an unfreezed reserve');
|
||||||
|
|
||||||
if (_currentRateMode == ReserveLogic.InterestRateMode.STABLE) {
|
if (currentRateMode == ReserveLogic.InterestRateMode.STABLE) {
|
||||||
require(
|
require(
|
||||||
_stableBorrowBalance > 0,
|
stableBorrowBalance > 0,
|
||||||
'User does not have a stable rate loan in progress on this reserve'
|
'User does not have a stable rate loan in progress on this reserve'
|
||||||
);
|
);
|
||||||
} else if (_currentRateMode == ReserveLogic.InterestRateMode.VARIABLE) {
|
} else if (currentRateMode == ReserveLogic.InterestRateMode.VARIABLE) {
|
||||||
require(
|
require(
|
||||||
_variableBorrowBalance > 0,
|
variableBorrowBalance > 0,
|
||||||
'User does not have a variable rate loan in progress on this reserve'
|
'User does not have a variable rate loan in progress on this reserve'
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
|
@ -292,10 +288,10 @@ library ValidationLogic {
|
||||||
require(stableRateEnabled, '11');
|
require(stableRateEnabled, '11');
|
||||||
|
|
||||||
require(
|
require(
|
||||||
!_userConfig.isUsingAsCollateral(_reserve.index) ||
|
!userConfig.isUsingAsCollateral(reserve.index) ||
|
||||||
_reserve.configuration.getLtv() == 0 ||
|
reserve.configuration.getLtv() == 0 ||
|
||||||
_stableBorrowBalance.add(_variableBorrowBalance) >
|
stableBorrowBalance.add(variableBorrowBalance) >
|
||||||
IERC20(_reserve.aTokenAddress).balanceOf(msg.sender),
|
IERC20(reserve.aTokenAddress).balanceOf(msg.sender),
|
||||||
'12'
|
'12'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -305,34 +301,34 @@ library ValidationLogic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev validates the choice of a user of setting (or not) an asset as collateral
|
* @dev validates the choice of a user of setting (or not) an asset as collateral
|
||||||
* @param _reserve the state of the reserve that the user is enabling or disabling as collateral
|
* @param reserve the state of the reserve that the user is enabling or disabling as collateral
|
||||||
* @param _reserveAddress the address of the reserve
|
* @param reserveAddress the address of the reserve
|
||||||
* @param _reservesData the data of all the reserves
|
* @param reservesData the data of all the reserves
|
||||||
* @param _userConfig the state of the user for the specific reserve
|
* @param userConfig the state of the user for the specific reserve
|
||||||
* @param _reserves the addresses of all the active reserves
|
* @param reserves the addresses of all the active reserves
|
||||||
* @param _oracle the price oracle
|
* @param oracle the price oracle
|
||||||
*/
|
*/
|
||||||
function validateSetUseReserveAsCollateral(
|
function validateSetUseReserveAsCollateral(
|
||||||
ReserveLogic.ReserveData storage _reserve,
|
ReserveLogic.ReserveData storage reserve,
|
||||||
address _reserveAddress,
|
address reserveAddress,
|
||||||
mapping(address => ReserveLogic.ReserveData) storage _reservesData,
|
mapping(address => ReserveLogic.ReserveData) storage reservesData,
|
||||||
UserConfiguration.Map storage _userConfig,
|
UserConfiguration.Map storage userConfig,
|
||||||
address[] calldata _reserves,
|
address[] calldata reserves,
|
||||||
address _oracle
|
address oracle
|
||||||
) external view {
|
) external view {
|
||||||
uint256 underlyingBalance = IERC20(_reserve.aTokenAddress).balanceOf(msg.sender);
|
uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender);
|
||||||
|
|
||||||
require(underlyingBalance > 0, '22');
|
require(underlyingBalance > 0, '22');
|
||||||
|
|
||||||
require(
|
require(
|
||||||
GenericLogic.balanceDecreaseAllowed(
|
GenericLogic.balanceDecreaseAllowed(
|
||||||
_reserveAddress,
|
reserveAddress,
|
||||||
msg.sender,
|
msg.sender,
|
||||||
underlyingBalance,
|
underlyingBalance,
|
||||||
_reservesData,
|
reservesData,
|
||||||
_userConfig,
|
userConfig,
|
||||||
_reserves,
|
reserves,
|
||||||
_oracle
|
oracle
|
||||||
),
|
),
|
||||||
'User deposit is already being used as collateral'
|
'User deposit is already being used as collateral'
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,22 +12,22 @@ library MathUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev function to calculate the interest using a linear interest rate formula
|
* @dev function to calculate the interest using a linear interest rate formula
|
||||||
* @param _rate the interest rate, in ray
|
* @param rate the interest rate, in ray
|
||||||
* @param _lastUpdateTimestamp the timestamp of the last update of the interest
|
* @param lastUpdateTimestamp the timestamp of the last update of the interest
|
||||||
* @return the interest rate linearly accumulated during the timeDelta, in ray
|
* @return the interest rate linearly accumulated during the timeDelta, in ray
|
||||||
**/
|
**/
|
||||||
|
|
||||||
function calculateLinearInterest(uint256 _rate, uint40 _lastUpdateTimestamp)
|
function calculateLinearInterest(uint256 rate, uint40 lastUpdateTimestamp)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
uint256 timeDifference = block.timestamp.sub(uint256(_lastUpdateTimestamp));
|
uint256 timeDifference = block.timestamp.sub(uint256(lastUpdateTimestamp));
|
||||||
|
|
||||||
uint256 timeDelta = timeDifference.wadToRay().rayDiv(SECONDS_PER_YEAR.wadToRay());
|
uint256 timeDelta = timeDifference.wadToRay().rayDiv(SECONDS_PER_YEAR.wadToRay());
|
||||||
|
|
||||||
return _rate.rayMul(timeDelta).add(WadRayMath.ray());
|
return rate.rayMul(timeDelta).add(WadRayMath.ray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,17 +39,17 @@ library MathUtils {
|
||||||
* The approximation slightly underpays liquidity providers, with the advantage of great gas cost reductions.
|
* The approximation slightly underpays liquidity providers, with the advantage of great gas cost reductions.
|
||||||
* The whitepaper contains reference to the approximation and a table showing the margin of error per different time periods.
|
* The whitepaper contains reference to the approximation and a table showing the margin of error per different time periods.
|
||||||
*
|
*
|
||||||
* @param _rate the interest rate, in ray
|
* @param rate the interest rate, in ray
|
||||||
* @param _lastUpdateTimestamp the timestamp of the last update of the interest
|
* @param lastUpdateTimestamp the timestamp of the last update of the interest
|
||||||
* @return the interest rate compounded during the timeDelta, in ray
|
* @return the interest rate compounded during the timeDelta, in ray
|
||||||
**/
|
**/
|
||||||
function calculateCompoundedInterest(uint256 _rate, uint40 _lastUpdateTimestamp)
|
function calculateCompoundedInterest(uint256 rate, uint40 lastUpdateTimestamp)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
uint256 exp = block.timestamp.sub(uint256(_lastUpdateTimestamp));
|
uint256 exp = block.timestamp.sub(uint256(lastUpdateTimestamp));
|
||||||
|
|
||||||
if (exp == 0) {
|
if (exp == 0) {
|
||||||
return WadRayMath.ray();
|
return WadRayMath.ray();
|
||||||
|
@ -59,7 +59,7 @@ library MathUtils {
|
||||||
|
|
||||||
uint256 expMinusTwo = exp > 2 ? exp.sub(2) : 0;
|
uint256 expMinusTwo = exp > 2 ? exp.sub(2) : 0;
|
||||||
|
|
||||||
uint256 ratePerSecond = _rate.div(31536000);
|
uint256 ratePerSecond = rate.div(31536000);
|
||||||
|
|
||||||
uint256 basePowerTwo = ratePerSecond.rayMul(ratePerSecond);
|
uint256 basePowerTwo = ratePerSecond.rayMul(ratePerSecond);
|
||||||
uint256 basePowerThree = basePowerTwo.rayMul(ratePerSecond);
|
uint256 basePowerThree = basePowerTwo.rayMul(ratePerSecond);
|
||||||
|
|
|
@ -19,23 +19,23 @@ library PercentageMath {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev executes a percentage multiplication
|
* @dev executes a percentage multiplication
|
||||||
* @param _value the value of which the percentage needs to be calculated
|
* @param value the value of which the percentage needs to be calculated
|
||||||
* @param _percentage the percentage of the value to be calculated
|
* @param percentage the percentage of the value to be calculated
|
||||||
* @return the _percentage of _value
|
* @return the percentage of value
|
||||||
**/
|
**/
|
||||||
function percentMul(uint256 _value, uint256 _percentage) internal pure returns (uint256) {
|
function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256) {
|
||||||
return HALF_PERCENT.add(_value.mul(_percentage)).div(PERCENTAGE_FACTOR);
|
return HALF_PERCENT.add(value.mul(percentage)).div(PERCENTAGE_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev executes a percentage division
|
* @dev executes a percentage division
|
||||||
* @param _value the value of which the percentage needs to be calculated
|
* @param value the value of which the percentage needs to be calculated
|
||||||
* @param _percentage the percentage of the value to be calculated
|
* @param percentage the percentage of the value to be calculated
|
||||||
* @return the _value divided the _percentage
|
* @return the value divided the percentage
|
||||||
**/
|
**/
|
||||||
function percentDiv(uint256 _value, uint256 _percentage) internal pure returns (uint256) {
|
function percentDiv(uint256 value, uint256 percentage) internal pure returns (uint256) {
|
||||||
uint256 halfPercentage = _percentage / 2;
|
uint256 halfPercentage = percentage / 2;
|
||||||
|
|
||||||
return halfPercentage.add(_value.mul(PERCENTAGE_FACTOR)).div(_percentage);
|
return halfPercentage.add(value.mul(PERCENTAGE_FACTOR)).div(percentage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,22 +15,22 @@ contract InitializableAdminUpgradeabilityProxy is
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Contract initializer.
|
* Contract initializer.
|
||||||
* @param _logic address of the initial implementation.
|
* @param logic address of the initial implementation.
|
||||||
* @param _admin Address of the proxy administrator.
|
* @param admin Address of the proxy administrator.
|
||||||
* @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
|
* @param data Data to send as msg.data to the implementation to initialize the proxied contract.
|
||||||
* It should include the signature and the parameters of the function to be called, as described in
|
* It should include the signature and the parameters of the function to be called, as described in
|
||||||
* https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
|
* https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
|
||||||
* This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
|
* This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
|
||||||
*/
|
*/
|
||||||
function initialize(
|
function initialize(
|
||||||
address _logic,
|
address logic,
|
||||||
address _admin,
|
address admin,
|
||||||
bytes memory _data
|
bytes memory data
|
||||||
) public payable {
|
) public payable {
|
||||||
require(_implementation() == address(0));
|
require(_implementation() == address(0));
|
||||||
InitializableUpgradeabilityProxy.initialize(_logic, _data);
|
InitializableUpgradeabilityProxy.initialize(logic, data);
|
||||||
assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
|
assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
|
||||||
_setAdmin(_admin);
|
_setAdmin(admin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,7 +51,7 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
||||||
token.mint(_fee);
|
token.mint(_fee);
|
||||||
|
|
||||||
//returning amount + fee to the destination
|
//returning amount + fee to the destination
|
||||||
transferFundsBackInternal(_reserve, _destination, _amount.add(_fee));
|
_transferFundsBack(_reserve, _destination, _amount.add(_fee));
|
||||||
|
|
||||||
emit ExecutedWithSuccess(_reserve, _amount, _fee);
|
emit ExecutedWithSuccess(_reserve, _amount, _fee);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
address to,
|
address to,
|
||||||
uint256 amount
|
uint256 amount
|
||||||
) internal override whenTransferAllowed(from, amount) {
|
) internal override whenTransferAllowed(from, amount) {
|
||||||
executeTransferInternal(from, to, amount);
|
_executeTransfer(from, to, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +86,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param to the address to which the interest will be redirected
|
* @param to the address to which the interest will be redirected
|
||||||
**/
|
**/
|
||||||
function redirectInterestStream(address to) external override {
|
function redirectInterestStream(address to) external override {
|
||||||
redirectInterestStreamInternal(msg.sender, to);
|
_redirectInterestStream(msg.sender, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,7 +102,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
msg.sender == _interestRedirectionAllowances[from],
|
msg.sender == _interestRedirectionAllowances[from],
|
||||||
'Caller is not allowed to redirect the interest of the user'
|
'Caller is not allowed to redirect the interest of the user'
|
||||||
);
|
);
|
||||||
redirectInterestStreamInternal(from, to);
|
_redirectInterestStream(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,12 +128,12 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
uint256 amount
|
uint256 amount
|
||||||
) external override onlyLendingPool {
|
) external override onlyLendingPool {
|
||||||
//cumulates the balance of the user
|
//cumulates the balance of the user
|
||||||
(, uint256 currentBalance, uint256 balanceIncrease) = calculateBalanceIncreaseInternal(user);
|
(, uint256 currentBalance, uint256 balanceIncrease) = _calculateBalanceIncrease(user);
|
||||||
|
|
||||||
//if the user is redirecting his interest towards someone else,
|
//if the user is redirecting his interest towards someone else,
|
||||||
//we update the redirected balance of the redirection address by adding the accrued interest,
|
//we update the redirected balance of the redirection address by adding the accrued interest,
|
||||||
//and removing the amount to redeem
|
//and removing the amount to redeem
|
||||||
updateRedirectedBalanceOfRedirectionAddressInternal(user, balanceIncrease, amount);
|
_updateRedirectedBalanceOfRedirectionAddress(user, balanceIncrease, amount);
|
||||||
|
|
||||||
if (balanceIncrease > amount) {
|
if (balanceIncrease > amount) {
|
||||||
_mint(user, balanceIncrease.sub(amount));
|
_mint(user, balanceIncrease.sub(amount));
|
||||||
|
@ -145,7 +145,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
|
|
||||||
//reset the user data if the remaining balance is 0
|
//reset the user data if the remaining balance is 0
|
||||||
if (currentBalance.sub(amount) == 0) {
|
if (currentBalance.sub(amount) == 0) {
|
||||||
resetDataOnZeroBalanceInternal(user);
|
_resetDataOnZeroBalance(user);
|
||||||
} else {
|
} else {
|
||||||
//updates the user index
|
//updates the user index
|
||||||
userIndex = _userIndexes[user] = _pool.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
|
userIndex = _userIndexes[user] = _pool.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
|
||||||
|
@ -165,7 +165,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
*/
|
*/
|
||||||
function mint(address user, uint256 amount) external override onlyLendingPool {
|
function mint(address user, uint256 amount) external override onlyLendingPool {
|
||||||
//cumulates the balance of the user
|
//cumulates the balance of the user
|
||||||
(, , uint256 balanceIncrease) = calculateBalanceIncreaseInternal(user);
|
(, , uint256 balanceIncrease) = _calculateBalanceIncrease(user);
|
||||||
|
|
||||||
//updates the user index
|
//updates the user index
|
||||||
uint256 index = _userIndexes[user] = _pool.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
|
uint256 index = _userIndexes[user] = _pool.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
|
||||||
|
@ -173,7 +173,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
//if the user is redirecting his interest towards someone else,
|
//if the user is redirecting his interest towards someone else,
|
||||||
//we update the redirected balance of the redirection address by adding the accrued interest
|
//we update the redirected balance of the redirection address by adding the accrued interest
|
||||||
//and the amount deposited
|
//and the amount deposited
|
||||||
updateRedirectedBalanceOfRedirectionAddressInternal(user, balanceIncrease.add(amount), 0);
|
_updateRedirectedBalanceOfRedirectionAddress(user, balanceIncrease.add(amount), 0);
|
||||||
|
|
||||||
//mint an equivalent amount of tokens to cover the new deposit
|
//mint an equivalent amount of tokens to cover the new deposit
|
||||||
_mint(user, amount.add(balanceIncrease));
|
_mint(user, amount.add(balanceIncrease));
|
||||||
|
@ -195,7 +195,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
) external override onlyLendingPool {
|
) external override onlyLendingPool {
|
||||||
//being a normal transfer, the Transfer() and BalanceTransfer() are emitted
|
//being a normal transfer, the Transfer() and BalanceTransfer() are emitted
|
||||||
//so no need to emit a specific event here
|
//so no need to emit a specific event here
|
||||||
executeTransferInternal(from, to, value);
|
_executeTransfer(from, to, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -220,7 +220,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
//accruing for himself means that both the principal balance and
|
//accruing for himself means that both the principal balance and
|
||||||
//the redirected balance partecipate in the interest
|
//the redirected balance partecipate in the interest
|
||||||
return
|
return
|
||||||
calculateCumulatedBalanceInternal(user, currentPrincipalBalance.add(redirectedBalance)).sub(
|
_calculateCumulatedBalance(user, currentPrincipalBalance.add(redirectedBalance)).sub(
|
||||||
redirectedBalance
|
redirectedBalance
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -229,7 +229,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
//by the redirected balance is added to the current principal balance.
|
//by the redirected balance is added to the current principal balance.
|
||||||
return
|
return
|
||||||
currentPrincipalBalance.add(
|
currentPrincipalBalance.add(
|
||||||
calculateCumulatedBalanceInternal(user, redirectedBalance).sub(redirectedBalance)
|
_calculateCumulatedBalance(user, redirectedBalance).sub(redirectedBalance)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param user the address of the user
|
* @param user the address of the user
|
||||||
* @return the last user principal balance, the current balance and the balance increase
|
* @return the last user principal balance, the current balance and the balance increase
|
||||||
**/
|
**/
|
||||||
function calculateBalanceIncreaseInternal(address user)
|
function _calculateBalanceIncrease(address user)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (
|
returns (
|
||||||
|
@ -335,7 +335,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @return the previous principal balance, the new principal balance, the balance increase
|
* @return the previous principal balance, the new principal balance, the balance increase
|
||||||
* and the new user index
|
* and the new user index
|
||||||
**/
|
**/
|
||||||
function cumulateBalanceInternal(address user)
|
function _cumulateBalance(address user)
|
||||||
internal
|
internal
|
||||||
returns (
|
returns (
|
||||||
uint256,
|
uint256,
|
||||||
|
@ -348,7 +348,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
uint256 previousBalance,
|
uint256 previousBalance,
|
||||||
uint256 currentBalance,
|
uint256 currentBalance,
|
||||||
uint256 balanceIncrease
|
uint256 balanceIncrease
|
||||||
) = calculateBalanceIncreaseInternal(user);
|
) = _calculateBalanceIncrease(user);
|
||||||
|
|
||||||
_mint(user, balanceIncrease);
|
_mint(user, balanceIncrease);
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param balanceToAdd the amount to add to the redirected balance
|
* @param balanceToAdd the amount to add to the redirected balance
|
||||||
* @param balanceToRemove the amount to remove from the redirected balance
|
* @param balanceToRemove the amount to remove from the redirected balance
|
||||||
**/
|
**/
|
||||||
function updateRedirectedBalanceOfRedirectionAddressInternal(
|
function _updateRedirectedBalanceOfRedirectionAddress(
|
||||||
address user,
|
address user,
|
||||||
uint256 balanceToAdd,
|
uint256 balanceToAdd,
|
||||||
uint256 balanceToRemove
|
uint256 balanceToRemove
|
||||||
|
@ -377,7 +377,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
//compound balances of the redirected address
|
//compound balances of the redirected address
|
||||||
(, , uint256 balanceIncrease, uint256 index) = cumulateBalanceInternal(redirectionAddress);
|
(, , uint256 balanceIncrease, uint256 index) = _cumulateBalance(redirectionAddress);
|
||||||
|
|
||||||
//updating the redirected balance
|
//updating the redirected balance
|
||||||
_redirectedBalances[redirectionAddress] = _redirectedBalances[redirectionAddress]
|
_redirectedBalances[redirectionAddress] = _redirectedBalances[redirectionAddress]
|
||||||
|
@ -391,7 +391,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
// if the redirection address is also redirecting the interest, we accumulate his balance
|
// if the redirection address is also redirecting the interest, we accumulate his balance
|
||||||
// and update his chain of redirection
|
// and update his chain of redirection
|
||||||
if (targetOfRedirectionAddress != address(0)) {
|
if (targetOfRedirectionAddress != address(0)) {
|
||||||
updateRedirectedBalanceOfRedirectionAddressInternal(redirectionAddress, balanceIncrease, 0);
|
_updateRedirectedBalanceOfRedirectionAddress(redirectionAddress, balanceIncrease, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit RedirectedBalanceUpdated(
|
emit RedirectedBalanceUpdated(
|
||||||
|
@ -409,7 +409,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param balance the balance on which the interest is calculated
|
* @param balance the balance on which the interest is calculated
|
||||||
* @return the interest rate accrued
|
* @return the interest rate accrued
|
||||||
**/
|
**/
|
||||||
function calculateCumulatedBalanceInternal(address user, uint256 balance)
|
function _calculateCumulatedBalance(address user, uint256 balance)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
|
@ -429,7 +429,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param to the destination address
|
* @param to the destination address
|
||||||
* @param value the amount to transfer
|
* @param value the amount to transfer
|
||||||
**/
|
**/
|
||||||
function executeTransferInternal(
|
function _executeTransfer(
|
||||||
address from,
|
address from,
|
||||||
address to,
|
address to,
|
||||||
uint256 value
|
uint256 value
|
||||||
|
@ -442,20 +442,20 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
uint256 fromBalance,
|
uint256 fromBalance,
|
||||||
uint256 fromBalanceIncrease,
|
uint256 fromBalanceIncrease,
|
||||||
uint256 fromIndex
|
uint256 fromIndex
|
||||||
) = cumulateBalanceInternal(from);
|
) = _cumulateBalance(from);
|
||||||
|
|
||||||
//cumulate the balance of the receiver
|
//cumulate the balance of the receiver
|
||||||
(, , uint256 toBalanceIncrease, uint256 toIndex) = cumulateBalanceInternal(to);
|
(, , uint256 toBalanceIncrease, uint256 toIndex) = _cumulateBalance(to);
|
||||||
|
|
||||||
//if the sender is redirecting his interest towards someone else,
|
//if the sender is redirecting his interest towards someone else,
|
||||||
//adds to the redirected balance the accrued interest and removes the amount
|
//adds to the redirected balance the accrued interest and removes the amount
|
||||||
//being transferred
|
//being transferred
|
||||||
updateRedirectedBalanceOfRedirectionAddressInternal(from, fromBalanceIncrease, value);
|
_updateRedirectedBalanceOfRedirectionAddress(from, fromBalanceIncrease, value);
|
||||||
|
|
||||||
//if the receiver is redirecting his interest towards someone else,
|
//if the receiver is redirecting his interest towards someone else,
|
||||||
//adds to the redirected balance the accrued interest and the amount
|
//adds to the redirected balance the accrued interest and the amount
|
||||||
//being transferred
|
//being transferred
|
||||||
updateRedirectedBalanceOfRedirectionAddressInternal(to, toBalanceIncrease.add(value), 0);
|
_updateRedirectedBalanceOfRedirectionAddress(to, toBalanceIncrease.add(value), 0);
|
||||||
|
|
||||||
//performs the transfer
|
//performs the transfer
|
||||||
super._transfer(from, to, value);
|
super._transfer(from, to, value);
|
||||||
|
@ -463,7 +463,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
bool fromIndexReset = false;
|
bool fromIndexReset = false;
|
||||||
//reset the user data if the remaining balance is 0
|
//reset the user data if the remaining balance is 0
|
||||||
if (fromBalance.sub(value) == 0 && from != to) {
|
if (fromBalance.sub(value) == 0 && from != to) {
|
||||||
fromIndexReset = resetDataOnZeroBalanceInternal(from);
|
fromIndexReset = _resetDataOnZeroBalance(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit BalanceTransfer(
|
emit BalanceTransfer(
|
||||||
|
@ -483,7 +483,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param from the address from which transfer the aTokens
|
* @param from the address from which transfer the aTokens
|
||||||
* @param to the destination address
|
* @param to the destination address
|
||||||
**/
|
**/
|
||||||
function redirectInterestStreamInternal(address from, address to) internal {
|
function _redirectInterestStream(address from, address to) internal {
|
||||||
address currentRedirectionAddress = _interestRedirectionAddresses[from];
|
address currentRedirectionAddress = _interestRedirectionAddresses[from];
|
||||||
|
|
||||||
require(to != currentRedirectionAddress, 'Interest is already redirected to the user');
|
require(to != currentRedirectionAddress, 'Interest is already redirected to the user');
|
||||||
|
@ -494,7 +494,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
uint256 fromBalance,
|
uint256 fromBalance,
|
||||||
uint256 balanceIncrease,
|
uint256 balanceIncrease,
|
||||||
uint256 fromIndex
|
uint256 fromIndex
|
||||||
) = cumulateBalanceInternal(from);
|
) = _cumulateBalance(from);
|
||||||
|
|
||||||
require(fromBalance > 0, 'Interest stream can only be redirected if there is a valid balance');
|
require(fromBalance > 0, 'Interest stream can only be redirected if there is a valid balance');
|
||||||
|
|
||||||
|
@ -502,7 +502,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
//the redirection address we substract the redirected balance of the previous
|
//the redirection address we substract the redirected balance of the previous
|
||||||
//recipient
|
//recipient
|
||||||
if (currentRedirectionAddress != address(0)) {
|
if (currentRedirectionAddress != address(0)) {
|
||||||
updateRedirectedBalanceOfRedirectionAddressInternal(from, 0, previousPrincipalBalance);
|
_updateRedirectedBalanceOfRedirectionAddress(from, 0, previousPrincipalBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if the user is redirecting the interest back to himself,
|
//if the user is redirecting the interest back to himself,
|
||||||
|
@ -517,7 +517,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
_interestRedirectionAddresses[from] = to;
|
_interestRedirectionAddresses[from] = to;
|
||||||
|
|
||||||
//adds the user balance to the redirected balance of the destination
|
//adds the user balance to the redirected balance of the destination
|
||||||
updateRedirectedBalanceOfRedirectionAddressInternal(from, fromBalance, 0);
|
_updateRedirectedBalanceOfRedirectionAddress(from, fromBalance, 0);
|
||||||
|
|
||||||
emit InterestStreamRedirected(from, to, fromBalance, balanceIncrease, fromIndex);
|
emit InterestStreamRedirected(from, to, fromBalance, balanceIncrease, fromIndex);
|
||||||
}
|
}
|
||||||
|
@ -528,7 +528,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param user the address of the user
|
* @param user the address of the user
|
||||||
* @return true if the user index has also been reset, false otherwise. useful to emit the proper user index value
|
* @return true if the user index has also been reset, false otherwise. useful to emit the proper user index value
|
||||||
**/
|
**/
|
||||||
function resetDataOnZeroBalanceInternal(address user) internal returns (bool) {
|
function _resetDataOnZeroBalance(address user) internal returns (bool) {
|
||||||
//if the user has 0 principal balance, the interest stream redirection gets reset
|
//if the user has 0 principal balance, the interest stream redirection gets reset
|
||||||
_interestRedirectionAddresses[user] = address(0);
|
_interestRedirectionAddresses[user] = address(0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user