33// (c) Gearbox Holdings, 2024
44pragma solidity ^ 0.8.10 ;
55
6- import {IPriceHelper, TokenPriceInfo} from "./interfaces/IPriceHelper.sol " ;
6+ import {IPriceHelper, PriceOnDemand, TokenPriceInfo} from "./interfaces/IPriceHelper.sol " ;
77import {ICreditAccountV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditAccountV3.sol " ;
88import {ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol " ;
99import {IPriceOracleV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IPriceOracleV3.sol " ;
10- import {IPriceFeed} from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceFeed.sol " ;
10+ import {IPriceFeed, IUpdatablePriceFeed } from "@gearbox-protocol/core-v2/contracts/interfaces/IPriceFeed.sol " ;
1111import {IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
1212import {IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol " ;
13+ import "@gearbox-protocol/core-v3/contracts/interfaces/IExceptions.sol " ;
1314
1415contract PriceHelper is IPriceHelper {
15- function previewTokens (address creditAccount ) external view returns (TokenPriceInfo[] memory results ) {
16+ function previewTokens (address creditAccount , PriceOnDemand[] memory priceUpdates )
17+ external
18+ returns (TokenPriceInfo[] memory results )
19+ {
1620 ICreditManagerV3 creditManager = ICreditManagerV3 (ICreditAccountV3 (creditAccount).creditManager ());
21+ address oracle = creditManager.priceOracle ();
22+
23+ _updatePrices (oracle, priceUpdates);
24+
1725 address underlying = creditManager.underlying ();
1826 uint256 underlyingScale = 10 ** IERC20Metadata (underlying).decimals ();
19- address oracle = creditManager.priceOracle ();
2027 uint256 enabledTokensMask = creditManager.enabledTokensMaskOf (creditAccount);
21- uint256 priceTo = _getUnupdatedPrice (oracle, underlying);
28+ uint256 priceTo = _unsafeGetPrice (oracle, underlying);
2229
2330 uint256 len = creditManager.collateralTokensCount ();
2431 uint256 cnt = 0 ;
@@ -34,7 +41,7 @@ contract PriceHelper is IPriceHelper {
3441 if (info.token == underlying) {
3542 info.balanceInUnderlying = info.balance;
3643 } else {
37- uint256 priceFrom = _getUnupdatedPrice (oracle, info.token);
44+ uint256 priceFrom = _unsafeGetPrice (oracle, info.token);
3845 info.balanceInUnderlying = info.balance * priceFrom * underlyingScale / (priceTo * tokenScale);
3946 }
4047 tmp[cnt] = info;
@@ -51,8 +58,22 @@ contract PriceHelper is IPriceHelper {
5158 }
5259 }
5360
54- /// @dev Returns price feed answer while trying to ignore that can happen due to unupdated PULL oracles
55- function _getUnupdatedPrice (address oracle , address token ) internal view returns (uint256 price ) {
61+ function _updatePrices (address priceOracle , PriceOnDemand[] memory priceUpdates ) internal {
62+ IPriceOracleV3 oracle = IPriceOracleV3 (priceOracle);
63+ uint256 len = priceUpdates.length ;
64+ unchecked {
65+ for (uint256 i; i < len; ++ i) {
66+ address priceFeed = oracle.priceFeeds (priceUpdates[i].token);
67+ if (priceFeed == address (0 )) {
68+ revert PriceFeedDoesNotExistException ();
69+ }
70+ IUpdatablePriceFeed (priceFeed).updatePrice (priceUpdates[i].callData);
71+ }
72+ }
73+ }
74+
75+ /// @dev Returns price feed answer while trying to ignore revert that can happen due to unupdated PULL oracles
76+ function _unsafeGetPrice (address oracle , address token ) internal view returns (uint256 price ) {
5677 IPriceOracleV3 priceOracle = IPriceOracleV3 (oracle);
5778
5879 // check main price feed
0 commit comments