harb/onchain/analysis/STORAGE_LAYOUT.md

102 lines
3.3 KiB
Markdown
Raw Permalink Normal View History

# 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