Price oracle manipulation describes any situation where a smart contract relies on price or valuation data that can be directly or indirectly influenced by an attacker, causing the protocol to make decisions based on incorrect values. Oracles are trust boundaries: the contract implicitly trusts that the price it receives reflects real-world or on-chain market conditions. When that trust is violated—whether by manipulation, staleness, or misconfiguration—protocol behavior is distorted.
This affects all contract types that consume price data: DeFi lending and borrowing (collateral valuation, liquidation), AMMs and DEXes (spot and TWAP-based pricing), yield vaults (NAV calculations, share valuation), liquid staking and derivatives (ETH/stake price feeds), NFT and token valuations (floor price oracles), and cross-chain bridges (asset pricing for mint/burn ratios). On non-EVM chains (e.g., Move, Solana), similar patterns apply wherever external price sources feed into on-chain logic.
Few areas to focus on:
Attackers exploit:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IPriceFeed {
function latestAnswer() external view returns (int256);
}
contract VulnerableOracleLending {
IPriceFeed public priceFeed; // single-point oracle
mapping(address => uint256) public collateralEth;
mapping(address => uint256) public debtUsd;
constructor(IPriceFeed _feed) {
priceFeed = _feed;
}
function depositCollateral() external payable {
collateralEth[msg.sender] += msg.value;
}
function borrow(uint256 amountUsd) external {
int256 price = priceFeed.latestAnswer(); // no sanity checks, no delay
require(price > 0, "bad price");
uint256 collateralUsd = (collateralEth[msg.sender] * uint256(price)) / 1e8;
// Allows borrowing up to 100% of collateral value – overly generous
require(collateralUsd >= amountUsd, "insufficient collateral");
debtUsd[msg.sender] += amountUsd;
// transfer stablecoin (omitted)
}
}
Issues:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IAggregatorV3 {
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
contract RobustOracleLending {
IAggregatorV3 public immutable priceFeed;
mapping(address => uint256) public collateralEth;
mapping(address => uint256) public debtUsd;
uint256 public constant MAX_DELAY = 1 hours;
uint256 public constant COLLATERAL_FACTOR_BPS = 7500; // 75%
constructor(IAggregatorV3 _feed) {
priceFeed = _feed;
}
function _getSafePrice() internal view returns (uint256) {
(, int256 answer, , uint256 updatedAt, uint80 answeredInRound) =
priceFeed.latestRoundData();
require(answer > 0, "bad answer");
require(updatedAt != 0 && block.timestamp - updatedAt <= MAX_DELAY, "stale price");
require(answeredInRound != 0, "incomplete round");
return uint256(answer);
}
function depositCollateral() external payable {
require(msg.value > 0, "no collateral");
collateralEth[msg.sender] += msg.value;
}
function borrow(uint256 amountUsd) external {
uint256 price = _getSafePrice();
uint256 collateralUsd = (collateralEth[msg.sender] * price) / 1e8;
uint256 maxBorrow = (collateralUsd * COLLATERAL_FACTOR_BPS) / 10_000;
require(debtUsd[msg.sender] + amountUsd <= maxBorrow, "exceeds limit");
debtUsd[msg.sender] += amountUsd;
// transfer stablecoin (omitted)
}
}
Security Improvements:
_getSafePrice, making reasoning and testing easier.In 2025, pure oracle-only mega-exploits were less frequent, but oracle manipulation was often one component in multi-vector attacks.
getPrice() function relied solely on DEX pair (Uniswap V2/PancakeSwap) reserve balances to calculate token price. Attackers used a flash loan to swap large amounts and manipulate reserves, skewing the oracle to show artificially low values, then bypassed purchase limits and cooldown protections to drain ~$2M. Oracle manipulation was the root cause.
executeDecreaseOrder, the attack flow involved price feed manipulation in conjunction: the attacker manipulated global average short price for Bitcoin downward (~57×), then used a flash loan to purchase GLP at artificially low prices and redeem at inflated prices. Oracle/pricing was a key enabler of the exploit.