Skip to content
This repository was archived by the owner on Oct 21, 2025. It is now read-only.

Commit 1225fdb

Browse files
authored
Merge pull request #15 from aave/feat/14_uipooldataprovider_v3
WIP: feat: updated ui pool data provider with latest logic
2 parents cb81b4a + d1e68c4 commit 1225fdb

File tree

10 files changed

+279
-176
lines changed

10 files changed

+279
-176
lines changed

contracts/misc/UiPoolDataProvider.sol

Lines changed: 116 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pragma solidity 0.8.7;
33

44
import {IERC20Detailed} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol';
55
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
6-
import {IAaveIncentivesController} from '@aave/core-v3/contracts/interfaces/IAaveIncentivesController.sol';
76
import {IUiPoolDataProvider} from './interfaces/IUiPoolDataProvider.sol';
87
import {IPool} from '@aave/core-v3/contracts/interfaces/IPool.sol';
98
import {IPriceOracleGetter} from '@aave/core-v3/contracts/interfaces/IPriceOracleGetter.sol';
@@ -17,19 +16,24 @@ import {DataTypes} from '@aave/core-v3/contracts/protocol/libraries/types/DataTy
1716
import {
1817
DefaultReserveInterestRateStrategy
1918
} from '@aave/core-v3/contracts/protocol/pool/DefaultReserveInterestRateStrategy.sol';
19+
import {IEACAggregatorProxy} from './interfaces/IEACAggregatorProxy.sol';
2020

2121
contract UiPoolDataProvider is IUiPoolDataProvider {
2222
using WadRayMath for uint256;
2323
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
2424
using UserConfiguration for DataTypes.UserConfigurationMap;
2525

26-
address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
27-
IAaveIncentivesController public immutable incentivesController;
28-
IPriceOracleGetter public immutable oracle;
26+
IEACAggregatorProxy public immutable networkBaseTokenPriceInUsdProxyAggregator;
27+
IEACAggregatorProxy public immutable marketReferenceCurrencyPriceInUsdProxyAggregator;
28+
uint256 public constant ETH_CURRENCY_UNIT = 1 ether;
2929

30-
constructor(IAaveIncentivesController _incentivesController, IPriceOracleGetter _oracle) {
31-
incentivesController = _incentivesController;
32-
oracle = _oracle;
30+
31+
constructor(
32+
IEACAggregatorProxy _networkBaseTokenPriceInUsdProxyAggregator,
33+
IEACAggregatorProxy _marketReferenceCurrencyPriceInUsdProxyAggregator
34+
) {
35+
networkBaseTokenPriceInUsdProxyAggregator = _networkBaseTokenPriceInUsdProxyAggregator;
36+
marketReferenceCurrencyPriceInUsdProxyAggregator = _marketReferenceCurrencyPriceInUsdProxyAggregator;
3337
}
3438

3539
function getInterestRateStrategySlopes(DefaultReserveInterestRateStrategy interestRateStrategy)
@@ -50,24 +54,29 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
5054
);
5155
}
5256

53-
function getReservesData(IPoolAddressesProvider provider, address user)
54-
external
57+
function getReservesList(IPoolAddressesProvider provider)
58+
public
59+
view
60+
override
61+
returns (address[] memory)
62+
{
63+
IPool pool = IPool(provider.getPool());
64+
return pool.getReservesList();
65+
}
66+
67+
function getReservesData(IPoolAddressesProvider provider)
68+
public
5569
view
5670
override
5771
returns (
5872
AggregatedReserveData[] memory,
59-
UserReserveData[] memory,
60-
uint256,
61-
uint256
73+
BaseCurrencyInfo memory
6274
)
6375
{
76+
IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle());
6477
IPool pool = IPool(provider.getPool());
6578
address[] memory reserves = pool.getReservesList();
66-
DataTypes.UserConfigurationMap memory userConfig = pool.getUserConfiguration(user);
67-
6879
AggregatedReserveData[] memory reservesData = new AggregatedReserveData[](reserves.length);
69-
UserReserveData[] memory userReservesData =
70-
new UserReserveData[](user != address(0) ? reserves.length : 0);
7180

