Summary
The function related to settlement of orders needs to check whether the priceDatais valid or not. However, some of the checks are missing which may result in stale price being used for order.
Vulnerability Details
Below is the function:
https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/leaves/SettlementConfiguration.sol#L87-L103
function requireDataStreamsReportIsValid(
bytes32 streamId,
bytes memory verifiedReportData,
uint256 maxVerificationDelay
)
internal
view
{
PremiumReport memory premiumReport = abi.decode(verifiedReportData, (PremiumReport));
if (
streamId != premiumReport.feedId
|| block.timestamp > premiumReport.validFromTimestamp + maxVerificationDelay
) {
revert Errors.InvalidDataStreamReport(streamId, premiumReport.feedId);
}
}
PremiumReportstruct is as follows:
struct PremiumReport {
bytes32 feedId;
uint32 validFromTimestamp;
uint32 observationsTimestamp;
uint192 nativeFee;
uint192 linkFee;
uint32 expiresAt;
int192 price;
int192 bid;
int192 ask;
}
The function requireDataStreamsReportIsValiddoesn't check if the price data is valid at block.timestamp. It also doesn't check if the report is expired or not. Due to this, orders may be filled with expired price data. Also, the keepercan also be any users for the protocol. So, they can feed expired price data for order settlement causing traders to get unfair prices.
The function is being used at following places:
https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/branches/SettlementBranch.sol#L138-L139
https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/branches/SettlementBranch.sol#L209-L210
Impact
Users may get their orders filled using expired price data.
Tools Used
Manual
Recommendations
Add following check in the mentioned function
if (
streamId != premiumReport.feedId
|| block.timestamp > premiumReport.validFromTimestamp + maxVerificationDelay
|| block.timestamp > expiresAt || block.timestamp > observationsTimestamp
) {
revert Errors.InvalidDataStreamReport(streamId, premiumReport.feedId);
}