Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

Keeper Price Verification Lacks Deviation Checks in StabilityBranch.sol::fulfillSwap

Summary

The fulfillSwap function verifies keeper-provided off‑chain price data using verifyOffchainPrice(), but it does not validate that the reported price falls within an expected deviation range compared to prior swaps or trusted price feeds. Without deviation checks, the system may accept extreme price changes within a single transaction, potentially leading to price manipulation attacks or acceptance of stale prices, exposing the protocol to economic risks.

Vulnerability Details

The current implementation obtains the price as follows:

function fulfillSwap(...) external {
// ...
// Price verification lacks deviation checks
ctx.priceX18 = stabilityConfiguration.verifyOffchainPrice(priceData);
ctx.amountOutBeforeFeesX18 = getAmountOfAssetOut(
ctx.vaultId,
ud60x18(ctx.amountIn),
ctx.priceX18
);
// ...
}

Impact

  • Price Manipulation: Malicious or compromised keepers might supply a price with a drastic deviation, leading to unfair swap rates and potential asset loss.

  • Acceptance of Stale Prices: In scenarios of network delay or flash crashes, stale prices might be used, exposing users to unexpected slippage.

  • Economic Exploits: An attacker could benefit from intentionally triggering abnormal price movements within a single transaction, resulting in arbitrage opportunities or draining vault liquidity.

Tools Used

  • Manual Code Review: Inspection of the price verification process in the fulfillSwap function.

  • Static Analysis: Tools like Slither and MythX identified the absence of deviation checks.

  • Fuzz Testing: Input variations simulated with frameworks like Forge demonstrated potential for abnormal price inputs.

Recommendations

  • Implement Deviation Checks: Introduce logic to verify that the keeper-provided price does not vary beyond an acceptable range (e.g., a percentage spike) compared to a recent reference price or an oracle-based average.

    For example:

    uint256 allowedDeviationBps = 200; // Example: 2% deviation allowed.
    uint256 referencePrice = getReferencePrice(); // Retrieve trusted, recent price.
    uint256 lowerBound = referencePrice.mul(BPS_DENOMINATOR.sub(allowedDeviationBps)).div(BPS_DENOMINATOR);
    uint256 upperBound = referencePrice.mul(BPS_DENOMINATOR.add(allowedDeviationBps)).div(BPS_DENOMINATOR);
    if (priceX18 < lowerBound || priceX18 > upperBound) {
    revert Errors.PriceDeviationTooHigh(priceX18, referencePrice);
    }
  • Integrate Additional Oracles: Use multiple price feeds or a moving average to better understand normal market deviations.

  • Reporting and Alerts: Implement monitoring to alert if price deviations occur frequently, suggesting potential manipulation or network issues.

  • Rigorous Testing: Simulate abnormal price scenarios to ensure that the deviation check works as intended without impairing legitimate swap activity.

Updates

Lead Judging Commences

inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!