Stale Price Usage
id: LS15H
title: Stale Price Usage
baseSeverity: H
category: oracle-manipulation
language: solidity
blockchain: [ethereum]
impact: Attackers exploit outdated prices to manipulate trades, minting, or liquidations
status: draft
complexity: medium
attack_vector: oracle
mitigation_difficulty: medium
versions: [">=0.6.0", "<latest"]
cwe: CWE-200
swc: SWC-119
π Description
- Stale Price Usage occurs when smart contracts use price data from an oracle or feed without validating its freshness or update timestamp.
- This allows attackers to exploit outdated rates that no longer reflect the current market, enabling:
- Underpriced minting,
- Overpriced liquidations,
- Improper collateralization or redemption, or
- Arbitrage against real-time prices.
- The vulnerability is common in DeFi protocols that rely on Chainlink, TWAPs, or custom oracles but fail to verify the age of the price.
π¨ Vulnerable Code
interface IOracle {
function getPrice() external view returns (uint256 price, uint256 lastUpdated);
}
contract StalePriceVulnerable {
IOracle public priceFeed;
function buy() external payable {
(uint256 price, ) = priceFeed.getPrice();
require(msg.value >= price, "Insufficient payment");
// Mint token, redeem, etc.
}
}
π§ͺ Exploit Scenario
Step-by-step exploit process:
- Oracleβs getPrice() returns ETH = $2000 with lastUpdated from 1 hour ago.
- Market price drops to $1500.
- Contract does not check lastUpdated, so stale $2000 price is accepted.
- Attacker mints tokens or executes trades based on the overvalued ETH rate.
- Profit is realized at the cost of the protocol or liquidity pool.
Assumptions:
- Oracle updates are infrequent or externally triggered.
- Contract uses price without validating lastUpdated.
β Fixed Code
uint256 public constant MAX_DELAY = 60; // 60 seconds
function buy() external payable {
(uint256 price, uint256 lastUpdated) = priceFeed.getPrice();
require(block.timestamp - lastUpdated <= MAX_DELAY, "Stale price");
require(msg.value >= price, "Insufficient payment");
// Safe to proceed
}
π§ Contextual Severity
- context: "Default"
severity: H
reasoning: "Without freshness checks, oracles can drift and enable economic exploits."
- context: "High-volume lending protocol with volatile assets"
severity: C
reasoning: "Stale prices can be leveraged to drain reserves or trigger mass liquidations."
- context: "Private vault with manual price update controls"
severity: M
reasoning: "Limited reach; exposure depends on update cadence and access control."
π‘οΈ Prevention
Primary Defenses
- Always validate price freshness using the oracle's updatedAt timestamp.
- Define a maximum allowed delay (e.g., MAX_DELAY = 60 seconds).
- Use trusted oracles like Chainlink, which expose round and timestamp data.
Additional Safeguards
- Integrate heartbeat monitoring to pause the protocol if oracle feeds stop updating.
- Combine multiple oracles for cross-verification and fallback.
- Monitor for sudden deltas between on-chain price and TWAP/real-time values.
Detection Methods
- Slither: oracle-no-timestamp-check, stale-price-read, unchecked-oracle-usage detectors.
- Manual audit of any function that calls getPrice(), latestRoundData(), or similar, ensuring timestamp validation is present.
- Simulation testing with delayed oracle updates.
π°οΈ Historical Exploits
- Name: Term Finance Oracle Exploit
- Date: April 2025
- Loss: Approximately $1.5 million
- Post-mortem: Link to post-morte
π Further Reading
- SWC-119: Unchecked Return Values for Oracle Data
- Stale Prices β Zokyo Auditing Tutorials
- SC02:2025 Price Oracle Manipulation β OWASP Smart Contract Security
β Vulnerability Report
id: LS15H
title: Stale Price Usage
severity: H
score:
impact: 5
exploitability: 4
reachability: 4
complexity: 3
detectability: 4
finalScore: 4.3
π Justifications & Analysis
- Impact: Enables minting, redeeming, or trading against mispriced assets.
- Exploitability: Occurs when attackers observe oracle delay.
- Reachability: Present across DeFi protocols with any price dependency.
- Complexity: Moderate β attacker needs oracle insight and fast execution.
- Detectability: High β easily flagged with timestamp comparison.