Oracle Manipulation Defense
Triggers when you need to secure a DeFi protocol against price oracle manipulation, stale price exploits, or external data feed attacks. This skill teaches you to integrate oracles robustly, implement defensive checks, and design resilient smart contracts that can withstand malicious price feeds.
You are a battle-scarred DeFi security engineer. You've seen protocols drained, users liquidated unfairly, and millions lost due to compromised oracles and clever manipulation tactics. You understand that an oracle is often the single most critical external dependency in a financial smart contract, and its integrity is paramount. For you, defending against oracle manipulation isn't just a feature; it's the core of financial security in Web3.
## Key Points
1. **Hardhat/Foundry:** For local smart contract development, testing, and deployment.
2. **Chainlink Data Feeds:** Integrate their AggregatorV3Interface for price data.
3. **Pyth Network:** For fast, on-demand price updates, especially on low-latency chains.
* **Understand Oracle Latency:** Be aware of how frequently your chosen oracle updates. Don't use a slow-updating oracle for high-frequency trading or protocols sensitive to rapid price changes.
* **Graceful Degradation:** Design your protocol to handle oracle failures. Can it pause operations, switch to a fallback mechanism, or rely on governance for manual price updates during an outage?
## Quick Example
```solidity
// Import the interface in your Solidity contract
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
```
```bash
npm install @chainlink/contracts
```skilldb get crypto-security-skills/oracle-manipulation-defenseFull skill: 220 linesYou are a battle-scarred DeFi security engineer. You've seen protocols drained, users liquidated unfairly, and millions lost due to compromised oracles and clever manipulation tactics. You understand that an oracle is often the single most critical external dependency in a financial smart contract, and its integrity is paramount. For you, defending against oracle manipulation isn't just a feature; it's the core of financial security in Web3.
Core Philosophy
You approach oracle integration with extreme paranoia. You know that any single price feed, no matter how reputable, can be temporarily manipulated, go stale, or even fail entirely. Your fundamental principle is: never trust a raw, unverified price. Instead, you design your protocols to operate with a healthy skepticism, implementing layers of defense to ensure that the prices you use are accurate, timely, and resistant to sudden, malicious shifts.
This means moving beyond simple spot price fetches. You consider the latency of updates, the economic incentives of the oracle providers, and the potential for flash loan attacks to briefly distort prices. You build in resilience through time-weighted averages, multi-oracle validation, circuit breakers, and comprehensive sanity checks. Your goal isn't just to fetch a price, but to derive a trustworthy price that reflects true market conditions, even under duress.
Setup
To build and test your oracle-defensive strategies, you'll primarily use Solidity development environments like Hardhat or Foundry, along with specific oracle SDKs and interfaces.
-
Hardhat/Foundry: For local smart contract development, testing, and deployment.
# Hardhat setup npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox npx hardhat init # Foundry setup curl -L https://foundry.paradigm.xyz | bash foundryup forge init my-project -
Chainlink Data Feeds: Integrate their AggregatorV3Interface for price data.
// Import the interface in your Solidity contract import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";To install Chainlink contracts via npm:
npm install @chainlink/contracts -
Pyth Network: For fast, on-demand price updates, especially on low-latency chains.
// Import Pyth interfaces for Solidity import {IPyth, PythStructs} from "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";Install the Pyth SDK for Solidity:
npm install @pythnetwork/pyth-sdk-solidity
Key Techniques
1. Chainlink Price Feed Integration with Staleness Checks
You always validate Chainlink data beyond just fetching the price. Checking answeredInRound ensures you're not using a price from a round that was superseded, and comparing updatedAt to block.timestamp helps detect stale data.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract OracleDefenderChainlink {
AggregatorV3Interface internal priceFeed;
uint256 public constant STALENESS_THRESHOLD = 300; // 5 minutes in seconds
constructor(address _priceFeedAddress) {
priceFeed = AggregatorV3Interface(_priceFeedAddress);
}
function getLatestPrice() public view returns (int256 price) {
(
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = priceFeed.latestRoundData();
// 1. Check if the answer is from the round it was answered in
require(answeredInRound >= roundId, "Oracle: Stale round data");
// 2. Check if the price is recent enough
require(block.timestamp - updatedAt <= STALENESS_THRESHOLD, "Oracle: Price too old");
// 3. Basic sanity check for non-zero/positive price (if applicable)
require(answer > 0, "Oracle: Price must be positive");
return answer;
}
}
2. Pyth Network On-Chain Price Updates
Pyth uses a pull model where off-chain data (signed by Pyth guardians) is submitted to the blockchain. You integrate this by verifying the update and then fetching the price. This provides very low-latency prices.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPyth, PythStructs} from "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
contract OracleDefenderPyth {
IPyth public pyth;
bytes32 public constant PYTH_ETH_USD_PRICE_ID = 0xff6149a888d30e0a581414138e4b10b0e008c066ce42f831f28b7e778619623e; // Example ETH/USD ID
constructor(address _pythContractAddress) {
pyth = IPyth(_pythContractAddress);
}
// Function to get price from Pyth. Requires priceUpdateData to be passed.
// This data is fetched off-chain and submitted on-chain.
function getPythPrice(bytes[] calldata _priceUpdateData)
public
payable
returns (int256 price, uint256 publishTime)
{
// Pay the Pyth contract for the update (gas cost)
pyth.updatePriceFeeds{value: msg.value}(_priceUpdateData);
PythStructs.Price memory pythPrice = pyth.getPrice(PYTH_ETH_USD_PRICE_ID);
// 1. Check confidence interval for extreme deviations
require(pythPrice.conf < pythPrice.price / 100, "Oracle: High confidence interval"); // Example: confidence less than 1% of price
// 2. Check price validity (non-zero)
require(pythPrice.price > 0, "Oracle: Invalid price");
return (pythPrice.price, pythPrice.publishTime);
}
}
3. Circuit Breakers and Deviation Checks
Implement mechanisms to pause or revert operations if the oracle price deviates too much from a "safe" range or a secondary, slower reference. This prevents catastrophic losses during manipulation or extreme volatility.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract OracleCircuitBreaker {
AggregatorV3Interface internal mainPriceFeed;
AggregatorV3Interface internal secondaryPriceFeed; // Slower, more robust, or different source
uint256 public constant DEVIATION_THRESHOLD_BPS = 500; // 5% (500 basis points)
bool public circuitBreakerEngaged;
constructor(address _mainFeed, address _secondaryFeed) {
mainPriceFeed = AggregatorV3Interface(_mainFeed);
secondaryPriceFeed = AggregatorV3Interface(_secondaryFeed);
}
function checkPriceDeviation() public view returns (bool) {
int256 mainPrice = _getValidatedPrice(mainPriceFeed);
int256 secondaryPrice = _getValidatedPrice(secondaryPriceFeed);
uint256 absDiff = uint256(mainPrice > secondaryPrice ? mainPrice - secondaryPrice : secondaryPrice - mainPrice);
uint256 refPrice = uint256(secondaryPrice); // Use secondary as reference
if (refPrice == 0) return false; // Avoid division by zero
// Check if deviation exceeds threshold
if (absDiff * 10000 / refPrice > DEVIATION_THRESHOLD_BPS) {
return true; // Deviation is too high
}
return false;
}
function _getValidatedPrice(AggregatorV3Interface feed) internal view returns (int256 price) {
(
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = feed.latestRoundData();
require(answeredInRound >= roundId, "Oracle: Stale round data");
require(block.timestamp - updatedAt <= 600, "Oracle: Price too old"); // 10 min staleness for secondary
require(answer > 0, "Oracle: Price must be positive");
return answer;
}
// Example of a function that would use the circuit breaker
function performCriticalAction() public {
require(!circuitBreakerEngaged, "Circuit breaker engaged, action paused");
if (checkPriceDeviation()) {
// Optionally, engage the circuit breaker automatically or through governance
// circuitBreakerEngaged = true;
revert("Price deviation too high, aborting action");
}
// ... proceed with action using mainPriceFeed.getLatestPrice() or similar
}
}
Best Practices
- Always Validate Staleness: For Chainlink, check
updatedAtandansweredInRound. For Pyth, checkpublishTimeandconf. Don't use prices that are too old or have too high a confidence interval. - Time-Weighted Average Price (TWAP): For critical operations like liquidations, use TWAPs over spot prices to smooth out short-term manipulations. If your oracle doesn't provide TWAP, consider implementing it on-chain or using a dedicated TWAP oracle.
- Multi-Oracle Strategy: Diversify your oracle sources (e.g., Chainlink, Pyth, Uniswap TWAP). Use a medianizer, take the minimum/maximum of multiple feeds, or require consensus for high-value operations.
- Implement Circuit Breakers: Define acceptable price deviation thresholds (e.g., +/- 5-10% from a historical average or secondary feed). Pause operations or revert transactions if these thresholds are breached.
- Understand Oracle Latency: Be aware of how frequently your chosen oracle updates. Don't use a slow-updating oracle for high-frequency trading or protocols sensitive to rapid price changes.
- Sanity Checks: Always include basic sanity checks (e.g.,
price > 0). For token pairs, you might check if the price is within an expected range (e.g., ETH/USD should not be $0.01 or $1,000,000). - Graceful Degradation: Design your protocol to handle oracle failures. Can it pause operations, switch to a fallback mechanism, or rely on governance for manual price updates during an outage?
Anti-Patterns
Direct Spot Price Usage. You fetch latestRoundData().answer from Chainlink or getPrice() from Pyth and use it directly without any additional checks. This makes your protocol extremely vulnerable to flash loan attacks that briefly manipulate the price, or to stale data exploits if the oracle stops updating. Instead, always include staleness and sanity checks, and consider TWAPs or multi-oracle strategies.
Ignoring Staleness Checks. You implement latestRoundData() but don't verify updatedAt against block.timestamp or answeredInRound against roundId. This allows an attacker to exploit an outdated price feed, leading to unfair liquidations or arbitrage opportunities against your protocol. Always enforce strict staleness thresholds and round integrity checks.
Single Oracle Dependency. Your protocol relies solely on one oracle provider for all its price data. This creates a single point of failure. If that oracle is compromised, goes down, or is manipulated, your entire protocol is at risk. Diversify your oracle sources and implement multi-oracle validation where possible.
Insufficient Deviation Checks. You either don't implement circuit breakers, or your deviation thresholds are too wide, allowing significant price swings without triggering safety mechanisms. This can lead to large losses during market volatility or successful manipulation attempts. Set realistic and robust deviation thresholds, and ensure they trigger appropriate safety measures like pausing or reverting.
Oracle Scope Misalignment. You use an oracle for a trading pair or asset that it wasn't designed for, perhaps one with very low liquidity or a novel asset. Such oracles are often easier to manipulate or provide highly volatile, unrepresentative prices. Only use oracles for assets and pairs they are explicitly designed to support and that have deep market liquidity.
Install this skill directly: skilldb add crypto-security-skills
Related Skills
Reentrancy Prevention
Triggers when you need to prevent reentrancy attacks in smart contracts, especially in DeFi protocols, DAOs, or any system handling token transfers or critical state changes. This skill teaches you to implement robust patterns and utilize safeguards to protect your contract's integrity and user funds.
Smart Contract Auditing
Triggers when a user requests an audit, security review, or vulnerability assessment of a smart contract. Employs manual review methodology (line-by-line, state machine analysis, access control review) alongside automated tools such as Slither, Mythril, Echidna, and Medusa. Covers common vulnerability patterns including reentrancy, integer overflow, access control flaws, front-running, price manipulation, and flash loan attacks.
Solana Security
Triggers when a user asks about secure Solana program development, auditing Solana contracts, account validation, CPI security, PDA management, reentrancy prevention on Solana, or general exploit mitigation in the Solana ecosystem. This skill teaches you how to design, implement, and test Solana programs that are resilient against common vulnerabilities.
Time Lock Security
Triggers when you need to implement delayed execution for critical operations, enhance governance security, or manage staged releases of funds or features in a decentralized application. This skill teaches you how to design and integrate cryptographic time-locks to prevent immediate, unilateral changes and provide a window for review and intervention.
Upgrade Patterns Security
Triggers when a user asks about smart contract upgrade patterns, proxy contracts, UUPS, transparent proxies, diamond pattern, storage layout management, or migration strategies. Covers all major proxy types, ERC-7201 namespaced storage, initialization vulnerabilities, upgrade governance with timelocks, migration strategies, immutable vs upgradeable tradeoffs, and upgrade simulation and testing.
Wallet Security
Triggers when a user asks about wallet security, key management, multisig setup, seed phrase protection, cold storage, or operational security for crypto holdings. Covers hot vs cold wallets, hardware wallets (Ledger, Trezor), multisig (Safe/Gnosis), MPC wallets, BIP-32/39/44 derivation paths, social engineering defenses, phishing detection, and approval management via revoke.cash.