StrataxOracle is a thin wrapper around Chainlink's AggregatorV3Interface. Its getPrice(), getPriceDecimals(), and getRoundData() functions each make external calls to the configured Chainlink price feed without any try/catch error handling or fallback mechanism.
The getPrice() function calls priceFeed.latestRoundData(), and if that external call reverts for any reason, the revert propagates unconditionally to all callers:
The same pattern exists in getPriceDecimals() (calling priceFeed.decimals()) and getRoundData() (calling priceFeed.latestRoundData()). None of these functions implement try/catch, cached fallback values, or alternative feed sources.
The critical impact is on position unwinding. When a user calls unwindPosition(), the flow proceeds as follows:
unwindPosition() calls aavePool.flashLoanSimple().
Aave calls back executeOperation().
executeOperation() routes to _executeUnwindOperation().
_executeUnwindOperation() calls IStrataxOracle(strataxOracle).getPrice() for both the debt token and collateral token with no try/catch and no bypass:
If either getPrice() call reverts, the entire flash loan callback reverts, causing the flash loan to fail and blocking the unwind operation entirely. Since the Stratax contract holds the Aave position (collateral and debt belong to address(this)), users cannot directly interact with Aave to unwind their positions and are fully dependent on the Stratax contract's unwindPosition() flow.
The view helper calculateUnwindParams() is similarly affected, as it also calls getPrice() for both the borrow and collateral tokens. The view helper calculateOpenParams() calls getPrice() only when token prices are passed as zero, but createLeveragedPosition() itself does not call the oracle and can still be invoked with externally-calculated parameters, so position opening is not blocked.
The protocol has no fallback mechanism: no cached prices, no alternative feeds, and no circuit breaker that allows emergency operations. The only mitigation is for the owner to manually call setPriceFeed() to point to a working alternative feed, which requires the owner to be online and responsive, and for a working alternative feed to exist.
Chainlink feed outages are documented real-world events. During the Arbitrum sequencer outage in June 2023, Chainlink feeds on Arbitrum were returning stale data or reverting, causing DeFi protocols without fallback mechanisms to experience disruptions. The LUNA crash in May 2022 similarly caused Chainlink's LUNA/USD feed to become unreliable, blocking protocols that had no fallback mechanism.
This issue has a medium impact as users with active leveraged positions genuinely cannot unwind through the protocol during an oracle outage, potentially leading to Aave liquidation losses if the market moves against them. However, the impact is bounded because Aave liquidations still function independently, and the owner can update the price feed address to a working feed.
This issue has a low likelihood as Chainlink feed outages are rare on mainnet Ethereum but more common on L2s during sequencer downtime. Feed deprecation is announced in advance. The scenario requires a specific Chainlink infrastructure failure, which is an external dependency outside the protocol's control.
Implement a fallback mechanism in StrataxOracle for handling Chainlink feed failures. Wrap the latestRoundData() call in a try/catch block and maintain a cached price storage that records the last known good price and timestamp for each token. On success, update the cached price. On failure, return the cached price if it is within an acceptable staleness threshold, or revert with a more descriptive error if the cached price is too stale. Note that getPrice() must be changed from a view function to a non-view function to support writing cached values to storage.
Additionally, add a staleness check on the updatedAt value returned from latestRoundData() to detect feeds that return stale data without reverting. Implementing a secondary oracle feed (such as a Uniswap TWAP oracle) as a fallback when the primary Chainlink feed is unavailable would further improve resilience.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.