Analyze Proxy Contract Storage
Use a real proxy, implementation, block, and slot to distinguish the state address from the code and layout source.
Case objective
Determine where proxy state is stored, which contract supplies the storage layout, and how to read and verify a raw slot at a specific block.
Example transaction and context
This case continues with the transaction from block 17806056:
0xa84aa065ce61dbb1eb50ab6ae67fc31a9da50dd2c74eefd561661bfce2f1620cOpen the transaction in Skylens
The target is the Curve pETH-ETH-f pool. Users interact with minimal proxy 0x9848482da3Ee3076165ce6497eDA906E66bB85C5, while implementation 0x6326DEbBAa15bCFE603d831e7D75f4fc10d9B43E supplies the executable code.
Questions to answer
- Should state be read from the proxy or the implementation?
- Which address supplies the storage layout?
- How does slot
8at the target block map to SSTORE operations in the transaction?
Investigation steps
- Open the proxy address and load its implementation in Proxy Storage.
- Keep the proxy as the state address; use the implementation only as the source of code and storage layout.
- Locate slot
8in Storage Layout. If the variable cannot be decoded reliably, preserve the raw slot as the query key. - Query the slot at block
17806056and compare it with the transaction's State Changes. - Jump from State Changes to Execution Trace and verify that SSTORE operations in implementation code write to the proxy context.
Key evidence
| Evidence | Value |
|---|---|
| State address | Proxy 0x9848482da3Ee3076165ce6497eDA906E66bB85C5 |
| Layout / code source | Implementation 0x6326DEbBAa15bCFE603d831e7D75f4fc10d9B43E |
| Query block | 17806056 |
| Storage key | slot 8 (0x...0008) |
| Before | 0x00000000000000000000000000000000000000000000014f4ef71451a6d37997 |
| After | 0x00000000000000000000000000000000000000000000003f3278e0363aaefcf |
| SSTORE traces | 69, 87, 105, 144, 194 |
These facts preserve three distinct identities:
- State identity: the proxy address.
- Code and layout identity: the implementation address.
- Historical context: the transaction and block
17806056.
Reading slot 8 directly from the implementation would return the implementation's own storage, not the pool's business state.
Conclusion
The implementation supplies code for the pETH-ETH-f pool, but slot
8is stored on the proxy. Five SSTORE operations execute implementation code while State Changes correctly attributes the state to the proxy. Reading proxy state therefore requires the implementation layout, proxy storage, and target block together.
Caveats
- The historical block must use the implementation active at that time; the current implementation may not explain old state.
- An implementation can itself be a proxy, requiring another nested implementation lookup.
- Namespaced layouts using
@custom:storage-locationshould be decoded with EIP-7201 Decoder. - Until a layout is verified, report the address, slot, and raw value instead of presenting a guessed variable name as fact.
Related documentation
Debug an Unverified Contract
Narrow the scope with Execution Trace, then use opcodes, PCs, stack values, and runtime data to explain a critical call.
Reproduce and Verify a Transaction in Virtual TestNet
Fork a fixed block, execute a repeatable WETH deposit through RPC and Foundry, and verify the reset result.
