Boost _ Folks Finance 33443 - [Smart Contract - Low] StalenessCircuitBreakerNode checks if the last update time of the parent node is less than the threshold but the publicTime could be greater than current blocktimestamp
Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
StalenessCircuitBreakerNode checks if the last update time of the parent node is less than the threshold but the publicTime could be greater than current block.timestamp .
PythNode::Process() calls pyth.getEmaPriceUnsafe() and pyth.getPriceUnsafe() for fetching price.
Issue is In StalenessCircuitBreakerNodestalenessToleranceis conceived as the maximum number of seconds that the price can be in the past(compared to block.timestamp) but in reality the price could also be in future
Vulnerability Details
This fact is corroborated by the logic inside Pyth SDK that performs an abs delta between the price.publishTime in [getPriceNoOlderThan](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/sdk/solidity/AbstractPyth.sol#L48-L58). In the the check is even more explicit
Let's analyse getPriceUnsafe()
pub fn get_price_unsafe(&self, price_identifier: PriceIdentifier) -> Option<Price> {
self.get_price_no_older_than(price_identifier, u64::MAX)
}
/// Get the latest available price cached for the given price identifier, if that price is
/// no older than the given age.
pub fn get_price_no_older_than(
&self,
price_id: PriceIdentifier,
age: Seconds,
) -> Option<Price> {
self.prices.get(&price_id).and_then(|feed| {
let block_timestamp = env::block_timestamp() / 1_000_000_000;
let price_timestamp = feed.price.publish_time;
// - If Price older than STALENESS_THRESHOLD, set status to Unknown.
// - If Price newer than now by more than STALENESS_THRESHOLD, set status to Unknown.
// - Any other price around the current time is considered valid.
if u64::abs_diff(block_timestamp, price_timestamp.try_into().unwrap()) > age {
return None;
}
Some(feed.price)
})
}
we can see that absolute difference is taken betweenprice.publishtime and age which shows that price.publishtime could be greater than block.timestamp but during staleness check stalenessTolerance is used for only previous prices
Impact Details
price.publishtime could be greater than block.timestamp. In such case fetching price will revert due to underflow since block.timestamp < price.publishtime