circle-info
This is the first version of our Documentation, it will be improved and extended soon.
Page cover

Handle Stale Data

Stale oracle data is one of the most common risks in DeFi protocols. Even with reliable aggregation, network delays, source outages, or low deviation can cause prices to go unstale. Always implement staleness checks in your contracts to protect users.

Why Stale Data Matters

If a price hasn't updated recently:

  • It may no longer reflect market reality.

  • Pegged stablecoins could have de-pegged without detection.

  • Liquidations or borrowings could execute at unfair rates.

Implementing a Staleness Check

Use the lastUpdateTime returned by getAssetInfo to enforce a maximum age.

uint256 public constant MAX_PRICE_AGE = 3600; // 1 hour — adjust per asset risk

function _getFreshPrice(bytes32 assetId) internal view returns (int256 price, int8 decimal) {
    (IIfaPriceFeed.PriceFeed memory info, bool exists) = oracle.getAssetInfo(assetId);
    
    require(exists, "Asset not supported");
    require(block.timestamp - info.lastUpdateTime <= MAX_PRICE_AGE, "Oracle price stale");
    
    return (info.price, info.decimal);
}

Tunable Parameters:

  • Stablecoins near peg: 2–4 hours often safe.

  • Higher-risk assets: 30–60 minutes.

  • Critical protocols (e.g., lending): <30 minutes.

Combining with Deviation Checks (Circuit Breaker)

For extra safety, pair staleness with a reasonableness check.

Best Practices

  • Fail Closed → Revert or pause operations on stale data, not proceed with potentially bad prices.

  • Per-Asset Thresholds → Use a mapping for different max ages per asset.

  • Monitoring → Emit events on failed checks for offchain alerts.

  • Fallbacks → In advanced setups, switch to a secondary oracle if primary is stale.

By handling stale data proactively, you make your protocol significantly more resilient.

Next: Discover Working with Asset IDs for reliable feed identification.

Last updated

Was this helpful?