# 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
