Skip to content

implement per-asset heartbeats to prevent out stale price exposure #3

Description

@abiiralbhattarai

Security Issue: Missing Asset-Level Heartbeats in Price Updates

Summary

The current PriceFeedReceiver implementation does not track the time associated with each price update. Without an individual heartbeat (timestamp) for every asset, the oracle is vulnerable to accepting data that has been delayed or sent out of its original sequence.

Risks to Downstream Protocols

Contracts that rely on this price feed are exposed to critical risks because they cannot see when a price was generated:

  1. Stale Data Consumption: Without a heartbeat, a contract might use a price that is hours old because it has no way to check the time of the last update.
  2. Delayed Overwrites: If an update from 10:00 AM arrives after an update from 10:05 AM, the contract will blindly accept the 10:00 AM data, effectively "reverting" the price to a past state.
  3. Inability to Implement Safety Guards: Consuming protocols cannot implement logic such as if (currentTime - priceTime > 3600) revert() because the oracle does not expose the time of the update.

Proposed Security Fix: Individual Asset Heartbeats

To resolve this vulnerability, the storage structure is transitioned to a PriceData struct that pairs each price with a unique heartbeat (Unix timestamp).

1. Storage Structure

struct PriceData {
    uint256 price;
    uint256 lastUpdated;
}

mapping(string => PriceData) public prices;

2. Update Logic

if (incomingTimestamp > prices[name].lastUpdated) {
    prices[name] = PriceData({
        price: pricesArray[i],
        lastUpdated: incomingTimestamp
    });
}

Benefits of this Fix

  • Time Integrity: Guarantees that the oracle state can only move forward, preventing older, delayed data from overwriting newer entries.
  • Downstream Transparency: Other contracts can now query the heartbeat to decide if a price is too old for their specific use case.
  • Independent Asset Tracking: Each asset's time is tracked separately, so a delay in one token's feed does not impact the timing of others in the same batch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions