A proxy upgrade swaps the code and keeps the storage. If V2 lays its variables out differently than V1, the new code reads the old bytes and interprets them as something else. Solidity will not warn you. Paste two storage layouts and see the collision at byte resolution.
No network access — enforced by Content-Security-Policy, not by promise
Findings
Slot map · V1 above, V2 below
SLOTbyte 31 — most significantbyte 0 — offset 0
Check your own contracts
Generate the JSON with forge inspect MyContractV1 storageLayout or solc --storage-layout. Both emit the { storage, types } object this expects.
Each is keccak256(id) − 1, chosen so no sequentially allocated variable can land there. An implementation only reaches these slots through inline assembly — which is exactly the case worth catching.