7281
for (uint256 i = 0; i < reserves.length; i++) {
7382
AggregatedReserveData memory reserveData = reservesData[i];
@@ -76,17 +85,23 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
7685
// reserve current state
7786
DataTypes.ReserveData memory baseData =
7887
pool.getReserveData(reserveData.underlyingAsset);
88+
//the liquidity index. Expressed in ray
7989
reserveData.liquidityIndex = baseData.liquidityIndex;
90+
//variable borrow index. Expressed in ray
8091
reserveData.variableBorrowIndex = baseData.variableBorrowIndex;
92+
//the current supply rate. Expressed in ray
8193
reserveData.liquidityRate = baseData.currentLiquidityRate;
94+
//the current variable borrow rate. Expressed in ray
8295
reserveData.variableBorrowRate = baseData.currentVariableBorrowRate;
96+
//the current stable borrow rate. Expressed in ray
8397
reserveData.stableBorrowRate = baseData.currentStableBorrowRate;
8498
reserveData.lastUpdateTimestamp = baseData.lastUpdateTimestamp;
8599
reserveData.aTokenAddress = baseData.aTokenAddress;
86100
reserveData.stableDebtTokenAddress = baseData.stableDebtTokenAddress;
87101
reserveData.variableDebtTokenAddress = baseData.variableDebtTokenAddress;
102+
//address of the interest rate strategy
88103
reserveData.interestRateStrategyAddress = baseData.interestRateStrategyAddress;
89-
reserveData.priceInEth = oracle.getAssetPrice(reserveData.underlyingAsset);
104+
reserveData.priceInMarketReferenceCurrency = oracle.getAssetPrice(reserveData.underlyingAsset);
90105

91106
reserveData.availableLiquidity = IERC20Detailed(reserveData.underlyingAsset).balanceOf(
92107
reserveData.aTokenAddress
@@ -100,112 +115,114 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
100115
reserveData.totalScaledVariableDebt = IVariableDebtToken(reserveData.variableDebtTokenAddress)
101116
.scaledTotalSupply();
102117

103-
// reserve configuration
104-
105118
// we're getting this info from the aToken, because some of assets can be not compliant with ETC20Detailed
106-
reserveData.symbol = IERC20Detailed(reserveData.aTokenAddress).symbol();
119+
reserveData.symbol = IERC20Detailed(reserveData.underlyingAsset).symbol();
107120
reserveData.name = '';
108121

122+
(
123+
reserveData.variableRateSlope1,
124+
reserveData.variableRateSlope2,
125+
reserveData.stableRateSlope1,
126+
reserveData.stableRateSlope2
127+
) = getInterestRateStrategySlopes(
128+
DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress)
129+
);
130+
131+
132+
//stores the reserve configuration
133+
DataTypes.ReserveConfigurationMap memory reserveConfigurationMap = baseData.configuration;
134+
reserveData.debtCeiling = reserveConfigurationMap.getDebtCeiling();
135+
(reserveData.borrowCap, reserveData.supplyCap) = reserveConfigurationMap.getCaps();
136+
137+
uint256 eModeCategoryId;
109138
(
110139
reserveData.baseLTVasCollateral,
111140
reserveData.reserveLiquidationThreshold,
112141
reserveData.reserveLiquidationBonus,
113142
reserveData.decimals,
114143
reserveData.reserveFactor,
115-
) = baseData.configuration.getParams();
116-
(reserveData.borrowCap, reserveData.supplyCap) = baseData.configuration.getCaps();
144+
eModeCategoryId
145+
) = reserveConfigurationMap.getParams();
146+
reserveData.eModeCategoryId = uint8(eModeCategoryId);
147+
117148
(
118149
reserveData.isActive,
119150
reserveData.isFrozen,
120151
reserveData.borrowingEnabled,
121152
reserveData.stableBorrowRateEnabled,
122153
reserveData.isPaused
123-
) = baseData.configuration.getFlags();
154+
) = reserveConfigurationMap.getFlags();
124155
reserveData.usageAsCollateralEnabled = reserveData.baseLTVasCollateral != 0;
125-
(
126-
reserveData.variableRateSlope1,
127-
reserveData.variableRateSlope2,
128-
reserveData.stableRateSlope1,
129-
reserveData.stableRateSlope2
130-
) = getInterestRateStrategySlopes(
131-
DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress)
132-
);
156+
157+
DataTypes.EModeCategory memory categoryData = pool.getEModeCategoryData(reserveData.eModeCategoryId);
158+
reserveData.eModeLtv = categoryData.ltv;
159+
reserveData.eModeLiquidationThreshold =categoryData.liquidationThreshold;
160+
reserveData.eModeLiquidationBonus =categoryData.liquidationBonus;
161+
// each eMode category may or may not have a custom oracle to override the individual assets price oracles
162+
reserveData.eModePriceSource =categoryData.priceSource;
163+
reserveData.eModeLabel = categoryData.label;
164+
}
133165

