• YouTube Channel
  • System Status
  • VS Code Extension
  • Oracle Manipulation

    Overview

    What is Oracle Manipulation?

    Oracle manipulation occurs when a smart contract relies on price feeds or other external data without proper validation mechanisms. This vulnerability can allow attackers to manipulate contract behavior through price manipulation, stale data usage, or flash loan attacks on price sources.

    Why is Oracle Manipulation Dangerous?

    Oracle manipulation vulnerabilities can be extremely dangerous because:

    Technical Example of Vulnerable Code

    
    pragma solidity ^0.8.0;
    
    contract VulnerableOracleConsumer {
        AggregatorV3Interface public priceFeed;
        
        constructor(address _priceFeed) {
            priceFeed = AggregatorV3Interface(_priceFeed);
        }
        
        // VULNERABLE: No staleness check, no price validation
        function getPrice() external view returns (int) {
            (, int price,,,) = priceFeed.latestRoundData();
            return price;
        }
        
        // VULNERABLE: No access control, no validation
        function setPriceFeed(address _newPriceFeed) external {
            priceFeed = AggregatorV3Interface(_newPriceFeed);
        }
        
        // VULNERABLE: Direct price usage without checks
        function calculateValue(uint256 amount) external view returns (uint256) {
            (, int price,,,) = priceFeed.latestRoundData();
            return amount * uint256(price);
        }
    }
    
    

    In this example, the contract uses oracle data without any validation. It doesn't check for stale data, validate price values, or protect against manipulation. The price feed can also be changed by any address.

    Technical Example of Fixed Code

    
    pragma solidity ^0.8.0;
    
    contract SecureOracleConsumer {
        AggregatorV3Interface public priceFeed;
        uint256 public constant STALENESS_PERIOD = 1 hours;
        address public owner;
        
        modifier onlyOwner() {
            require(msg.sender == owner, "Not owner");
            _;
        }
        
        constructor(address _priceFeed) {
            priceFeed = AggregatorV3Interface(_priceFeed);
            owner = msg.sender;
        }
        
        function getValidatedPrice() public view returns (int) {
            (
                uint80 roundId,
                int price,
                ,
                uint256 updatedAt,
                uint80 answeredInRound
            ) = priceFeed.latestRoundData();
            
            // Freshness check
            require(block.timestamp - updatedAt <= STALENESS_PERIOD, "Stale price");
            
            // Round validation
            require(answeredInRound >= roundId, "Price rounds mismatch");
            
            // Sanity check
            require(price > 0, "Invalid price");
            
            return price;
        }
        
        function setPriceFeed(address _newPriceFeed) external onlyOwner {
            require(_newPriceFeed != address(0), "Invalid address");
            priceFeed = AggregatorV3Interface(_newPriceFeed);
        }
        
        function calculateValue(uint256 amount) external view returns (uint256) {
            int validatedPrice = getValidatedPrice();
            return amount * uint256(validatedPrice);
        }
    }
    
    

    The improved version includes comprehensive oracle validation: