diff --git a/docs/storage-layout-reference.md b/docs/storage-layout-reference.md
new file mode 100644
index 00000000..cf99e310
--- /dev/null
+++ b/docs/storage-layout-reference.md
@@ -0,0 +1,648 @@
+# YieldVault Smart Contract Storage Layout Reference
+
+**Version:** 2.0
+**Target:** Stellar Soroban (WASM)
+**Last Updated:** May 29, 2026
+
+---
+
+## 1. Storage Architecture Overview
+
+YieldVault uses a **namespace-partitioned storage model** with explicit collision prevention. All contract state is organized into nine logical namespaces, each serving a distinct functional domain:
+
+| Namespace ID | Name | Purpose | Scope |
+|------|------|---------|-------|
+| 0 | `Core` | Token, shares, assets, admin, strategy state | Vault fundamentals |
+| 1 | `Governance` | DAO voting, proposals, multisig configuration | Governance operations |
+| 2 | `User` | Share balances, deposits, per-user caps | User holdings |
+| 3 | `Shipment` | RWA shipment tracking and status | Asset provenance |
+| 4 | `Fee` | Protocol fees, treasury, fee accumulation | Revenue management |
+| 5 | `Withdrawal` | Timelocks, queues, minimum deposit rules | Withdrawal mechanics |
+| 6 | `Oracle` | Price oracle configuration, heartbeat | Price validation |
+| 7 | `Emergency` | Dual-approver actions, emergency proposals | Critical operations |
+| 8 | `Strategy` | Strategy whitelist, caps, risk thresholds | Strategy management |
+
+### Storage Layer Separation
+
+- **Proxy Storage** (`ProxyDataKey` enum, `upgrade.rs`)
+ - Lives in unstructured storage alongside the proxy implementation
+ - **Never overlaps** with vault instance storage (`DataKey` enum)
+ - Protected by EIP-1967-style hashed slot constants
+
+- **Vault Instance Storage** (`DataKey` enum, `lib.rs`)
+ - Contains all protocol state variables
+ - Organized into nine namespaces via `StorageNamespace` enum
+ - Subject to upgrade migrations and version tracking
+
+---
+
+## 2. Proxy Storage Layout
+
+The proxy contract maintains upgrade state using explicit numeric discriminators (0–4). These keys are **completely separate** from the vault's `DataKey` enum.
+
+### ProxyDataKey Enum (upgrade.rs)
+
+| Discriminator | Key Name | Type | Purpose | Slot Hash |
+|---|---|---|---|---|
+| 0 | `Admin` | `Address` | Current proxy admin | `0xb531276...` |
+| 1 | `Implementation` | `BytesN<32>` | Current WASM hash | `0x360894a...` |
+| 2 | `Initialized` | `bool` | Initialization flag | (derived from `ProxyDataKey::Initialized`) |
+| 3 | `PendingAdmin` | `Address` | Pending admin for two-step transfer | (derived) |
+| 4 | `StorageVersion` | `u32` | Storage schema version for migrations | (derived) |
+
+**Immutable Constants:**
+```rust
+pub const ADMIN_SLOT: [u8; 32] = [0xb5, 0x31, 0x27, 0x68, ...]; // keccak256("contract.proxy.admin") - 1
+pub const IMPLEMENTATION_SLOT: [u8; 32] = [0x36, 0x08, 0x94, 0xa1, ...]; // keccak256("contract.proxy.implementation") - 1
+```
+
+---
+
+## 3. Vault Instance Storage Layout
+
+### 3.1 Core Namespace (ID: 0)
+
+Fundamental vault state and configuration.
+
+| Storage Key | Type | Purpose | Upgrade Rule |
+|---|---|---|---|
+| `TokenAsset` | `Address` | Underlying token (USDC SAC) | **NEVER** modify or reorder |
+| `TotalShares` | `i128` | Aggregate vault shares outstanding | Can persist across versions |
+| `TotalAssets` | `i128` | Aggregate deposited assets | Can persist across versions |
+| `Admin` | `Address` | Current vault administrator | Proxy-managed, vault-stored |
+| `Strategy` | `Address` | Active strategy connector address | Can modify, increment version |
+| `State` | `VaultState` struct | Vault paused flag, totals snapshot | Can persist |
+| `DaoThreshold` | `i128` | DAO proposal voting threshold | Can persist |
+| `ProposalNonce` | `u32` | Counter for proposal IDs | Can persist |
+| `GovernanceConfig` | `GovernanceConfig` struct | Multisig signers, threshold, migration | Can persist |
+| `BenjiStrategy` | `Address` | BENJI strategy connector (deprecated) | Can persist; do not reorder |
+| `KoreanDebtStrategy` | `Address` | Korean debt strategy connector | Can persist; do not reorder |
+| `PauseReason` | `PauseReason` enum | Reason code for vault pause | Can persist |
+| `IsPaused` | `bool` | *(DEPRECATED: use PauseReason)* | Not used; kept for compat |
+
+**VaultState Struct:**
+```rust
+#[contracttype]
+pub struct VaultState {
+ pub total_shares: i128, // Replica of TotalShares for atomic updates
+ pub total_assets: i128, // Replica of TotalAssets for atomic updates
+ pub is_paused: bool, // Redundant with PauseReason; maintained for compatibility
+}
+```
+
+---
+
+### 3.2 Governance Namespace (ID: 1)
+
+DAO voting, governance configuration, and multisig setup.
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `DaoThreshold` | `i128` | Scalar | Voting threshold for proposals | Can persist |
+| `ProposalNonce` | `u32` | Scalar | Counter for unique proposal IDs | Can persist |
+| `GovernanceConfig` | `GovernanceConfig` struct | Scalar | Signers, threshold, migration deadline | Can persist |
+| `BenjiStrategy` | `Address` | Scalar | Legacy BENJI strategy address | Can persist |
+| `KoreanDebtStrategy` | `Address` | Scalar | Korean debt strategy address | Can persist |
+| `Proposal(u32)` | `StrategyProposal` struct | Parameterized by `proposal_id` | DAO proposal state for strategy voting | Can persist; parameterization prevents collisions |
+| `Vote(VoteKey)` | `bool` | Parameterized by `VoteKey` | Records whether voter has voted on proposal | Can persist |
+
+**StrategyProposal Struct:**
+```rust
+#[contracttype]
+pub struct StrategyProposal {
+ pub strategy: Address, // Strategy being proposed
+ pub yes_votes: i128, // Cumulative yes votes
+ pub no_votes: i128, // Cumulative no votes
+ pub executed: bool, // Proposal executed flag
+}
+```
+
+**VoteKey Struct (inline in DataKey enum):**
+```rust
+// Embedded in DataKey::Vote(VoteKey)
+pub struct VoteKey {
+ pub proposal_id: u32, // Which proposal
+ pub voter: Address, // Which voter
+}
+```
+
+**GovernanceConfig Struct:**
+```rust
+#[contracttype]
+pub struct GovernanceConfig {
+ pub signers: Vec
, // Current authorized signers
+ pub previous_signers: Vec, // Prior signer set (migration window)
+ pub threshold: u32, // Required signature count (M of N)
+ pub migration_deadline: u64, // Ledger timestamp after which old signers invalid
+}
+```
+
+---
+
+### 3.3 User Namespace (ID: 2)
+
+Per-user share balances, deposit amounts, and usage caps.
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `ShareBalance(Address)` | `i128` | Parameterized by `user` | Share balance for each user | Can persist; parameterization prevents collisions |
+| `UserDeposit(Address)` | `i128` | Parameterized by `user` | Cumulative deposit amount (cost basis) for tax tracking | Can persist |
+| `PerUserCap` | `i128` | Scalar | Maximum deposit per user (0 = unlimited) | Can persist; can modify |
+| `LastDepositTime(Address)` | `u64` | Parameterized by `user` | Timestamp of last deposit for cooldown enforcement | Can persist |
+| `UserCheckpoint(Address)` | `u32` | Parameterized by `user` | Latest checkpoint ID for this user | Can persist |
+| `UserBalanceAt(UserBalanceKey)` | `i128` | Parameterized by `user` + `checkpoint_id` | User's share balance snapshot at checkpoint | Can persist |
+
+**UserBalanceKey Struct (inline in DataKey enum):**
+```rust
+pub struct UserBalanceKey {
+ pub user: Address, // User address
+ pub checkpoint_id: u32, // Checkpoint iteration
+}
+```
+
+---
+
+### 3.4 Shipment Namespace (ID: 3)
+
+RWA shipment tracking for asset provenance and status management.
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `ShipmentByStatus(ShipmentStatus)` | `Vec` | Parameterized by `status` enum variant | List of shipment IDs with given status | Can persist; status is enum discriminator |
+| `ShipmentStatusOf(u64)` | `ShipmentStatus` enum | Parameterized by `shipment_id` | Current status of shipment | Can persist |
+
+**ShipmentStatus Enum:**
+```rust
+#[contracttype]
+pub enum ShipmentStatus {
+ Pending, // 0
+ InTransit, // 1
+ Delivered, // 2
+ Cancelled, // 3
+}
+```
+
+---
+
+### 3.5 Fee Namespace (ID: 4)
+
+Protocol fee configuration, treasury management, and fee accumulation.
+
+| Storage Key | Type | Purpose | Upgrade Rule |
+|---|---|---|---|
+| `FeeBps` | `i128` | Protocol fee rate in basis points (0–10000) | Can persist; can modify |
+| `Treasury` | `Address` | Treasury recipient address for fees | Can persist; can modify |
+| `TreasuryBalance` | `i128` | Accumulated protocol fees | Can persist |
+| `TreasuryRolloverExcess` | `i128` | Cumulative fees exceeding bounded accumulator | Can persist |
+
+---
+
+### 3.6 Withdrawal Namespace (ID: 5)
+
+Large-withdrawal timelocks, queued withdrawals, and minimum deposit enforcement.
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `LargeWithdrawalThreshold` | `i128` | Scalar | Share amount triggering 24-hour timelock | Can persist; can modify |
+| `PendingWithdrawal(Address)` | `PendingWithdrawal` struct | Parameterized by `user` | Locked withdrawal awaiting timelock expiry | Can persist |
+| `MinDeposit` | `i128` | Scalar | Minimum deposit amount (0 = no minimum) | Can persist; can modify |
+| `MinLiquidityBuffer` | `i128` | Scalar | Minimum idle liquidity retained before strategy allocation | Can persist; can modify |
+| `WithdrawalCooldown` | `u64` | Scalar | Cooldown duration in seconds (0 = disabled) | Can persist; can modify |
+| `WithdrawalQueueMeta` | `WithdrawalQueueMeta` struct | Scalar | FIFO queue head/tail, admin param change guard | Can persist |
+| `WithdrawalQueueEntry(u64)` | `WithdrawalQueueEntry` struct | Parameterized by `queue_sequence_number` | Queued withdrawal awaiting liquidity | Can persist |
+
+**PendingWithdrawal Struct:**
+```rust
+#[contracttype]
+pub struct PendingWithdrawal {
+ pub shares: i128, // Shares locked in timelock
+ pub unlock_timestamp: u64, // Ledger timestamp after which executable
+}
+```
+
+**WithdrawalQueueMeta Struct:**
+```rust
+#[contracttype]
+pub struct WithdrawalQueueMeta {
+ pub head: u64, // FIFO queue head index
+ pub tail: u64, // FIFO queue tail index
+ pub admin_last_change_ts: u64, // Timestamp of last admin param change
+ pub admin_min_interval_secs: u64, // Minimum interval between param changes
+ pub admin_interval_armed: bool, // Whether interval enforcement is active
+}
+```
+
+**WithdrawalQueueEntry Struct:**
+```rust
+#[contracttype]
+pub struct WithdrawalQueueEntry {
+ pub user: Address, // User requesting withdrawal
+ pub shares: i128, // Shares to burn
+ pub assets: i128, // Assets promised to user
+ pub enqueued_at: u64, // Ledger timestamp of enqueue
+}
+```
+
+---
+
+### 3.7 Oracle Namespace (ID: 6)
+
+Oracle price feed configuration and validation parameters.
+
+| Storage Key | Type | Purpose | Upgrade Rule |
+|---|---|---|---|
+| `PriceOracle` | `Address` | Oracle contract address | Can persist; can modify |
+| `OracleEnabled` | `bool` | Oracle validation enabled flag | Can persist; can modify |
+| `OracleHeartbeat` | `u64` | Maximum stale price duration (seconds) | Can persist; can modify |
+
+---
+
+### 3.8 Emergency Namespace (ID: 7)
+
+Dual-approver operations for critical emergency actions (pause, divest, upgrade).
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `EmergencyApprovers` | `EmergencyApprovers` struct | Scalar | Primary and secondary approver addresses | Can persist; can modify |
+| `EmergencyProposalNonce` | `u32` | Scalar | Counter for emergency proposal IDs | Can persist |
+| `Emergency(EmergencyStorageKey::Proposal(u32))` | `EmergencyProposal` struct | Parameterized by `proposal_id` | Emergency action proposal state | Can persist |
+| `Emergency(EmergencyStorageKey::DisputeWindow)` | `u64` | Scalar | Dispute window duration (seconds) | Can persist; default 3600 |
+
+**EmergencyApprovers Struct:**
+```rust
+#[contracttype]
+pub struct EmergencyApprovers {
+ pub primary: Address, // Initiator of emergency actions
+ pub secondary: Address, // Confirmer of emergency actions (must be distinct)
+}
+```
+
+**EmergencyProposal Struct:**
+```rust
+#[contracttype]
+pub struct EmergencyProposal {
+ pub kind: EmergencyActionKind, // Type of emergency action
+ pub pause_reason_code: u32, // Pause reason (0 = N/A)
+ pub divest_amount: Option, // Amount to divest (if divest action)
+ pub wasm_hash: Option>, // New WASM hash (if upgrade action)
+ pub initiator: Address, // Who initiated the proposal
+ pub confirmed: bool, // Whether secondary has confirmed
+ pub executed: bool, // Whether action has been executed
+ pub cancelled: bool, // Whether proposal was cancelled
+ pub dispute_deadline: u64, // Ledger timestamp before which admin can cancel
+}
+```
+
+**EmergencyActionKind Enum:**
+```rust
+#[contracttype]
+pub enum EmergencyActionKind {
+ Pause = 1, // Pause vault operations
+ Unpause = 2, // Resume vault operations
+ EmergencyDivest = 3, // Forcibly recall from strategy
+ ForceUpgrade = 4, // Execute code upgrade without normal DAO
+}
+```
+
+---
+
+### 3.9 Strategy Namespace (ID: 8)
+
+Strategy connector lifecycle, performance thresholds, and whitelisting.
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `StrategyWhitelist(Address)` | `u32` | Parameterized by `strategy_address` | Registration state: `1` = Pending, `2` = Active, `3` = Retired | Can persist; state transitions guarded |
+| `StrategyCap(Address)` | `i128` | Parameterized by `strategy_address` | Maximum allocation to strategy (0 = unlimited) | Can persist; can modify |
+| `StrategyRiskThreshold(Address)` | `i128` | Parameterized by `strategy_address` | Allocation limit based on risk tier | Can persist; can modify |
+| `StrategyWatermark(Address)` | `i128` | Parameterized by `strategy_address` | High-water mark for performance fees | Can persist; can modify |
+| `StrategyHeartbeat` | `u64` | Scalar | Maximum duration between strategy updates before "stale" | Can persist; can modify |
+| `StrategyHeartbeat(Address)` | `u64` | Parameterized by `strategy_address` | Last update timestamp for strategy | Can persist; automatically managed |
+
+**Strategy Registration State Machine:**
+```
+None → STATE_PENDING (1)
+ ↓
+STATE_ACTIVE (2) ← accepted for allocation
+ ↓
+STATE_RETIRED (3) ← no new allocations allowed
+```
+
+---
+
+### 3.10 Batch Deposit & Relayer Management
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `RelayerWhitelist(Address)` | `bool` | Parameterized by `relayer_address` | Whether relayer is authorized for batch deposits | Can persist; can modify |
+| `MaxBatchSize` | `u32` | Scalar | Maximum entries per `batch_deposit` call (default 50) | Can persist; can modify |
+
+---
+
+### 3.11 Checkpointing & Balance Snapshots
+
+| Storage Key | Type | Parameterization | Purpose | Upgrade Rule |
+|---|---|---|---|---|
+| `CheckpointNonce` | `u32` | Scalar | Counter for checkpoint iterations | Can persist |
+| `CheckpointTotals(u32)` | `CheckpointTotals` struct | Parameterized by `checkpoint_id` | Total shares/assets at checkpoint | Can persist |
+| `UserCheckpoint(Address)` | `u32` | Parameterized by `user` | Latest checkpoint ID for user | Can persist |
+| `UserBalanceAt(UserBalanceKey)` | `i128` | Parameterized by `user` + `checkpoint_id` | User balance snapshot at checkpoint | Can persist |
+
+**CheckpointTotals Struct:**
+```rust
+#[contracttype]
+pub struct CheckpointTotals {
+ pub total_shares: i128, // Aggregate shares at checkpoint
+ pub total_assets: i128, // Aggregate assets at checkpoint
+}
+```
+
+---
+
+## 4. Storage Key Collision Prevention
+
+### 4.1 Namespace Isolation
+
+Each `DataKey` variant is assigned to exactly one namespace via `StorageNamespace` enum (0–8). Soroban's `contracttype` macro encodes the enum discriminator in the storage key, ensuring variants in different enum values never collide.
+
+### 4.2 Parameterized Key Encoding
+
+Parameterized keys (e.g., `ShareBalance(Address)`) embed their parameter in the storage key hash:
+
+```rust
+// Soroban encodes as:
+// storage_key = hash(variant_discriminator, Address)
+env.storage().instance().set(&DataKey::ShareBalance(user), &balance);
+```
+
+- Different `user` values produce different storage keys
+- `ShareBalance(alice)` and `ShareBalance(bob)` are distinct slots
+- Parameter types must be `#[contracttype]`-compatible
+
+### 4.3 Proxy Storage Separation
+
+`ProxyDataKey` uses explicit numeric discriminators (0–4) and stores in proxy-managed slots, which are **completely separate** from vault instance storage. The vault's `DataKey` enum cannot reuse these discriminators.
+
+### 4.4 Registry Validation
+
+The `storage_registry.rs` module provides runtime validation:
+
+```rust
+pub fn validate_registry_no_collisions(
+ keys: &Vec
+) -> Result<(), Symbol>
+```
+
+All registered keys are tested at deployment to ensure no two keys share the same `(namespace, name)` pair.
+
+---
+
+## 5. Upgrade Safety Constraints
+
+### 5.1 Safe Operations
+
+✅ **Appending New State Variables:**
+- Add new `DataKey` variant at the end of the enum
+- Use unique discriminator (next available integer)
+- Assign to appropriate namespace
+- Initialize to sensible default in all code paths
+- Must not affect existing storage slots
+
+✅ **Adding New Parameterized Keys:**
+- Create new enum variant with distinct name
+- Parameterize by new or existing `#[contracttype]` struct
+- Ensure parameter type encodes uniquely
+- Test collision detection
+
+✅ **Extending Struct Fields:**
+- Only at **end of struct** (does not break binary layout)
+- Must update all access paths to handle field presence
+- Can initialize missing field as `default()` during first access
+- Document migration path for nodes decoding old state
+
+✅ **Changing Storage Version:**
+- Increment `STORAGE_VERSION` constant
+- Implement migration hook in `run_storage_migration()`
+- Ensure forward and backward compatibility semantics
+
+✅ **Modifying Parameter Types:**
+- Only if new type can be decoded from old serialization
+- Add version stamp to struct if unsure
+- Test deserialization with legacy data
+
+### 5.2 Forbidden Operations
+
+❌ **Reordering DataKey Variants:**
+- Changes discriminator values for existing keys
+- Breaks deserialization of live storage
+- **Always append, never reorder**
+
+❌ **Deleting or Renaming Existing Variants:**
+- Breaks access to live storage
+- Must deprecate with warning instead
+- Keep zombie variant marked `#[deprecated]`
+
+❌ **Mutating Parameter Types:**
+- Changes storage key hash
+- Existing data becomes inaccessible under new key
+- Requires explicit migration hook to copy data
+
+❌ **Changing Field Order in Structs:**
+- Breaks binary deserialization layout
+- Only append new fields at the end
+
+❌ **Reducing Numeric Type Capacity:**
+- E.g., `i128` → `i64`: data loss
+- E.g., `u32` → `u16`: overflow risk
+- Always expand or maintain type size
+
+---
+
+## 6. Migration Patterns
+
+### 6.1 Version-Gated Migration
+
+Each upgrade runs `run_storage_migration()` to adapt state for the new contract version:
+
+```rust
+fn run_storage_migration(env: &Env, target_version: u32) -> Result<(), VaultError> {
+ let current_version = get_storage_version(env);
+
+ // Version 1 → 2: Example migration
+ if current_version < 2 && target_version >= 2 {
+ // Copy data from old key to new key (if needed)
+ // Initialize new mandatory fields
+ // Validate invariants
+ }
+
+ set_storage_version(env, target_version);
+ Ok(())
+}
+```
+
+### 6.2 Field Presence Patterns
+
+When extending a struct, support both old and new shapes:
+
+```rust
+// During migration
+if let Some(old_value) = env.storage().instance().get(&DataKey::OldField) {
+ // Migrate old data
+ env.storage().instance().set(&DataKey::NewField, &migrated_value);
+}
+
+// In read paths
+let value = env.storage().instance()
+ .get(&DataKey::NewField)
+ .or_else(|| default_value()); // Graceful fallback
+```
+
+### 6.3 Immutable Field Preservation
+
+Never relocate or modify core identifiers:
+
+```rust
+// NEVER change:
+TokenAsset // Hardcoded contract instantiation
+Admin // Proxy-layer field
+Initialized // One-time setup flag
+PauseReason enum // Existing reason codes 0–6
+```
+
+---
+
+## 7. Storage Namespace Audit Checklist
+
+Before deploying contract upgrades, verify:
+
+- [ ] All existing `DataKey` variants remain unchanged and ordered identically
+- [ ] New variants appended at end of enum (no reordering)
+- [ ] New variant has unique discriminator (≥ current max + 1)
+- [ ] Assigned to appropriate `StorageNamespace`
+- [ ] Parameterized keys use only `#[contracttype]` types
+- [ ] No two keys map to same `(namespace, name)` pair
+- [ ] `storage_registry.rs` updated with new keys
+- [ ] Collision validation test passes
+- [ ] All access paths initialize new fields with sensible defaults
+- [ ] Migration hook (if needed) implemented and tested
+- [ ] Storage version incremented (if schema changes)
+- [ ] Backward compatibility preserved for reads
+- [ ] Emergency unwind and data recovery tested
+
+---
+
+## 8. Storage Slot Reference Table
+
+### Quick Lookup by Namespace
+
+**Core (0):** TokenAsset, TotalShares, TotalAssets, Admin, Strategy, State, DaoThreshold, ProposalNonce, GovernanceConfig, BenjiStrategy, KoreanDebtStrategy, PauseReason, EmergencyApprovers, EmergencyProposalNonce
+
+**Governance (1):** DaoThreshold, ProposalNonce, GovernanceConfig, BenjiStrategy, KoreanDebtStrategy, Proposal(u32), Vote(VoteKey)
+
+**User (2):** ShareBalance(Address), UserDeposit(Address), PerUserCap, LastDepositTime(Address), UserCheckpoint(Address), UserBalanceAt(UserBalanceKey)
+
+**Shipment (3):** ShipmentByStatus(ShipmentStatus), ShipmentStatusOf(u64)
+
+**Fee (4):** FeeBps, Treasury, TreasuryBalance, TreasuryRolloverExcess
+
+**Withdrawal (5):** LargeWithdrawalThreshold, PendingWithdrawal(Address), MinDeposit, MinLiquidityBuffer, WithdrawalCooldown, WithdrawalQueueMeta, WithdrawalQueueEntry(u64)
+
+**Oracle (6):** PriceOracle, OracleEnabled, OracleHeartbeat
+
+**Emergency (7):** EmergencyApprovers, EmergencyProposalNonce, Emergency(EmergencyStorageKey::Proposal(u32)), Emergency(EmergencyStorageKey::DisputeWindow)
+
+**Strategy (8):** StrategyWhitelist(Address), StrategyCap(Address), StrategyRiskThreshold(Address), StrategyWatermark(Address), StrategyHeartbeat, StrategyHeartbeat(Address)
+
+---
+
+## 9. Critical Constants
+
+| Constant | Value | Purpose |
+|---|---|---|
+| `STORAGE_VERSION` | 2 | Current schema version |
+| `MAX_PAGE_SIZE` | 50 | Max items in paginated queries |
+| `SHARE_PRICE_SCALE` | 1e18 | Decimal scaling for share price math |
+| `IMPLEMENTATION_SLOT` | `0x360894a...` | EIP-1967 proxy implementation slot hash |
+| `ADMIN_SLOT` | `0xb531276...` | EIP-1967 proxy admin slot hash |
+
+---
+
+## 10. Appendix: Reserved and Deprecated Fields
+
+| Key | Status | Reason | Replacement |
+|---|---|---|---|
+| `IsPaused` | Deprecated | Redundant with `PauseReason` | Use `PauseReason` enum |
+| `ShipmentByStatus(ShipmentStatus)` | Active | RWA provenance tracking | No replacement (core feature) |
+| `BenjiStrategy` | Active | Legacy strategy; kept for compat | Use `Strategy` instead |
+
+---
+
+## 11. Governance Storage Transitions
+
+**Governance Signer Migration (Active):**
+- Old signers stored in `GovernanceConfig.previous_signers`
+- New signers in `GovernanceConfig.signers`
+- Migration window controlled by `migration_deadline`
+- After deadline, only new signers are valid
+- Migration finalized by `finalize_governance_migration()`
+
+---
+
+## 12. Example: Safe Schema Extension
+
+**Scenario:** Add a new "vault insurance provider" address field.
+
+**Safe Implementation:**
+
+1. Add new `DataKey` variant:
+```rust
+#[contracttype]
+pub enum DataKey {
+ // ... existing variants ...
+ InsuranceProvider, // NEW: append at end
+}
+```
+
+2. Update registry:
+```rust
+keys.push_back(scalar(StorageNamespace::Core, "InsuranceProvider"));
+```
+
+3. Initialize on upgrade:
+```rust
+fn run_storage_migration(env: &Env, target_version: u32) {
+ if target_version >= 3 {
+ env.storage().instance().set(&DataKey::InsuranceProvider, &Address::default());
+ }
+}
+```
+
+4. Access with fallback:
+```rust
+fn insurance_provider(env: Env) -> Option {
+ env.storage().instance().get(&DataKey::InsuranceProvider)
+}
+```
+
+**Result:** Existing storage untouched. New field available for future business logic.
+
+---
+
+## 13. Example: Unsafe Schema Change (Do NOT Do)
+
+**❌ Forbidden:** Reorder `DataKey` variants
+
+```rust
+// WRONG: Breaks all existing storage access
+pub enum DataKey {
+ State, // Was 5th, now 1st → different discriminator
+ TotalShares, // Was 1st, now 2nd → different discriminator
+ TotalAssets, // Was 2nd, now 3rd → different discriminator
+ // ...
+}
+```
+
+**Why:** Discriminator changes mean `env.storage().instance().get(&DataKey::State)` now points to the wrong slot. The old `State` data is still in storage but unreachable. New contract can't read old balances.
+
+**Correct Approach:** Add new variant at end, implement migration to copy data if semantics change.
+