Skip to content

Commit 4a742cd

Browse files
committed
fix: PriceFeedCompressor fixes
1 parent 0a2c20d commit 4a742cd

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

contracts/compressors/PriceFeedCompressor.sol

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ interface ImplementsPriceFeedType {
3030
/// - it does not implement `getTokens`
3131
/// - it only allows to fetch staleness period of a currently active price feed
3232
interface IPriceOracleV3Legacy {
33-
/// @dev Older signature for fetching main and reserve feeds
33+
/// @dev Older signature for fetching main and reserve feeds, reverts if price feed is not set
3434
function priceFeedsRaw(address token, bool reserve) external view returns (address);
3535
}
3636

@@ -90,9 +90,6 @@ contract PriceFeedCompressor is IVersion, Ownable {
9090
/// - `priceFeedTree` is a set of nodes in a tree-like structure that contains detailed info of both feeds
9191
/// from `priceFeedMap` and their underlying feeds, in case former are nested, which can help to determine
9292
/// what underlying feeds should be updated to query the nested one.
93-
/// @dev `priceFeedTree` can have duplicate entries since a price feed can both be in `priceFeedMap` for one or
94-
/// more (token, reserve) pairs, and serve as an underlying feed in one or more nested feeds.
95-
/// If there are two identical nodes in the tree, then subtrees of these nodes are also identical.
9693
function getPriceFeeds(address priceOracle)
9794
external
9895
view
@@ -138,6 +135,10 @@ contract PriceFeedCompressor is IVersion, Ownable {
138135
for (uint256 i; i < priceFeedMapSize; ++i) {
139136
offset = _loadPriceFeedTree(priceFeedMap[i].priceFeed, priceFeedTree, offset);
140137
}
138+
// trim array to its actual size in case there were duplicates
139+
assembly {
140+
mstore(priceFeedTree, offset)
141+
}
141142
}
142143

143144
// --------- //
@@ -155,9 +156,12 @@ contract PriceFeedCompressor is IVersion, Ownable {
155156
/// @dev Returns `token`'s price feed in the price oracle
156157
function _getPriceFeed(address priceOracle, address token, bool reserve) internal view returns (address, uint32) {
157158
if (IPriceOracleV3(priceOracle).version() < 3_10) {
158-
address priceFeed = IPriceOracleV3Legacy(priceOracle).priceFeedsRaw(token, reserve);
159-
// legacy oracle does not allow to fetch staleness period of a non-active feed
160-
return (priceFeed, 0);
159+
try IPriceOracleV3Legacy(priceOracle).priceFeedsRaw(token, reserve) returns (address priceFeed) {
160+
// legacy oracle does not allow to fetch staleness period of a non-active feed
161+
return (priceFeed, 0);
162+
} catch {
163+
return (address(0), 0);
164+
}
161165
}
162166
PriceFeedParams memory params = reserve
163167
? IPriceOracleV3(priceOracle).reservePriceFeedParams(token)
@@ -180,6 +184,12 @@ contract PriceFeedCompressor is IVersion, Ownable {
180184
view
181185
returns (uint256)
182186
{
187+
// duplicates are possible since price feed can be in `priceFeedMap` for more than one (token, reserve) pair
188+
// or serve as an underlying in more than one nested feed, and the whole subtree can be skipped in this case
189+
for (uint256 i; i < offset; ++i) {
190+
if (priceFeedTree[i].priceFeed == priceFeed) return offset;
191+
}
192+
183193
PriceFeedTreeNode memory node = _getPriceFeedTreeNode(priceFeed);
184194
priceFeedTree[offset++] = node;
185195
for (uint256 i; i < node.underlyingFeeds.length; ++i) {

0 commit comments

Comments
 (0)