# Storage Layout Verification: Optimizer → OptimizerV3 UUPS Upgrade **Date:** 2026-02-13 **Result:** SAFE — storage layout is identical --- ## Inheritance Chain (C3 Linearization) Both contracts share the same inheritance: ``` Optimizer/OptimizerV3 → Initializable → UUPSUpgradeable → ERC1967Upgrade ``` --- ## Storage Slot Map ### OpenZeppelin Infrastructure (Slot 0) | Offset | Type | Variable | Size | |--------|------|----------|------| | 0 | `uint8` | `_initialized` | 1 byte | | 0 | `bool` | `_initializing` | 1 byte (packed) | ERC1967Upgrade uses **named constant slots** (not sequential): - `_IMPLEMENTATION_SLOT` = `0x360894...` — proxy implementation pointer - `_ADMIN_SLOT` = `0xb53127...` — proxy admin address - `_ROLLBACK_SLOT` = `0x4910fd...` — upgrade rollback check These do not conflict with sequential storage. ### Contract State Variables | Slot | Type | Variable | Optimizer.sol | OptimizerV3.sol | |------|------|----------|:---:|:---:| | 1 | `Kraiken` (address) | `kraiken` | Line 37 | Line 29 | | 2 | `Stake` (address) | `stake` | Line 38 | Line 30 | **Both contracts declare the same two state variables in the same order with the same types.** --- ## Comparison ``` Optimizer.sol (V1) OptimizerV3.sol ───────────────────── ───────────────────── Slot 0: _initialized, _initializing Slot 0: _initialized, _initializing Slot 1: Kraiken private kraiken Slot 1: Kraiken private kraiken Slot 2: Stake private stake Slot 2: Stake private stake ``` - No new state variables added in V3 - No variables removed or reordered - No type changes - No `__gap` arrays needed (both are final implementations, not base contracts) --- ## Function Signature Compatibility | Function | Optimizer | OptimizerV3 | Compatible | |----------|:---------:|:-----------:|:----------:| | `initialize(address,address)` | Yes | Yes | Yes | | `getLiquidityParams()` → `(uint256,uint256,uint24,uint256)` | Yes | Yes | Yes | | `_authorizeUpgrade(address)` | Yes | Yes | Yes | | `calculateSentiment(uint256,uint256)` | Yes | No (removed) | N/A (internal) | | `isBullMarket(uint256,uint256)` | No | Yes (new) | N/A (additive) | The critical external interface (`getLiquidityParams`) is identical. New functions are additive and don't affect storage. --- ## Upgrade Path ``` 1. Deploy OptimizerV3 implementation contract 2. Call UUPSUpgradeable(proxy).upgradeTo(newImpl) 3. No re-initialization needed (storage persists) 4. Verify: call getLiquidityParams() through proxy → returns V3 binary bear/bull params ``` The `UpgradeOptimizer.sol` script at `script/UpgradeOptimizer.sol` implements this correctly and includes post-upgrade verification. --- ## OptimizerV2 (Intermediate Version) `OptimizerV2.sol` also has identical storage layout (same two variables: `kraiken`, `stake`). The full upgrade chain Optimizer → OptimizerV2 → OptimizerV3 is safe at every step. --- ## Conclusion **UUPS Upgrade: APPROVED** - Storage layout: identical across all optimizer versions - Proxy infrastructure: preserved (initialization flags, admin slot) - No re-initialization required - The only change is the algorithm inside `getLiquidityParams()` — from sentiment-score interpolation to direct 2D binary mapping