Stratax Contracts

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

StrataxOracle Not Upgradeable — Misaligned With Stratax Upgrade Pattern

Author Revealed upon completion

Root + Impact

Location: src/StrataxOracle.sol:20

Description

Stratax uses OpenZeppelin's BeaconProxy pattern with Initializable specifically to support upgrades. StrataxOracle uses a plain constructor, making it non-upgradeable. Any fix or enhancement to oracle logic requires deploying a new contract and manually calling setStrataxOracle() on every Stratax proxy.

// src/StrataxOracle.sol:20
constructor() {
owner = msg.sender; // @> plain constructor — not upgradeable
}

Risk

Likelihood:

  • Any bug discovered in StrataxOracle requires a full redeployment and migration

  • Multiple Stratax proxies sharing the same beacon may point to different oracle versions during the migration window

Impact:

  • Inconsistent oracle versions across proxies during migration — different proxies receive different prices simultaneously

  • If the oracle owner key is compromised, there is no upgrade path to patch the oracle — only redeployment

Proof of Concept

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
// Deployment scenario showing inconsistent oracle versions:
//
// t=0: 5 Stratax proxies deployed, all pointing to StrataxOracle v1
// proxy1.strataxOracle = OracleV1
// proxy2.strataxOracle = OracleV1
// proxy3.strataxOracle = OracleV1
//
// t=1: H-1 (staleness bug) discovered — StrataxOracle v2 deployed with freshness check
// OracleV2 = new StrataxOracle() ← fresh deployment required
//
// t=2: Owner begins migration — calls setStrataxOracle(OracleV2) on each proxy
// proxy1.setStrataxOracle(OracleV2) ← updated
// proxy2.setStrataxOracle(OracleV2) ← updated
// // Owner's tx gets congested / front-run / forgotten
//
// t=3: During migration window:
// proxy1.getPrice(WETH) → OracleV2.getPrice() → reverts on stale price ✓
// proxy3.getPrice(WETH) → OracleV1.getPrice() → accepts stale price ✗
// // Two proxies return different prices for the same asset simultaneously

Recommended Mitigation

  • Convert StrataxOracle to use the same Initializable + BeaconProxy pattern as Stratax. A single beacon upgrade atomically updates the oracle logic for all Stratax proxies simultaneously, eliminating migration windows where different proxies operate with different oracle versions.

  • Deploy behind its own BeaconProxy so oracle upgrades propagate atomically to all Stratax instances.

- contract StrataxOracle {
- constructor() {
- owner = msg.sender;
- }
+ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
+
+ contract StrataxOracle is Initializable {
+ function initialize() external initializer {
+ owner = msg.sender;
+ }

Support

FAQs

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

Give us feedback!