Review upgradeable Solidity proxies (UUPS, transparent, beacon) for storage-layout clashes, unprotected initialize, missing initializer lock, and implementation suicide. Use before shipping or auditing proxies.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add nuroctane/nur-cli --skill reviewing-upgradeable-proxies --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Reviewing Upgradeable Proxies?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/nuroctane-reviewing-upgradeable-proxies)More formats (shields.io, HTML) on the badges page.
---
name: reviewing-upgradeable-proxies
description: "Review upgradeable Solidity proxies (UUPS, transparent, beacon) for storage-layout clashes, unprotected initialize, missing initializer lock, and implementation suicide. Use before shipping or auditing proxies."
---
# Reviewing upgradeable proxies
A proxy bug is usually instant total loss. Review this class even when Slither is quiet.
In-scope source only. Confirm with storage-layout diffs and `test_RevertWhen_*`, not live upgrades.
## Pattern checklist
### Storage layout
- Implementation storage starts after the proxy reserved slots (ERC-1967).
- Upgrades **never reorder or remove** existing state variables. Append only, or use a storage-gap / ERC-7201 namespaced struct.
- Diff layouts between versions: `forge inspect Impl storage --pretty` (or solc storage layout JSON) and compare.
- Packed structs: changing a type width shifts neighbors.
### Initialize / constructors
- Implementation constructor must `_disableInitializers()` (OpenZeppelin) so the impl cannot be initialized and `selfdestruct`ed under old EVM rules / taken over.
- `initialize` is `initializer` (or `reinitializer(n)` on purpose) and **not** callable twice.
- Front-run: if `initialize` sets owner, the deploy script must initialize in the same tx as proxy creation (`forge script` + factory, or OZ upgrades plugin). A public uninitialized proxy is Critical.
- `reinitializer` version must increase; a lower/equal version is a bug.
### UUPS vs transparent vs beacon
- UUPS: `_authorizeUpgrade` must be access-controlled. Missing modifier = anyone upgrades. Slither `unprotected-upgrade`.
- Transparent: admin must not be a hot wallet that also calls logic (selector clash). Admin is for upgrade only.
- Beacon: swapping the beacon implementation upgrades **every** child. Beacon owner is a crown jewel.
### delegatecall surface
- No `delegatecall` to a user-supplied address.
- `upgradeToAndCall` data is trusted-admin only.
- Avoid `delegatecall` into contracts that use `selfdestruct` or that write `address(this)` assuming they are not a proxy.
## Steps
1. Identify proxy kind from `ERC1967Upgrade` / `UUPSUpgradeable` / `TransparentUpgradeableProxy` / `UpgradeableBeacon`.
2. List every `initialize` / `reinitializer` / `_authorizeUpgrade`.
3. Diff storage layout vs the previous tagged implementation (or vs OZ parent).
4. Write tests: attacker cannot `initialize`, cannot `upgradeTo`, cannot call admin functions on the proxy.
5. Confirm deploy script initializes atomically and keys live in an encrypted `cast` keystore (Foundry skill `secure-deployment-and-keys.md`).
## Expected output
`(issue, contract, slot/function, test, severity)`. Unprotected upgrade or uninitialized proxy = Critical, blocks deploy. Next: `contest-and-bounty-reporting` or the Foundry PASS/FAIL gate.
## Paid bounty analogs
Full `$` table: `hunting-x-linked-bounties` `references/paid-payouts.md`. Local tests only.
| $ | Protocol | Pack | Whitehat |
|---|----------|------|----------|
| **$10M** | Wormhole uninitialized UUPS impl | T12 | satya0x |
| $42k | 88mph unprotected `init` | T12 | Ashiq Amien |
| also-paid | Harvest uninit Uniswap V3 vaults; Teller beacon | T12 | Immunefi library |
Invariant: attacker cannot `initialize` the implementation. `test_RevertWhen_AttackerInitializesImplementation`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!