Oracle Liveness Drift
id: LS36H
title: Oracle Liveness Drift
baseSeverity: H
category: oracle
language: solidity
blockchain: [ethereum, arbitrum, optimism, avalanche, bsc]
impact: Price manipulation, arbitrage, or incorrect liquidation
status: draft
complexity: medium
attack_vector: external
mitigation_difficulty: medium
versions: [">=0.6.0", "<=0.8.25"]
cwe: CWE-200
swc: SWC-114
π Description
- Oracle liveness drift occurs when price data remains unchanged past its expected update interval, leading to stale, inaccurate, or manipulable price feeds. This is common in:
- Cross-chain oracle setups (e.g., Chainlink CCIP, LayerZero relays)
- Off-chain price push mechanisms (e.g., keepers, Pyth pull models)
- Custom oracles that lack on-chain freshness enforcement
- If contracts do not validate oracle timestamps or update frequency, they may:
- Execute trades at outdated prices
- Allow under-collateralized borrowing
- Trigger or skip liquidations
- Be exploited via multi-block arbitrage (e.g., flashloans)
π¨ Vulnerable Code
pragma solidity ^0.8.0;
interface Oracle {
function latestAnswer() external view returns (int256);
}
contract LivenessDriftVault {
Oracle public priceOracle;
function getPrice() public view returns (int256) {
return priceOracle.latestAnswer(); // β no check on staleness or timestamp
}
function liquidate(address user) external {
int256 price = getPrice();
// liquidate user if price is below threshold (logic omitted)
}
}
π§ͺ Exploit Scenario
- The oracle stops updating due to relayer downtime or RPC issues.
- The attacker borrows at full collateralization and dumps the collateral asset, knowing liquidation logic won't adjust.
- Alternatively, the attacker triggers forced liquidation using a stale high price, even though the real market value dropped.
- Cross-chain deployments (e.g., BSC β Ethereum) using async oracles have different price states across chains.
Assumptions:
- Oracle has drifted or paused without alert.
- Consumer contract doesn't validate freshness.
β Fixed Code
pragma solidity ^0.8.0;
interface TimestampedOracle {
function latestAnswer() external view returns (int256);
function latestTimestamp() external view returns (uint256);
}
contract SafeOracleVault {
TimestampedOracle public oracle;
uint256 public staleThreshold = 300; // 5 minutes
function getSafePrice() public view returns (int256) {
require(block.timestamp - oracle.latestTimestamp() <= staleThreshold, "Stale oracle");
return oracle.latestAnswer();
}
}
π§ Contextual Severity
- context: "Stablecoin protocol or lending platform"
severity: H
reasoning: "Delayed updates lead to real financial losses via mispriced actions"
- context: "Read-only dashboard or historical viewer"
severity: L
reasoning: "No financial consequences from stale display"
- context: "Oracle with bounded round liveness checks + freshness threshold"
severity: M
reasoning: "Partially mitigated, but still exploitable during drift windows"
π‘οΈ Prevention
Primary Defenses
- Enforce freshness checks on every oracle access
- Validate both answer and timestamp/roundId
Additional Safeguards
- Use fallback oracles (multi-feed model)
- Emit drift-related metrics to external monitoring systems
- Automatically pause protocol actions (e.g., liquidations, trading) on stale oracles
Detection Methods
- Review for oracle consumers that donβt use latestTimestamp(), latestRoundData(), or equivalent
- Tools: Manual audit, Slither custom rule, static analyzers
π°οΈ Historical Exploits
- Name: KiloEX Oracle Manipulation Exploit
- Date: 2025-04-16
- Loss: ~$7.5 million
- Post-mortem: Link to post-mortem
- Name: Drift Protocol Oracle Desynchronization Bug
- Date: 2022-05-11
- Loss: ~$11.75 million
- Post-mortem: Link to post-mortem
- Name: Radiant Capital Cross-Chain Oracle Drift Attack
- Date: 2024-10
- Loss: ~$58 million
- Post-mortem: Link to post-mortem
π Further Reading
- Chainlink Docs β LatestRoundData
- SWC-114: Transaction Ordering Dependence
- OpenZeppelin Defender β Oracle Monitoring
β Vulnerability Report
id: LS36H
title: Oracle Liveness Drift
severity: H
score:
impact: 5
exploitability: 3
reachability: 5
complexity: 2
detectability: 4
finalScore: 4.1
π Justifications & Analysis
- Impact: Critical price-based actions execute on outdated data, risking large losses
- Exploitability: Occurs during oracle downtime or relayer stalls
- Reachability: Widespread across lending, AMMs, derivatives
- Complexity: Simple β just wait for oracle to stall
- Detectability: Easily flagged by monitoring or testing for stale timestamps