Positions may be liquidated due to incorrect implementation of Oracle logic
Steadefi checks for historical data to make sure that last price update are within maximum delya allowed and in the range of maximum % deviation allowed.\\nBut checking the historical data is incorrect according to the chainlink docs which can damage some serious logic with in the protcol\\nVault calls ChainlinkARBOracle.consult(token) to get the fair price from chainlink oracle\\n```\\nFile:\\n\\n  function consult(address token) public view whenNotPaused returns (int256, uint8) {\\n    address _feed = feeds[token];\\n\\n    if (_feed == address(0)) revert Errors.NoTokenPriceFeedAvailable();\\n\\n    ChainlinkResponse memory chainlinkResponse = _getChainlinkResponse(_feed);\\n    ChainlinkResponse memory prevChainlinkResponse = _getPrevChainlinkResponse(_feed, chainlinkResponse.roundId);//@audit incorrect way to get historical data\\n    if (_chainlinkIsFrozen(chainlinkResponse, token)) revert Errors.FrozenTokenPriceFeed();\\n    if (_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse, token)) revert Errors.BrokenTokenPriceFeed();\\n\\n return (chainlinkResponse.answer, chainlinkResponse.decimals);\\n  }\\n```\\n\\nhttps://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/ChainlinkARBOracle.sol#L62\\nwhich calls an interval function `_getPrevChainlinkResponse()` and try to fetch previous roundId price and other details\\n```\\n  function _getPrevChainlinkResponse(address _feed, uint80 _currentRoundId) internal view returns (ChainlinkResponse memory) {\\n    ChainlinkResponse memory _prevChainlinkResponse;\\n\\n    (\\n      uint80 _roundId,\\n      int256 _answer,\\n      /* uint256 _startedAt */,\\n      uint256 _timestamp,\\n      /* uint80 _answeredInRound */\\n    ) = AggregatorV3Interface(_feed).getRoundData(_currentRoundId - 1);\\n\\n    _prevChainlinkResponse.roundId = _roundId;\\n    _prevChainlinkResponse.answer = _answer;\\n    _prevChainlinkResponse.timestamp = _timestamp;\\n    _prevChainlinkResponse.success = true;\\n\\n    return _prevChainlinkResponse;\\n  }\\n```\\n\\nhttps://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/ChainlinkARBOracle.sol#L210\\nBut this is incorrect way of fetching historical data. chainlink docs say: `Oracles provide periodic data updates to the aggregators. Data feeds are updated in rounds. Rounds are identified by their roundId, which increases with each new round. This increase may not be monotonic. Knowing the roundId of a previous round allows contracts to consume historical data.\\nThe examples in this document name the aggregator roundId as aggregatorRoundId to differentiate it from the proxy roundId.` check here\\nso it is not mendatory that there will be valid data for currentRoundID-1. if there is not data for currentRooundId-1 then `_badPriceDeviation(currChainlinkResponse,PrevResponse)` check here will return true. Hence vault won't able to get the price of token at some specific times
Positions may be liquidated due to incorrect implementation of Oracle logic\\nAs chainlink docs says. Increase in roundId may not be monotonic so loop through the previous roundID and fetch the previoous roundId data\\npseudo code\\n```\\n iterate (from roundId-1 to untill we get previous first data corressponding to roundID){\\n    if(data present for roundID){\\n        fetch the data and return\\n    }else{\\n        again iterate to get the data\\n    }\\n }\\n```\\n
In worse case keeper won't able to get the price of token so rebalancing , debt repay won't be possible leading to liquidation breaking the main important factor of protocol\\nAlmost 70% of vault action is dependent on price of a token and not getting price will make them inactive affecting net APR
```\\nFile:\\n\\n  function consult(address token) public view whenNotPaused returns (int256, uint8) {\\n    address _feed = feeds[token];\\n\\n    if (_feed == address(0)) revert Errors.NoTokenPriceFeedAvailable();\\n\\n    ChainlinkResponse memory chainlinkResponse = _getChainlinkResponse(_feed);\\n    ChainlinkResponse memory prevChainlinkResponse = _getPrevChainlinkResponse(_feed, chainlinkResponse.roundId);//@audit incorrect way to get historical data\\n    if (_chainlinkIsFrozen(chainlinkResponse, token)) revert Errors.FrozenTokenPriceFeed();\\n    if (_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse, token)) revert Errors.BrokenTokenPriceFeed();\\n\\n return (chainlinkResponse.answer, chainlinkResponse.decimals);\\n  }\\n```\\n