diff --git a/contracts/interfaces/IAaveIncentivesController.sol b/contracts/interfaces/IAaveIncentivesController.sol index bae75967..0006e31e 100644 --- a/contracts/interfaces/IAaveIncentivesController.sol +++ b/contracts/interfaces/IAaveIncentivesController.sol @@ -30,6 +30,21 @@ interface IAaveIncentivesController { uint256 ); + /* + * LEGACY ************************** + * @dev Returns the configuration of the distribution for a certain asset + * @param asset The address of the reference asset of the distribution + * @return The asset index, the emission per second and the last updated timestamp + **/ + function assets(address asset) + external + view + returns ( + uint128, + uint128, + uint256 + ); + /** * @dev Whitelists an address to claim the rewards on behalf of another address * @param user The address of the user diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index f06d0183..e9f40fe5 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -25,7 +25,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { using UserConfiguration for DataTypes.UserConfigurationMap; address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96; - IAaveIncentivesController public immutable incentivesController; + IAaveIncentivesController public immutable override incentivesController; IPriceOracleGetter public immutable oracle; constructor(IAaveIncentivesController _incentivesController, IPriceOracleGetter _oracle) public { @@ -51,6 +51,188 @@ contract UiPoolDataProvider is IUiPoolDataProvider { ); } + 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.aTokenAddress).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.aEmissionPerSecond, + reserveData.aIncentivesLastUpdateTimestamp, + reserveData.aTokenIncentivesIndex + // ) = incentivesController.getAssetData(reserveData.aTokenAddress); TODO: temp fix + ) = incentivesController.assets(reserveData.aTokenAddress); + + ( + reserveData.sEmissionPerSecond, + reserveData.sIncentivesLastUpdateTimestamp, + reserveData.sTokenIncentivesIndex + // ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); TODO: temp fix + ) = incentivesController.assets(reserveData.stableDebtTokenAddress); + + ( + reserveData.vEmissionPerSecond, + reserveData.vIncentivesLastUpdateTimestamp, + reserveData.vTokenIncentivesIndex + // ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); TODO: temp fix + ) = incentivesController.assets(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 @@ -136,19 +318,22 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.aTokenIncentivesIndex, reserveData.aEmissionPerSecond, reserveData.aIncentivesLastUpdateTimestamp - ) = incentivesController.getAssetData(reserveData.aTokenAddress); + // ) = incentivesController.getAssetData(reserveData.aTokenAddress); TODO: temp fix + ) = incentivesController.assets(reserveData.aTokenAddress); ( reserveData.sTokenIncentivesIndex, reserveData.sEmissionPerSecond, reserveData.sIncentivesLastUpdateTimestamp - ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); + // ) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress); TODO: temp fix + ) = incentivesController.assets(reserveData.stableDebtTokenAddress); ( reserveData.vTokenIncentivesIndex, reserveData.vEmissionPerSecond, reserveData.vIncentivesLastUpdateTimestamp - ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); + // ) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress); TODO: temp fix + ) = incentivesController.assets(reserveData.variableDebtTokenAddress); } if (user != address(0)) { @@ -200,12 +385,12 @@ contract UiPoolDataProvider is IUiPoolDataProvider { } } - IncentivesControllerData memory incentivesControllerData; if (address(0) != address(incentivesController)) { if (user != address(0)) { - incentivesControllerData.userUnclaimedRewards = incentivesController.getUserUnclaimedRewards(user); + incentivesControllerData.userUnclaimedRewards = incentivesController + .getUserUnclaimedRewards(user); } incentivesControllerData.emissionEndTimestamp = incentivesController.DISTRIBUTION_END(); } diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 15c9bd07..db7f3093 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -73,7 +73,31 @@ interface IUiPoolDataProvider { uint256 emissionEndTimestamp; } + function getReservesList(ILendingPoolAddressesProvider provider) + external + view + returns (address[] memory); + function incentivesController() external view returns (IAaveIncentivesController); + + function getSimpleReservesData(ILendingPoolAddressesProvider provider) + external + view + returns ( + AggregatedReserveData[] memory, + uint256, // usd price eth + uint256 // emission end timestamp + ); + + function getUserReservesData(ILendingPoolAddressesProvider provider, address user) + external + view + returns ( + UserReserveData[] memory, + uint256 // user unclaimed rewards + ); + + // generic method with full data function getReservesData(ILendingPoolAddressesProvider provider, address user) external view diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 374b9403..a9bdf5cc 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -48,7 +48,10 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { [eEthereumNetwork.buidlerevm]: 'http://localhost:8545', [eEthereumNetwork.tenderly]: `https://rpc.tenderly.co/fork/`, [ePolygonNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com', - [ePolygonNetwork.matic]: 'https://rpc-mainnet.matic.network', + [ePolygonNetwork.matic]: + // 'https://rpc-mainnet.maticvigil.com/v1/e616b9ddc7598ffae92629f8145614d55094c722', + 'https://polygon-mainnet.g.alchemy.com/v2/6NUmfWDZw6lC3RPAphj0p_2vm7ElOn2U', + // [ePolygonNetwork.matic]: 'https://rpc-mainnet.matic.network', [eXDaiNetwork.xdai]: 'https://rpc.xdaichain.com/', [eAvalancheNetwork.avalanche]: 'https://cchain.explorer.avax.network/', [eAvalancheNetwork.fuji]: 'https://api.avax-test.network/ext/bc/C/rpc'