134-
// incentives
135-
if (address(0) != address(incentivesController)) {
136-
(
137-
reserveData.aEmissionPerSecond,
138-
reserveData.aIncentivesLastUpdateTimestamp,
139-
reserveData.aTokenIncentivesIndex
140-
) = incentivesController.getAssetData(reserveData.aTokenAddress);
141-
142-
(
143-
reserveData.sEmissionPerSecond,
144-
reserveData.sIncentivesLastUpdateTimestamp,
145-
reserveData.sTokenIncentivesIndex
146-
) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress);
147-
148-
(
149-
reserveData.vEmissionPerSecond,
150-
reserveData.vIncentivesLastUpdateTimestamp,
151-
reserveData.vTokenIncentivesIndex
152-
) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress);
153-
}
166+
BaseCurrencyInfo memory baseCurrencyInfo;
167+
baseCurrencyInfo.networkBaseTokenPriceInUsd = networkBaseTokenPriceInUsdProxyAggregator.latestAnswer();
168+
baseCurrencyInfo.networkBaseTokenPriceDecimals = networkBaseTokenPriceInUsdProxyAggregator.decimals();
154169

155-
if (user != address(0)) {
156-
// incentives
157-
if (address(0) != address(incentivesController)) {
158-
userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData(
159-
user,
160-
reserveData.aTokenAddress
161-
);
162-
userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData(
163-
user,
164-
reserveData.variableDebtTokenAddress
165-
);
166-
userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData(
167-
user,
168-
reserveData.stableDebtTokenAddress
169-
);
170-
}
171-
// user reserve data
172-
userReservesData[i].underlyingAsset = reserveData.underlyingAsset;
173-
userReservesData[i].scaledATokenBalance = IAToken(reserveData.aTokenAddress)
174-
.scaledBalanceOf(user);
175-
userReservesData[i].usageAsCollateralEnabledOnUser = userConfig.isUsingAsCollateral(i);
170+
try oracle.BASE_CURRENCY_UNIT() returns (uint256 baseCurrencyUnit) {
171+
baseCurrencyInfo.marketReferenceCurrencyUnit = baseCurrencyUnit;
172+
baseCurrencyInfo.marketReferenceCurrencyPriceInUsd = int256(baseCurrencyUnit);
173+
} catch (bytes memory /*lowLevelData*/) {
174+
baseCurrencyInfo.marketReferenceCurrencyUnit = ETH_CURRENCY_UNIT;
175+
baseCurrencyInfo.marketReferenceCurrencyPriceInUsd = marketReferenceCurrencyPriceInUsdProxyAggregator.latestAnswer();
176+
}
176177

177-
if (userConfig.isBorrowing(i)) {
178-
userReservesData[i].scaledVariableDebt = IVariableDebtToken(
179-
reserveData
180-
.variableDebtTokenAddress
181-
)
182-
.scaledBalanceOf(user);
183-
userReservesData[i].principalStableDebt = IStableDebtToken(
184-
reserveData
178+
return (reservesData, baseCurrencyInfo);
179+
}
180+
181+
function getUserReservesData(IPoolAddressesProvider provider, address user)
182+
external
183+
view
184+
override
185+
returns (UserReserveData[] memory, uint8)
186+
{
187+
IPool pool = IPool(provider.getPool());
188+
address[] memory reserves = pool.getReservesList();
189+
DataTypes.UserConfigurationMap memory userConfig = pool.getUserConfiguration(user);
190+
191+
uint8 userEmodeCategoryId = uint8(pool.getUserEMode((user)));
192+
193+
UserReserveData[] memory userReservesData =
194+
new UserReserveData[](user != address(0) ? reserves.length : 0);
195+
196+
for (uint256 i = 0; i < reserves.length; i++) {
197+
DataTypes.ReserveData memory baseData = pool.getReserveData(reserves[i]);
198+
199+
// user reserve data
200+
userReservesData[i].underlyingAsset = reserves[i];
201+
userReservesData[i].scaledATokenBalance = IAToken(baseData.aTokenAddress).scaledBalanceOf(
202+
user
203+
);
204+
userReservesData[i].usageAsCollateralEnabledOnUser = userConfig.isUsingAsCollateral(i);
205+
206+
if (userConfig.isBorrowing(i)) {
207+
userReservesData[i].scaledVariableDebt = IVariableDebtToken(
208+
baseData
209+
.variableDebtTokenAddress
210+
)
211+
.scaledBalanceOf(user);
212+
userReservesData[i].principalStableDebt = IStableDebtToken(baseData.stableDebtTokenAddress)
213+
.principalBalanceOf(user);
214+
if (userReservesData[i].principalStableDebt != 0) {
215+
userReservesData[i].stableBorrowRate = IStableDebtToken(baseData.stableDebtTokenAddress)
216+
.getUserStableRate(user);
217+
userReservesData[i].stableBorrowLastUpdateTimestamp = IStableDebtToken(
218+
baseData
185219
.stableDebtTokenAddress
186220
)
187-
.principalBalanceOf(user);
188-
if (userReservesData[i].principalStableDebt != 0) {
189-
userReservesData[i].stableBorrowRate = IStableDebtToken(
190-
reserveData
191-
.stableDebtTokenAddress
192-
)
193-
.getUserStableRate(user);
194-
userReservesData[i].stableBorrowLastUpdateTimestamp = IStableDebtToken(
195-
reserveData
196-
.stableDebtTokenAddress
197-
)
198-
.getUserLastUpdated(user);
199-
}
221+
.getUserLastUpdated(user);
200222
}
201223
}
202224
}
203225

204-
return (
205-
reservesData,
206-
userReservesData,
207-
oracle.getAssetPrice(MOCK_USD_ADDRESS),
208-
incentivesController.getUserUnclaimedRewards(user)
209-
);
226+
return (userReservesData, userEmodeCategoryId);
210227
}
211228
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: agpl-3.0
2+
pragma solidity 0.8.7;
3+
4+
interface IEACAggregatorProxy {
5+
function decimals() external view returns (uint8);
6+
7+
function latestAnswer() external view returns (int256);
8+
9+
function latestTimestamp() external view returns (uint256);
10+
11+
function latestRound() external view returns (uint256);
12+
13+
function getAnswer(uint256 roundId) external view returns (int256);
14+
15+
function getTimestamp(uint256 roundId) external view returns (uint256);
16+
17+
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp);
18+
event NewRound(uint256 indexed roundId, address indexed startedBy);
19+
}

0 commit comments

Comments
 (0)