Stratax Contracts

First Flight #57
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: medium
Likelihood: medium

Oracle Price Freshness / Validation Missing

Author Revealed upon completion

Root + Impact

Description

  • Normal behavior: Stratax relies on StrataxOracle to fetch token prices for calculating leverage, flash loan amounts, and unwind parameters. These prices are used to ensure the position remains healthy and that flash loans can be repaid.

  • Issue: The contract does not verify that the oracle price is fresh or valid beyond checking > 0. If the oracle feed is stale, frozen, or incorrectly set by the oracle owner, the calculated borrow or withdraw amounts may be inaccurate. This could lead to miscalculated positions, potentially undercollateralized or not reaching the desired leverage.

// Example in calculateOpenParams()
if (details.collateralTokenPrice == 0) {
require(strataxOracle != address(0), "Oracle not set");
details.collateralTokenPrice = IStrataxOracle(strataxOracle).getPrice(details.collateralToken); // @> relies entirely on oracle, no freshness check
}
require(details.collateralTokenPrice > 0, "Collateral token price must be > 0"); // @> only checks >0, no timestamp validation

Risk

Likelihood:

  • Only occurs if the Chainlink oracle feed stops updating or the oracle owner sets a wrong feed address.

  • Can happen during network downtime, oracle maintenance, or misconfiguration by oracle owner.

Impact:

  • Borrow and flash loan amounts may be miscalculated, leading to inefficient or unhealthy positions.

  • Could result in partial liquidation or failure to achieve intended leverage, though funds are protected by Aave’s internal health factor enforcement.

Proof of Concept

// Pseudo-PoC demonstrating stale oracle
// Assume USDC price is frozen at 1e8 (unchanged) for hours
TradeDetails memory td = TradeDetails({
collateralToken: usdc,
borrowToken: dai,
desiredLeverage: 30000, // 3x
collateralAmount: 1_000e6,
collateralTokenPrice: 0, // triggers fetch
borrowTokenPrice: 0, // triggers fetch
collateralTokenDec: 6,
borrowTokenDec: 18
});
(uint256 flashLoanAmt, uint256 borrowAmt) = str.calcOpenParams(td);
// flashLoanAmt and borrowAmt will be wrong because oracle price hasn't updated

The PoC shows that if the oracle price is not updated or frozen, the contract will calculate leverage and borrow amounts incorrectly. Even though the funds themselves are protected by Aave’s health factor checks, the operation may fail or lead to inefficient capital use, demonstrating the medium risk.

Recommended Mitigation

- details.collateralTokenPrice = IStrataxOracle(strataxOracle).getPrice(details.collateralToken);
+ (details.collateralTokenPrice, uint256 timestamp) = IStrataxOracle(strataxOracle).getPriceWithTimestamp(details.collateralToken);
+ require(details.collateralTokenPrice > 0 && block.timestamp - timestamp < 1 hours, "Stale or invalid price");

Adding a timestamp check ensures that the oracle price is recent and valid. This prevents miscalculations due to frozen or stale feeds. Using getPriceWithTimestamp (or similar) allows the contract to verify freshness, reducing the likelihood of miscomputed leverage or borrow amounts and making the position safer.

Support

FAQs

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

Give us feedback!