MEDIUM severity: The `storePrice` function in the `OlympusPrice.v2.sol` contract is responsible for updating the movi. The `storePrice` function in the `OlympusPrice.v2.sol` contract is responsible for updating the moving average prices for a given asset. However, a vulnerability exists in the way the moving average prices are calculated. When `asset.useMovingAverage` is set to `true`, the `_getCurrentPrice` functio...

Vulnerable code:
```\nfunction storePrice(address asset_) public override permissioned {\n    Asset storage asset = _assetData[asset_];\n\n    // Check if asset is approved\n    if (!asset.approved) {\n        revert PRICE_AssetNotApproved(asset_);\n    }\n\n    // Get the current price for the asset\n    (uint256 price, uint48 currentTime) = _getCurrentPrice(asset_);\n\n    // Store the data in the obs index\n    uint256 oldestPrice = asset.obs[asset.nextObsIndex];\n    asset.obs[asset.nextObsIndex] = price;\n\n    // Update the last observation time and increment the next index\n    asset.lastObservationTime = currentTime;\n    asset.nextObsIndex = (asset.nextObsIndex + 1) % asset.numObservations;\n\n    // Update the cumulative observation, if storing the moving average\n    if (asset.storeMovingAverage) {\n        asset.cumulativeObs = asset.cumulativeObs + price - oldestPrice;\n    }\n\n    // Emit event\n    emit PriceStored(asset_, price, currentTime);\n}\n```\n```\nfunction _getCurrentPrice(address asset_) internal view returns (uint256, uint48) {\n    Asset storage asset = _assetData[asset_];\n\n    // Iterate through feeds to get prices to aggregate with strategy\n    Component[] memory feeds = abi.decode(asset.feeds, (Component[]));\n    uint256 numFeeds = feeds.length;\n\n    uint256[] memory prices = asset.useMovingAverage\n       ? new uint256[](numFeeds + 1)\n        : new uint256[](numFeeds);\n    uint8 _decimals = decimals; // cache in memory to save gas\n    for (uint256 i = 0; i < numFeeds; i++) {\n        (bool success_, bytes memory data_) = address(_getSubmoduleIfInstalled(feeds[i].target))\n           .staticcall(\n                abi.encodeWithSelector(feeds[i].selector, asset_, _decimals, feeds[i].params)\n            );\n\n        // Store price if successful, otherwise leave as zero\n        // Idea is that if you have several price calls and just\n        // one fails, it'll DOS the contract with this revert.\n        // We handle faulty feeds in the strategy contract.\n        if (success_) prices[i] = abi.decode(data_, (uint256));\n    }\n\n    // If moving average is used in strategy, add to end of prices array\n    if (asset.useMovingAverage) prices[numFeeds] = asset.cumulativeObs / asset.numObservations;\n\n    // If there is only one price, ensure it is not zero and return\n    // Otherwise, send to strategy to aggregate\n    if (prices.length == 1) {\n        if (prices[0] == 0) revert PRICE_PriceZero(asset_);\n        return (prices[0], uint48(block.timestamp));\n    } else {\n        // Get price from strategy\n        Component memory strategy = abi.decode(asset.strategy, (Component));\n        (bool success, bytes memory data) = address(_getSubmoduleIfInstalled(strategy.target))\n           .staticcall(abi.encodeWithSelector(strategy.selector, prices, strategy.params));\n\n        // Ensure call was successful\n        if (!success) revert PRICE_StrategyFailed(asset_, data);\n\n        // Decode asset price\n        uint256 price = abi.decode(data, (uint256));\n\n        // Ensure value is not zero\n        if (price == 0) revert PRICE_PriceZero(asset_);\n\n        return (price, uint48(block.timestamp));\n    }\n}\n```