This report identifies a potential vulnerability in the getSqrtPrice function of the protocol. The function retrieves price data from two separate oracles: a Chainlink oracle and an IPyth oracle. While the function verifies the validity of the IPyth price data by ensuring it's not older than a specified time period (VALID_TIME_PERIOD), it does not perform a similar check for the Chainlink oracle data. This omission could lead to the use of stale prices in the calculation of the square root price (sqrtPrice), potentially impacting various functionalities within the protocol.
Proof of Concept
The sqrtPrice calculated using potentially stale Chainlink data might not reflect the true market price. this is actively used in position calculation
function getSqrtIndexPrice(DataType.PairStatus memory pairStatus) internal view returns (uint256 sqrtPriceX96) {
if (pairStatus.priceFeed != address(0)) {
return PriceFeed(pairStatus.priceFeed).getSqrtPrice();
The value obtained from the feed are used to Calculate minmargin which are also critical to other sensitive functions used to liquidate and check the vault's health. Using a stale price can prevent the liquidation of an account that should be liquidated as the vault will still be safe.
To mitigate this vulnerability, it's recommended to implement a similar timeliness check for the Chainlink oracle data as the one currently in place for the IPyth data. Here's an approach:
Retrieve Latest Chainlink Data: Use the latestRoundData function of the AggregatorV3Interface to obtain the most recent price data from the Chainlink oracle.
Verify Timestamp: Check the timestamp associated with the retrieved Chainlink data. This timestamp should be within an acceptable time limit ( VALID_TIME_PERIOD = 5 * 60).
Reject Stale Data: If the timestamp indicates that the Chainlink data is older than the acceptable time limit, revert the function or throw an error, preventing the use of stale data.
Lines of code
https://github.com/code-423n4/2024-05-predy/blob/a9246db5f874a91fb71c296aac6a66902289306a/src/PriceFeed.sol#L46-L52 https://github.com/code-423n4/2024-05-predy/blob/a9246db5f874a91fb71c296aac6a66902289306a/src/libraries/PositionCalculator.sol#L141-L147
Vulnerability details
Impact
This report identifies a potential vulnerability in the
getSqrtPrice
function of the protocol. The function retrieves price data from two separate oracles: a Chainlink oracle and an IPyth oracle. While the function verifies the validity of the IPyth price data by ensuring it's not older than a specified time period (VALID_TIME_PERIOD
), it does not perform a similar check for the Chainlink oracle data. This omission could lead to the use of stale prices in the calculation of the square root price (sqrtPrice
), potentially impacting various functionalities within the protocol.Proof of Concept
The
sqrtPrice
calculated using potentially stale Chainlink data might not reflect the true market price. this is actively used in position calculationThe value obtained from the feed are used to Calculate minmargin which are also critical to other sensitive functions used to liquidate and check the vault's health. Using a stale price can prevent the liquidation of an account that should be liquidated as the vault will still be safe.
Tools Used
Recommended Mitigation Steps
To mitigate this vulnerability, it's recommended to implement a similar timeliness check for the Chainlink oracle data as the one currently in place for the IPyth data. Here's an approach:
latestRoundData
function of theAggregatorV3Interface
to obtain the most recent price data from the Chainlink oracle.VALID_TIME_PERIOD
= 5 * 60).Assessed type
Oracle