Skip to content
Back to skills

Reviewing Upgradeable Proxies

ASecurity

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.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 2, 2026
ai-agentsrust

Security analysis

A100/100

Scanned September 2, 2026

npx -y skills add nuroctane/nur-cli --skill reviewing-upgradeable-proxies --agent claude-code

Installs 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 with every re-scan.

Security grade badge for Reviewing Upgradeable Proxies
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nuroctane-reviewing-upgradeable-proxies/badge)](https://www.skillsdirectory.com/skills/nuroctane-reviewing-upgradeable-proxies)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…