DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: low
Invalid

The `SettlementConfiguration::requireDataStreamsReportIsValid` function uses block.timestamp

Summary

The SettlementConfiguration::requireDataStreamsReportIsValid function uses block.timestamp . The result is that others functions that expect valid data report may receive delayed report and in a more serious case, orders could be filled with an incorrect fillPriceX18.

Vulnerability Details

To fill market orders and off-chain orders, the order keeper should call SettlementBranch::fillMarketOrder and SettlementBranch::fillOffchainOrders functions respectively. Those functions set the bidX18 and askX18 prices of their contexts by calling the SettlementConfiguration:: verifyOffchainPrice function which calls the SettlementConfiguration:: requireDataStreamsReportIsValid function and returns the bid and ask prices from the verified premium report.

The SettlementConfiguration::requireDataStreamsReportIsValid function uses block.timestamp to checks if the provided data streams report is using the expected stream id, which could be manipulated by miners to a small degree, potentially allowing the use of delayed premium report if it is using the expected stream id.

Impact

Filling market orders and off-chain orders with wrong fillPriceX18 will lead to incorrect trading account values of pnlUsdX18 andorderFeeUsdX18 possibly making the protocol losing funds and so will do the traders.

Code Snippet

File: src/perpetuals/leaves/SettlementConfiguration.sol
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);
}
}
function verifyOffchainPrice(
Data storage self,
bytes memory priceData,
uint256 maxVerificationDelay
)
internal
returns (UD60x18 bidX18, UD60x18 askX18)
{
if (self.strategy == Strategy.DATA_STREAMS_DEFAULT) {
DataStreamsStrategy memory dataStreamsStrategy = abi.decode(self.data, (DataStreamsStrategy));
bytes memory verifiedPriceData = verifyDataStreamsReport(dataStreamsStrategy, priceData);
requireDataStreamsReportIsValid(dataStreamsStrategy.streamId, verifiedPriceData, maxVerificationDelay);
PremiumReport memory premiumReport = abi.decode(verifiedPriceData, (PremiumReport));
(bidX18, askX18) =
(ud60x18(int256(premiumReport.bid).toUint256()), ud60x18(int256(premiumReport.ask).toUint256()));
} else {
revert Errors.InvalidSettlementStrategy();
}
}

Tools Used

Manual review.

Recommendations

Use a more robust timestamp source

Updates

Lead Judging Commences

inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.