Oracle Manipulation

Oracle Manipulation


Price oracle manipulation is a critical vulnerability in DeFi protocols that rely on external price data for critical operations.


What are Oracles?


Oracles provide off-chain data to smart contracts. Price oracles are especially critical for:

- Lending protocols (collateralization ratios)

- DEXs (price discovery)

- Derivatives (settlement prices)

- Liquidation mechanisms


Manipulation Risks


Flash Loan Price Manipulation


Attackers can:

1. Take a flash loan

2. Manipulate the price on a DEX

3. Use the manipulated price in your protocol

4. Profit from the difference

5. Repay the flash loan


Example Vulnerable Code


// Vulnerable: Using spot price from single DEX
function getPrice() public view returns (uint) {
    return uniswapPair.getReserves(); // Can be manipulated in single tx
}

Secure Oracle Patterns


1. Chainlink Price Feeds


import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract SecureOracle {
    AggregatorV3Interface internal priceFeed;
    
    constructor() {
        priceFeed = AggregatorV3Interface(
            0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 // ETH/USD
        );
    }
    
    function getLatestPrice() public view returns (int) {
        (
            uint80 roundID,
            int price,
            uint startedAt,
            uint timeStamp,
            uint80 answeredInRound
        ) = priceFeed.latestRoundData();
        
        require(timeStamp > 0, "Round not complete");
        require(answeredInRound >= roundID, "Stale price");
        
        return price;
    }
}

2. Time-Weighted Average Price (TWAP)


// Using Uniswap V3 TWAP
function getTWAP(uint32 twapInterval) public view returns (uint) {
    uint32[] memory secondsAgos = new uint32[](2);
    secondsAgos[0] = twapInterval;
    secondsAgos[1] = 0;
    
    (int56[] memory tickCumulatives, ) = pool.observe(secondsAgos);
    
    int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];
    int24 arithmeticMeanTick = int24(tickCumulativesDelta / int56(uint56(twapInterval)));
    
    return getQuoteAtTick(arithmeticMeanTick, amountIn, baseToken, quoteToken);
}

3. Multiple Oracle Sources


function getPrice() public view returns (uint) {
    uint chainlinkPrice = getChainlinkPrice();
    uint uniswapTWAP = getUniswapTWAP();
    uint bandPrice = getBandPrice();
    
    // Use median or require consistency
    require(
        abs(chainlinkPrice - uniswapTWAP) < chainlinkPrice / 20,
        "Price deviation too high"
    );
    
    return (chainlinkPrice + uniswapTWAP) / 2;
}

Best Practices


1. Never use spot prices from a single DEX for critical operations

2. Use established oracle solutions (Chainlink, Band Protocol)

3. Implement TWAP for DEX-based prices

4. Use multiple oracle sources and verify consistency

5. Add circuit breakers for abnormal price movements

6. Implement price deviation checks

7. Add time delays for large operations


Circuit Breaker Implementation


uint public constant MAX_PRICE_CHANGE = 10; // 10% max change

function checkPrice(uint newPrice, uint oldPrice) internal pure {
    uint percentChange = abs(newPrice - oldPrice) * 100 / oldPrice;
    require(percentChange <= MAX_PRICE_CHANGE, "Price change too large");
}

Real-World Examples


- **Harvest Finance** (~$34M): Flash loan attack manipulating Curve pool prices

- **Cream Finance** (~$130M): Price oracle manipulation

- **Venus Protocol** (~$11M): Oracle price manipulation


References


- [Chainlink Documentation](https://docs.chain.link/)

- [Uniswap V3 Oracle](https://docs.uniswap.org/concepts/protocol/oracle)

Need Professional Security Audit?

Our experts can help secure your smart contracts

Get Audit Quote