aave-protocol-v2/contracts/misc/UiPoolDataProvider.sol
2021-10-05 10:11:15 +02:00

400 lines
15 KiB
Solidity

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol';
import {IUiPoolDataProvider} from './interfaces/IUiPoolDataProvider.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IAToken} from '../interfaces/IAToken.sol';
import {IVariableDebtToken} from '../interfaces/IVariableDebtToken.sol';
import {IStableDebtToken} from '../interfaces/IStableDebtToken.sol';
import {WadRayMath} from '../protocol/libraries/math/WadRayMath.sol';
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
import {
DefaultReserveInterestRateStrategy
} from '../protocol/lendingpool/DefaultReserveInterestRateStrategy.sol';
contract UiPoolDataProvider is IUiPoolDataProvider {
using WadRayMath for uint256;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
IAaveIncentivesController public immutable override incentivesController;
IPriceOracleGetter public immutable oracle;
constructor(IAaveIncentivesController _incentivesController, IPriceOracleGetter _oracle) public {
incentivesController = _incentivesController;
oracle = _oracle;
}
function getInterestRateStrategySlopes(DefaultReserveInterestRateStrategy interestRateStrategy)
internal
view
returns (
uint256,
uint256,
uint256,
uint256
)
{
return (
interestRateStrategy.variableRateSlope1(),
interestRateStrategy.variableRateSlope2(),
interestRateStrategy.stableRateSlope1(),
interestRateStrategy.stableRateSlope2()
);
}
function getReservesList(ILendingPoolAddressesProvider provider)
public
view
override
returns (address[] memory)
{
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
return lendingPool.getReservesList();
}
function getSimpleReservesData(ILendingPoolAddressesProvider provider)
public
view
override
returns (
AggregatedReserveData[] memory,
uint256,
uint256
)
{
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
address[] memory reserves = lendingPool.getReservesList();
AggregatedReserveData[] memory reservesData = new AggregatedReserveData[](reserves.length);
for (uint256 i = 0; i < reserves.length; i++) {
AggregatedReserveData memory reserveData = reservesData[i];
reserveData.underlyingAsset = reserves[i];
// reserve current state
DataTypes.ReserveData memory baseData =
lendingPool.getReserveData(reserveData.underlyingAsset);
reserveData.liquidityIndex = baseData.liquidityIndex;
reserveData.variableBorrowIndex = baseData.variableBorrowIndex;
reserveData.liquidityRate = baseData.currentLiquidityRate;
reserveData.variableBorrowRate = baseData.currentVariableBorrowRate;
reserveData.stableBorrowRate = baseData.currentStableBorrowRate;
reserveData.lastUpdateTimestamp = baseData.lastUpdateTimestamp;
reserveData.aTokenAddress = baseData.aTokenAddress;
reserveData.stableDebtTokenAddress = baseData.stableDebtTokenAddress;
reserveData.variableDebtTokenAddress = baseData.variableDebtTokenAddress;
reserveData.interestRateStrategyAddress = baseData.interestRateStrategyAddress;
reserveData.priceInEth = oracle.getAssetPrice(reserveData.underlyingAsset);
reserveData.availableLiquidity = IERC20Detailed(reserveData.underlyingAsset).balanceOf(
reserveData.aTokenAddress
);
(
reserveData.totalPrincipalStableDebt,
,
reserveData.averageStableRate,
reserveData.stableDebtLastUpdateTimestamp
) = IStableDebtToken(reserveData.stableDebtTokenAddress).getSupplyData();
reserveData.totalScaledVariableDebt = IVariableDebtToken(reserveData.variableDebtTokenAddress)
.scaledTotalSupply();
// reserve configuration
// we're getting this info from the aToken, because some of assets can be not compliant with ETC20Detailed
reserveData.symbol = IERC20Detailed(reserveData.underlyingAsset).symbol();
reserveData.name = '';
(
reserveData.baseLTVasCollateral,
reserveData.reserveLiquidationThreshold,
reserveData.reserveLiquidationBonus,
reserveData.decimals,
reserveData.reserveFactor
) = baseData.configuration.getParamsMemory();
(
reserveData.isActive,
reserveData.isFrozen,
reserveData.borrowingEnabled,
reserveData.stableBorrowRateEnabled
) = baseData.configuration.getFlagsMemory();
reserveData.usageAsCollateralEnabled = reserveData.baseLTVasCollateral != 0;
(
reserveData.variableRateSlope1,
reserveData.variableRateSlope2,
reserveData.stableRateSlope1,
reserveData.stableRateSlope2
) = getInterestRateStrategySlopes(
DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress)
);
// incentives
if (address(0) != address(incentivesController)) {
(
reserveData.aTokenIncentivesIndex,
reserveData.aEmissionPerSecond,
reserveData.aIncentivesLastUpdateTimestamp
) = incentivesController.getAssetData(reserveData.aTokenAddress);
(
reserveData.sTokenIncentivesIndex,
reserveData.sEmissionPerSecond,
reserveData.sIncentivesLastUpdateTimestamp
) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress);
(
reserveData.vTokenIncentivesIndex,
reserveData.vEmissionPerSecond,
reserveData.vIncentivesLastUpdateTimestamp
) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress);
}
}
uint256 emissionEndTimestamp;
if (address(0) != address(incentivesController)) {
emissionEndTimestamp = incentivesController.DISTRIBUTION_END();
}
return (reservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS), emissionEndTimestamp);
}
function getUserReservesData(ILendingPoolAddressesProvider provider, address user)
external
view
override
returns (UserReserveData[] memory, uint256)
{
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
address[] memory reserves = lendingPool.getReservesList();
DataTypes.UserConfigurationMap memory userConfig = lendingPool.getUserConfiguration(user);
UserReserveData[] memory userReservesData =
new UserReserveData[](user != address(0) ? reserves.length : 0);
for (uint256 i = 0; i < reserves.length; i++) {
DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]);
// incentives
if (address(0) != address(incentivesController)) {
userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
baseData.aTokenAddress
);
userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
baseData.variableDebtTokenAddress
);
userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
baseData.stableDebtTokenAddress
);
}
// user reserve data
userReservesData[i].underlyingAsset = reserves[i];
userReservesData[i].scaledATokenBalance = IAToken(baseData.aTokenAddress).scaledBalanceOf(
user
);
userReservesData[i].usageAsCollateralEnabledOnUser = userConfig.isUsingAsCollateral(i);
if (userConfig.isBorrowing(i)) {
userReservesData[i].scaledVariableDebt = IVariableDebtToken(
baseData
.variableDebtTokenAddress
)
.scaledBalanceOf(user);
userReservesData[i].principalStableDebt = IStableDebtToken(baseData.stableDebtTokenAddress)
.principalBalanceOf(user);
if (userReservesData[i].principalStableDebt != 0) {
userReservesData[i].stableBorrowRate = IStableDebtToken(baseData.stableDebtTokenAddress)
.getUserStableRate(user);
userReservesData[i].stableBorrowLastUpdateTimestamp = IStableDebtToken(
baseData
.stableDebtTokenAddress
)
.getUserLastUpdated(user);
}
}
}
uint256 userUnclaimedRewards;
if (address(0) != address(incentivesController)) {
userUnclaimedRewards = incentivesController.getUserUnclaimedRewards(user);
}
return (userReservesData, userUnclaimedRewards);
}
function getReservesData(ILendingPoolAddressesProvider provider, address user)
external
view
override
returns (
AggregatedReserveData[] memory,
UserReserveData[] memory,
uint256,
IncentivesControllerData memory
)
{
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
address[] memory reserves = lendingPool.getReservesList();
DataTypes.UserConfigurationMap memory userConfig = lendingPool.getUserConfiguration(user);
AggregatedReserveData[] memory reservesData = new AggregatedReserveData[](reserves.length);
UserReserveData[] memory userReservesData =
new UserReserveData[](user != address(0) ? reserves.length : 0);
for (uint256 i = 0; i < reserves.length; i++) {
AggregatedReserveData memory reserveData = reservesData[i];
reserveData.underlyingAsset = reserves[i];
// reserve current state
DataTypes.ReserveData memory baseData =
lendingPool.getReserveData(reserveData.underlyingAsset);
reserveData.liquidityIndex = baseData.liquidityIndex;
reserveData.variableBorrowIndex = baseData.variableBorrowIndex;
reserveData.liquidityRate = baseData.currentLiquidityRate;
reserveData.variableBorrowRate = baseData.currentVariableBorrowRate;
reserveData.stableBorrowRate = baseData.currentStableBorrowRate;
reserveData.lastUpdateTimestamp = baseData.lastUpdateTimestamp;
reserveData.aTokenAddress = baseData.aTokenAddress;
reserveData.stableDebtTokenAddress = baseData.stableDebtTokenAddress;
reserveData.variableDebtTokenAddress = baseData.variableDebtTokenAddress;
reserveData.interestRateStrategyAddress = baseData.interestRateStrategyAddress;
reserveData.priceInEth = oracle.getAssetPrice(reserveData.underlyingAsset);
reserveData.availableLiquidity = IERC20Detailed(reserveData.underlyingAsset).balanceOf(
reserveData.aTokenAddress
);
(
reserveData.totalPrincipalStableDebt,
,
reserveData.averageStableRate,
reserveData.stableDebtLastUpdateTimestamp
) = IStableDebtToken(reserveData.stableDebtTokenAddress).getSupplyData();
reserveData.totalScaledVariableDebt = IVariableDebtToken(reserveData.variableDebtTokenAddress)
.scaledTotalSupply();
// reserve configuration
// we're getting this info from the aToken, because some of assets can be not compliant with ETC20Detailed
reserveData.symbol = IERC20Detailed(reserveData.underlyingAsset).symbol();
reserveData.name = '';
(
reserveData.baseLTVasCollateral,
reserveData.reserveLiquidationThreshold,
reserveData.reserveLiquidationBonus,
reserveData.decimals,
reserveData.reserveFactor
) = baseData.configuration.getParamsMemory();
(
reserveData.isActive,
reserveData.isFrozen,
reserveData.borrowingEnabled,
reserveData.stableBorrowRateEnabled
) = baseData.configuration.getFlagsMemory();
reserveData.usageAsCollateralEnabled = reserveData.baseLTVasCollateral != 0;
(
reserveData.variableRateSlope1,
reserveData.variableRateSlope2,
reserveData.stableRateSlope1,
reserveData.stableRateSlope2
) = getInterestRateStrategySlopes(
DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress)
);
// incentives
if (address(0) != address(incentivesController)) {
(
reserveData.aTokenIncentivesIndex,
reserveData.aEmissionPerSecond,
reserveData.aIncentivesLastUpdateTimestamp
) = incentivesController.getAssetData(reserveData.aTokenAddress);
(
reserveData.sTokenIncentivesIndex,
reserveData.sEmissionPerSecond,
reserveData.sIncentivesLastUpdateTimestamp
) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress);
(
reserveData.vTokenIncentivesIndex,
reserveData.vEmissionPerSecond,
reserveData.vIncentivesLastUpdateTimestamp
) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress);
}
if (user != address(0)) {
// incentives
if (address(0) != address(incentivesController)) {
userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
reserveData.aTokenAddress
);
userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
reserveData.variableDebtTokenAddress
);
userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
reserveData.stableDebtTokenAddress
);
}
// user reserve data
userReservesData[i].underlyingAsset = reserveData.underlyingAsset;
userReservesData[i].scaledATokenBalance = IAToken(reserveData.aTokenAddress)
.scaledBalanceOf(user);
userReservesData[i].usageAsCollateralEnabledOnUser = userConfig.isUsingAsCollateral(i);
if (userConfig.isBorrowing(i)) {
userReservesData[i].scaledVariableDebt = IVariableDebtToken(
reserveData
.variableDebtTokenAddress
)
.scaledBalanceOf(user);
userReservesData[i].principalStableDebt = IStableDebtToken(
reserveData
.stableDebtTokenAddress
)
.principalBalanceOf(user);
if (userReservesData[i].principalStableDebt != 0) {
userReservesData[i].stableBorrowRate = IStableDebtToken(
reserveData
.stableDebtTokenAddress
)
.getUserStableRate(user);
userReservesData[i].stableBorrowLastUpdateTimestamp = IStableDebtToken(
reserveData
.stableDebtTokenAddress
)
.getUserLastUpdated(user);
}
}
}
}
IncentivesControllerData memory incentivesControllerData;
if (address(0) != address(incentivesController)) {
if (user != address(0)) {
incentivesControllerData.userUnclaimedRewards = incentivesController
.getUserUnclaimedRewards(user);
}
incentivesControllerData.emissionEndTimestamp = incentivesController.DISTRIBUTION_END();
}
return (
reservesData,
userReservesData,
oracle.getAssetPrice(MOCK_USD_ADDRESS),
incentivesControllerData
);
}
}