Skip to main content
Sigvex

Price Deviation Exploit Generator

Sigvex exploit generator that validates price deviation vulnerabilities by submitting extreme price updates (10x increase, 90% crash) and confirming whether the contract accepts them without bounds checking.

Price Deviation Exploit Generator

Overview

The price deviation exploit generator validates findings from the price_deviation, oracle_price_bounds, and related detectors by submitting four price updates — normal ($2000), a 10x increase ($20,000), a 90% crash ($200), and a reasonable 5% increase ($2100) — and confirming whether the contract accepts extreme changes without bounds checking. Contracts that process a 900% single-block price increase are confirmed vulnerable.

Unbounded price acceptance enables flash-loan price manipulation attacks. An attacker uses a flash loan to move an on-chain spot price by an extreme amount within a single transaction, exploits the contract at the manipulated price, and repays the loan — all atomically. Mango Markets lost $116M (October 2022) when an attacker manipulated the MNGO token price from $0.038 to $0.91 (2,300% increase) using a self-funding scheme, then borrowed against the inflated collateral. Venus Protocol lost $100M+ from a similar BNB price manipulation. Both protocols lacked deviation checks that would have rejected the extreme price as implausible.

Note: Exploit generation in Sigvex is for vulnerability validation purposes only.

Attack Scenario

Flash loan price manipulation:

  1. Attacker takes a large flash loan of ETH.
  2. Attacker buys a large amount of the target token on a DEX, moving the spot price from $2000 to $20,000 (10x).
  3. If the protocol uses spot price directly, the attacker’s collateral is now worth 10x.
  4. Attacker borrows the maximum amount against the inflated collateral.
  5. Attacker sells the token, restoring the price to $2000.
  6. Attacker repays the flash loan; the borrowed funds are profit.

Crash exploitation:

  1. An attacker or market event drops the price from $2000 to $200 (90% crash).
  2. Contracts that accept this without circuit breakers trigger mass liquidations.
  3. Liquidators receive bonus collateral at the artifically depressed price.
  4. If the crash is manipulation, the attacker profits from liquidation bonuses.

Exploit Mechanics

The generator executes four scenarios using a simulated oracle with price stored in slot 0. The fallback selector 0x8d6cc56d (updatePrice) is used when no specific selector is available from the finding location.

Scenario Price value Change Expected behavior Confirmed if
1 — Normal 200000000000 ($2000) Baseline Executes successfully Baseline
2 — 10x increase 2000000000000 ($20,000) +900% Should revert Succeeds (0.85 confidence)
3 — 90% crash 20000000000 ($200) -90% Should revert Succeeds (0.85 confidence)
4 — Reasonable 5% 210000000000 ($2100) +5% Should execute Baseline validation

Verdict:

  • Normal succeeds and 10x increase succeeds → extreme price increase accepted (confidence 0.85): no upper deviation bound.
  • Normal succeeds and 90% crash succeeds → extreme price crash accepted (confidence 0.85): no lower deviation bound.
  • Reasonable 5% succeeds but extremes revert → protected: deviation check in place.
// VULNERABLE: No bounds on accepted price
contract VulnerableAmm {
    uint256 public lastPrice;

    function updatePrice(uint256 newPrice) external onlyOracle {
        lastPrice = newPrice; // Accepts 10x or 0.1x price with no validation
        emit PriceUpdated(newPrice);
    }

    function getCollateralValue(uint256 amount) external view returns (uint256) {
        return amount * lastPrice / 1e8;
    }
}

// SECURE: Deviation check prevents manipulation
contract SafeAmm {
    uint256 public lastPrice;
    uint256 constant MAX_DEVIATION_BPS = 1000; // 10% max per update

    function updatePrice(uint256 newPrice) external onlyOracle {
        if (lastPrice != 0) {
            uint256 deviation = newPrice > lastPrice
                ? (newPrice - lastPrice) * 10000 / lastPrice
                : (lastPrice - newPrice) * 10000 / lastPrice;
            require(deviation <= MAX_DEVIATION_BPS, "Price deviation too large");
        }
        lastPrice = newPrice;
        emit PriceUpdated(newPrice);
    }
}

Remediation

Implement circuit breakers and deviation bounds at multiple levels:

// 1. Per-update deviation check
uint256 constant MAX_SINGLE_UPDATE_BPS = 500; // 5% per update

// 2. Time-weighted average prevents single-block manipulation
// Use a concentrated-liquidity AMM TWAP with a minimum observation window
uint256 constant MIN_TWAP_PERIOD = 1800; // 30 minutes
uint256 twapPrice = uniswapPool.observe(MIN_TWAP_PERIOD);

// 3. Absolute bounds for the asset class
uint256 constant ETH_MIN_PRICE = 100e8;      // $100 minimum
uint256 constant ETH_MAX_PRICE = 100_000e8;  // $100,000 maximum

// 4. Circuit breaker: pause on extreme deviation from TWAP
function validatePrice(uint256 spotPrice) internal view {
    uint256 twap = getTwapPrice();
    uint256 deviation = abs(spotPrice - twap) * 10000 / twap;
    if (deviation > CIRCUIT_BREAKER_BPS) {
        _pauseProtocol();
        revert("Price deviation triggered circuit breaker");
    }
}

// 5. Use TWAP instead of spot price for all lending decisions
// Spot price for display; TWAP for collateral calculations

For protocols that cannot avoid spot price use (e.g., AMMs), enforce minimum liquidity requirements: manipulating a deep pool requires far more capital, making attacks uneconomical.

References