Oracle will not failover as expected during liquidation
Oracle will not failover as expected during liquidation. If the liquidation cannot be executed due to the revert described in the following scenario, underwater positions and bad debt accumulate in the protocol, threatening the solvency of the protocol.\\nThe liquidators have the option to update the Pyth price during liquidation. If the liquidators do not intend to update the Pyth price during liquidation, they have to call the second `liquidate(uint256 tokenId)` function at Line 85 below directly, which does not have the `updatePythPrice` modifier.\\n```\\nFile: LiquidationModule.sol\\n    function liquidate(\\n        uint256 tokenID,\\n        bytes[] calldata priceUpdateData\\n    ) external payable whenNotPaused updatePythPrice(vault, msg.sender, priceUpdateData) {\\n        liquidate(tokenID);\\n    }\\n\\n    /// @notice Function to liquidate a position.\\n    /// @dev One could directly call this method instead of `liquidate(uint256, bytes[])` if they don't want to update the Pyth price.\\n    /// @param tokenId The token ID of the leverage position.\\n    function liquidate(uint256 tokenId) public nonReentrant whenNotPaused liquidationInvariantChecks(vault, tokenId) {\\n        FlatcoinStructs.Position memory position = vault.getPosition(tokenId);\\n```\\n\\nIt was understood from the protocol team that the rationale for allowing the liquidators to execute a liquidation without updating the Pyth price is to ensure that the liquidations will work regardless of Pyth's working status, in which case Chainlink is the fallback, and the last oracle price will be used for the liquidation.\\nHowever, upon further review, it was found that the fallback mechanism within the FlatCoin protocol does not work as expected by the protocol team.\\nAssume that Pyth is down. In this case, no one would be able to fetch the latest off-chain price from Pyth network and update Pyth on-chain contract. As a result, the prices stored in the Pyth on-chain contract will become outdated and stale.\\nWhen liquidation is executed in FlatCoin protocol, the following `_getPrice` function will be executed to fetch the price. Line 107 below will fetch the latest price from Chainlink, while Line 108 below will fetch the last available price on the Pyth on-chain contract. When the Pyth on-chain prices have not been updated for a period of time, the deviation between `onchainPrice` and `offchainPrice` will widen till a point where `diffPercent > maxDiffPercent` and a revert will occur at Line 113 below, thus blocking the liquidation from being carried out. As a result, the liquidation mechanism within the FlatCoin protocol will stop working.\\nAlso, the protocol team's goal of allowing the liquidators to execute a liquidation without updating the Pyth price to ensure that the liquidations will work regardless of Pyth's working status will not be achieved.\\n```\\nFile: OracleModule.sol\\n    /// @notice Returns the latest 18 decimal price of asset from either Pyth.network or Chainlink.\\n    /// @dev It verifies the Pyth network price against Chainlink price (ensure that it is within a threshold).\\n    /// @return price The latest 18 decimal price of asset.\\n    /// @return timestamp The timestamp of the latest price.\\n    function _getPrice(uint32 maxAge) internal view returns (uint256 price, uint256 timestamp) {\\n        (uint256 onchainPrice, uint256 onchainTime) = _getOnchainPrice(); // will revert if invalid\\n        (uint256 offchainPrice, uint256 offchainTime, bool offchainInvalid) = _getOffchainPrice();\\n        bool offchain;\\n\\n        uint256 priceDiff = (int256(onchainPrice) - int256(offchainPrice)).abs();\\n        uint256 diffPercent = (priceDiff * 1e18) / onchainPrice;\\n        if (diffPercent > maxDiffPercent) revert FlatcoinErrors.PriceMismatch(diffPercent);\\n\\n        if (offchainInvalid == false) {\\n            // return the freshest price\\n            if (offchainTime >= onchainTime) {\\n                price = offchainPrice;\\n                timestamp = offchainTime;\\n                offchain = true;\\n            } else {\\n                price = onchainPrice;\\n                timestamp = onchainTime;\\n            }\\n        } else {\\n            price = onchainPrice;\\n            timestamp = onchainTime;\\n        }\\n\\n        // Check that the timestamp is within the required age\\n        if (maxAge < type(uint32).max && timestamp + maxAge < block.timestamp) {\\n            revert FlatcoinErrors.PriceStale(\\n                offchain ? FlatcoinErrors.PriceSource.OffChain : FlatcoinErrors.PriceSource.OnChain\\n            );\\n        }\\n    }\\n```\\n
Consider implementing a feature to allow the protocol team to disable the price deviation check so that the protocol team can disable it in the event that Pyth network is down for an extended period of time.
The liquidation mechanism is the core component of the protocol and is important to the solvency of the protocol. If the liquidation cannot be executed due to the revert described in the above scenario, underwater positions and bad debt accumulate in the protocol threaten the solvency of the protocol.
```\\nFile: LiquidationModule.sol\\n    function liquidate(\\n        uint256 tokenID,\\n        bytes[] calldata priceUpdateData\\n    ) external payable whenNotPaused updatePythPrice(vault, msg.sender, priceUpdateData) {\\n        liquidate(tokenID);\\n    }\\n\\n    /// @notice Function to liquidate a position.\\n    /// @dev One could directly call this method instead of `liquidate(uint256, bytes[])` if they don't want to update the Pyth price.\\n    /// @param tokenId The token ID of the leverage position.\\n    function liquidate(uint256 tokenId) public nonReentrant whenNotPaused liquidationInvariantChecks(vault, tokenId) {\\n        FlatcoinStructs.Position memory position = vault.getPosition(tokenId);\\n```\\n