Vulnerability: Price calculation can be manipulated by intentionally reverting some of price feeds.
Severity: medium

Description:
Price calculation module iterates through available price feeds for the requested asset, gather prices of non-revert price feeds and then apply strategy on available prices to calculate final asset price. By abusing this functionality, an attacker can let some price feeds revert to get advantage from any manipulated price feed.\\nHere we have some methods that attackers can abuse to intentionally revert price feeds.\\nUniswapV3 price feed UniswapV3Price.sol#L210-214\\n```\\n// Get the current price of the lookup token in terms of the quote token\\n(, int24 currentTick, , , , , bool unlocked) = params.pool.slot0();\\n\\n// Check for re-entrancy\\nif (unlocked == false) revert UniswapV3_PoolReentrancy(address(params.pool));\\n```\\n\\nIn UniswapV3 price feed, it reverts if current state is re-entered. An attacker can intentionally revert this price feed by calling it from UniswapV3's callback methods.\\nBalancer price feed BalancerPoolTokenPrice.sol#L388 BalancerPoolTokenPrice.sol#487 BalancerPoolTokenPrice.sol#599 BalancerPoolTokenPrice.sol#748\\n```\\n// Prevent re-entrancy attacks\\nVaultReentrancyLib.ensureNotInVaultContext(balVault);\\n```\\n\\nIn BalancerPool price feed, it reverts if current state is re-entered. An attacker can intentionally revert this price feed by calling it in the middle of Balancer action.\\nBunniToken price feed BunniPirce.sol#L155-160\\n```\\n_validateReserves(\\n    _getBunniKey(token),\\n    lens,\\n    params.twapMaxDeviationsBps,\\n    params.twapObservationWindow\\n);\\n```\\n\\nIn BunniToken price feed, it validates reserves and reverts if it doesn't satisfy deviation. Since BunniToken uses UniswapV3, this can be intentionally reverted by calling it from UniswapV3's mint callback.\\n\\nUsually for ERC20 token prices, above 3 price feeds are commonly used combined with Chainlink price feed, and optionally with `averageMovingPrice`. There are another two points to consider here:\\nWhen average moving price is used, it is appended at the end of the price array. OlympusPrice.v2.sol#L160\\n```\\nif (asset.useMovingAverage) prices[numFeeds] = asset.cumulativeObs / asset.numObservations;\\n```\\n\\nIn price calculation strategy, first non-zero price is used when there are 2 valid prices: `getMedianPriceIfDeviation` - SimplePriceFeedStrategy.sol#L246 `getMedianPrice` - SimplePriceFeedStrategy.sol#L313 For `getAveragePrice` and `getAveragePriceIfDeviation`, it uses average price if it deviates.\\n\\nBased on the information above, here are potential attack vectors that attackers would try:\\nWhen Chainlink price feed is manipulated, an attacker can disable all three above price feeds intentionally to get advantage of the price manipulation.\\nWhen Chainlink price feed is not used for an asset, an attacker can manipulate one of above 3 spot price feeds and disable other ones.\\nWhen `averageMovingPrice` is used and average price strategy is applied, the manipulation effect becomes half: $\\frac{(P + \\Delta X) + (P)}{2} = P + \\frac{\\Delta X}{2}, P=Market Price, \\Delta X=Manipulated Amount$

Impact:
Attackers can disable some of price feeds as they want with ease, they can get advantage of one manipulated price feed.

Recommended mitigation:
For the cases above that price feeds being intentionally reverted, the price calculation itself also should revert without just ignoring it.