Back to Blog
Proxy Security Checklist: 33 Critical Upgradeability Checks
Security ChecklistWeb3 Security

Proxy Security Checklist: 33 Critical Upgradeability Checks

February 12, 2026
22 min
1 views

TL;DR — The 5 Things That Will Get Your Proxy Hacked

Building upgradeable contracts? These are the critical failures behind $350M+ in proxy exploits:
  1. Storage collision — New variables overwrite existing state, corrupting user data or funds
  2. Unprotected initializers — Anyone can reinitialize the contract and become admin
  3. Implementation self-destruct — Destroying the implementation bricks all proxies using it
  4. Function selector clashes — Proxy functions shadow implementation functions, breaking access control
  5. Upgrade authorization bypass — Weak admin controls allow unauthorized implementation changes
This checklist covers 33 security checks across 8 domains. Use it before your audit, during development, and as a pre-launch gate for all proxy implementations.

🔐 Interactive Checklist Available
We've created an interactive version of this checklist with expandable details, code examples, and audit checkboxes. Perfect for auditors and dev teams.

Introduction: Why Proxy Security Is Critical

Upgradeable smart contracts have become essential for DeFi protocols that need to iterate, fix bugs, and add features post-deployment. Proxy patterns enable this by separating contract logic (implementation) from state (proxy), allowing logic updates while preserving user data and funds.
But this power comes with extraordinary complexity and risk.
The numbers tell the story:
  • $350M+ lost to proxy-related exploits across DeFi
  • 770+ upgrade findings across 3,671 proxy audit issues analyzed
  • 564 initialization issues — unprotected or missing initializers
  • 176 storage collisions — layout corruption across implementations
  • 15% of findings are High+ severity, with critical impact on protocol security
Proxy patterns are among the most exploited smart contract mechanisms because they violate many of Solidity's safety assumptions. Unlike simple contracts, proxies must manage:
  • Cross-contract state consistency between proxy and implementation
  • Storage layout compatibility across upgrades
  • Initialization security without constructors
  • Function selector routing between proxy and implementation
  • Upgrade authorization and governance mechanisms
This checklist is distilled from analyzing 50+ proxy audit reports from leading firms, combined with post-mortems of major proxy exploits across DeFi. Whether you're implementing OpenZeppelin's upgradeable contracts, building custom proxy patterns, or auditing upgradeable systems, this guide will help you avoid becoming the next casualty.

How to Use This Checklist

This checklist is organized into eight critical domains:
Each section includes:
  • Why it matters — Context and real-world exploit examples
  • Security checks — Specific items to verify in your implementation
  • Red flags — Warning signs that indicate vulnerabilities
  • Code patterns — Safe vs. unsafe implementation examples
For teams using specific proxy patterns, we've included dedicated guidance for UUPS Proxies, Transparent Proxies, and Diamond Patterns.

1. Storage & Layout Security

Why It Matters

Storage collisions are the #1 cause of proxy vulnerabilities. When proxy and implementation contracts use overlapping storage slots, upgrades can silently overwrite critical data like user balances, ownership, or protocol parameters. The impact is often catastrophic and unrecoverable.
Unlike other smart contract bugs, storage collisions are nearly impossible to detect through testing because they may only manifest after specific upgrade sequences. By then, user funds are already lost.

Security Checks

ERC-1967 Compliance

  • Implementation slot is correct — Use bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) for implementation address storage
  • Admin slot is correct — Use bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1) for admin address storage
  • Beacon slot is correct — For beacon proxies, use bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)
  • Reserved slots are respected — Never use slots below 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc

Storage Gap Management

  • Gap arrays exist in all upgradeable contracts — Include uint256[50] private __gap; in all contracts that may be inherited
  • Gap sizes account for new variables — When adding variables, decrease gap size accordingly: add 2 variables, change uint256[50] to uint256[48]
  • Parent contract gaps are sufficient — Child contracts inheriting from upgradeable parents need gaps for their own future variables
  • Storage layout is documented — Maintain documentation showing which slots are used by which variables

Multi-Level Inheritance

  • Parent variable addition is safe — Adding variables to parent contracts can shift child storage slots. Use append-only patterns or dedicated storage structs
  • Diamond storage patterns for complex inheritance — For contracts with multiple inheritance, consider diamond storage to avoid slot conflicts
  • Struct packing is upgrade-safe — Changing struct member order or types breaks storage layout. Only append new members

Red Flags

  • No storage gaps in upgradeable contracts
  • Manual storage slot assignments without ERC-1967 compliance
  • Adding variables to middle of storage layout in upgrades
  • Complex inheritance without documented storage layout

2. Initialization & Constructor Patterns

Why It Matters

Proxy contracts cannot use constructors because the proxy's storage is separate from the implementation. This fundamental difference creates unique initialization vulnerabilities that don't exist in regular contracts. Unprotected initializers have led to complete protocol takeovers.

Security Checks

Initializer Protection

  • Initializer modifier is used — All initialization functions use OpenZeppelin's initializer modifier or equivalent protection
  • One-time execution is enforced — Initializers can only be called once per proxy deployment
  • Reentrancy protection exists — Initializers should have reentrancy guards since they often make external calls
  • Front-running protection implemented — Use access control or atomic deploy-initialize patterns to prevent initialization front-running

Constructor vs Initializer Separation

  • Critical setup in initializer, not constructor — Configuration like owner assignment, yield modes, or gas modes must be in initializer
  • Constructor only sets immutables — Implementation constructors should only set immutable variables and call _disableInitializers()
  • No storage writes in constructor — Constructor storage writes affect implementation, not proxy storage

Initialization State Management

  • All critical variables initialized — Owner, admin, fee recipients, precision values, and operational parameters explicitly set
  • Zero-value validation — Prevent initialization with zero addresses or invalid parameters
  • Initialization completeness checks — Verify all required initialization steps completed before contract becomes operational
  • Parent initializer chaining — When inheriting, all parent initializers must be called with onlyInitializing modifier

Implementation Contract Safety

  • Implementation is initialized on deployment — Call _disableInitializers() in implementation constructor to prevent direct initialization
  • Implementation cannot be used directly — Implementation should be unusable without proxy context

Red Flags

  • Public initializer without access control
  • Missing _disableInitializers() in implementation constructor
  • Critical configuration in constructor instead of initializer
  • No protection against initialization front-running

3. Upgrade Mechanisms & Authorization

Why It Matters

Unrestricted upgrade capabilities are equivalent to giving attackers complete control over user funds. Weak upgrade authorization has led to countless "rug pulls" where malicious implementations drain protocol funds. Even legitimate projects suffer when single keys controlling upgrades get compromised.

Security Checks

Upgrade Authorization

  • Multi-signature requirement for upgrades — Upgrades require multiple signatures from different parties (minimum 2-of-3, preferably higher for large TVL)
  • Timelock protection on critical upgrades — Major upgrades have mandatory delay periods (24-48h minimum) before execution
  • Role-based access control — Different roles for different upgrade operations, following principle of least privilege
  • Upgrade proposal transparency — Proposed implementations are published and verifiable before timelock execution

Implementation Validation

  • Interface compatibility checks — New implementations inherit required functions and maintain compatible interfaces
  • Storage layout compatibility — Automated tools verify storage layout compatibility (OpenZeppelin Upgrades plugin, etc.)
  • Initialization compatibility — New implementations don't require re-initialization that could reset critical state
  • Proxy compatibility verification — For UUPS proxies, verify new implementation includes correct proxiableUUID() and upgrade functions

Governance Integration

  • Decentralized upgrade control — Upgrades controlled by governance tokens/DAO rather than EOAs when appropriate for project maturity
  • Emergency upgrade procedures — Clear, limited emergency upgrade capabilities with higher authorization requirements
  • Upgrade execution monitoring — On-chain monitoring and alerts for all upgrade transactions
  • Rollback capabilities — Where possible, mechanisms to revert to previous implementations if issues are discovered

Red Flags

  • Single EOA controlling upgrades for production systems
  • No timelock on upgrades handling significant funds
  • Upgrades executable without multi-sig approval
  • Missing storage layout validation in upgrade process

4. Delegatecall & Execution Context

Why It Matters

Delegatecall is the mechanism that makes proxies work, but it's also their greatest source of vulnerability. When a proxy delegatecalls to an implementation, the implementation code runs in the proxy's storage context. This context switching creates opportunities for storage corruption, unauthorized access, and implementation-specific attacks.

Security Checks

Contract Existence Validation

  • Implementation address has code — Check extcodesize > 0 before delegatecall to prevent calls to empty addresses
  • Implementation address validation — Verify implementation address is a contract, not EOA or zero address
  • Implementation consistency — Store and validate implementation hash/codehash to detect unexpected changes

Context Preservation

  • Storage context awareness — Implementation functions must understand they execute in proxy storage context
  • msg.sender preservation — Verify msg.sender propagates correctly through proxy -> implementation -> external calls
  • msg.value handling — For payable functions, ensure msg.value is handled correctly across delegatecall boundary
  • Return data handling — Properly handle return data size and content from delegated calls

Delegatecall Safety

  • Return value validation — Check delegatecall success boolean and validate returned data
  • Gas handling — Appropriate gas forwarding and out-of-gas handling for delegated calls
  • Revert reason propagation — Forward revert reasons from implementation to proxy caller for debugging
  • State consistency — Ensure proxy state remains consistent even if delegated call fails

Red Flags

  • Delegatecall to unchecked addresses (user input, unvalidated storage)
  • No contract existence check before delegatecall
  • Ignoring delegatecall return value
  • Complex gas calculations for delegated calls

5. Access Control & Ownership

Why It Matters

Proxy contracts create additional layers of access control complexity. The proxy has its own admin/owner roles, while the implementation may have different role assumptions. Misconfigured access control can allow unauthorized upgrades, bypass intended restrictions, or create privilege escalation vulnerabilities.

Security Checks

Proxy Administration

  • Admin role separation — Proxy admin should be different from implementation owner/admin roles
  • Admin transfer procedures — Secure procedures for transferring proxy admin rights, preferably with accept/confirm patterns
  • Admin key security — Admin keys use hardware wallets, multi-sig, or other secure key management
  • Admin function access control — Only proxy admin can call upgrade functions, no exceptions

Implementation Access Control

  • Context-aware access control — Implementation access control works correctly when called via proxy
  • Role consistency across upgrades — Admin/owner roles preserved correctly across implementation upgrades
  • Initialization access control — Initializer can only be called by authorized parties
  • Emergency functions protection — Emergency stop, pause, and recovery functions properly restricted

Cross-Contract Permissions

  • Proxy-implementation permission sync — Permissions granted to proxy address work with implementation logic
  • External protocol integration — Other protocols correctly recognize proxy address for permissions/allowances
  • Signature verification compatibility — EIP-712 signatures work correctly with proxy context

Red Flags

  • Same address controls both proxy admin and implementation admin
  • No transfer procedures for admin roles
  • Implementation access control relies on msg.sender without considering proxy context
  • Missing access control on initialization functions

6. Implementation Safety

Why It Matters

Since all proxies share the same implementation contract, vulnerabilities in the implementation affect every proxy instance. A compromised or destroyed implementation can break hundreds or thousands of proxy instances simultaneously, magnifying the impact far beyond single-contract failures.

Security Checks

Self-Destruct Protection

  • No selfdestruct in implementation — Implementation contracts should never include selfdestruct functionality
  • Delegatecall to external contracts restricted — If implementation makes delegatecalls, ensure target contracts cannot selfdestruct
  • Library safety verification — External libraries used by implementation are safe and cannot be destroyed
  • Upgrade path preservation — Ensure no upgrade path can lead to an implementation with selfdestruct

Implementation Immutability

  • Implementation deploy security — Implementation deployed by trusted deployer, not arbitrary EOA
  • Implementation verification — Implementation source code verified on block explorers
  • Implementation audit status — All implementations undergo security audits before deployment
  • Implementation address management — Track and monitor all implementation addresses used by proxy instances

Library and External Dependency Safety

  • Library immutability — External libraries are deployed immutably (not upgradeable themselves)
  • Library audit status — All libraries used by implementation are audited
  • Dependency minimization — Minimize external dependencies to reduce attack surface
  • Version pinning — Pin library versions to audited releases, don't auto-upgrade

Red Flags

  • Implementation contains selfdestruct functionality
  • Implementation makes delegatecalls to unknown/user-controlled contracts
  • Using non-audited or upgradeable libraries
  • Missing implementation address validation

7. Function Selector Management

Why It Matters

Proxy contracts forward function calls to implementations based on function selectors (first 4 bytes of function signature). When proxy and implementation have functions with identical selectors, the proxy function takes precedence, potentially bypassing intended access controls or breaking expected behavior.

Security Checks

Selector Collision Prevention

  • No 4-byte collisions — Verify proxy admin functions don't have same selectors as implementation functions
  • Collision detection tools — Use automated tools to detect potential selector collisions during development
  • Systematic collision analysis — For complex proxies, maintain a registry of all function selectors across proxy and implementation
  • Transparent Proxy pattern compliance — Admin can only call admin functions, users can only call implementation functions

Proxy Function Design

  • Minimal proxy function surface — Proxy should expose minimal functions (upgrade, admin change, etc.)
  • Clear function separation — Obvious separation between proxy management and business logic functions
  • Function naming conventions — Use naming that clearly indicates proxy vs implementation functions
  • Selector reservation — Reserve function selectors for proxy management to prevent future collisions

Implementation Function Safety

  • No proxy-like functions in implementation — Implementation shouldn't include functions like upgrade(), changeAdmin() unless specifically designed as UUPS
  • Function visibility appropriate — Implementation functions have correct visibility (external vs public vs internal)
  • Delegatecall awareness — Implementation functions account for being called via delegatecall

Red Flags

  • Duplicate function selectors between proxy and implementation
  • Complex proxy interfaces that increase collision probability
  • Implementation includes proxy-management-like functions without clear purpose
  • No systematic collision detection in development process

8. Common Proxy Vulnerabilities

Why It Matters

Certain vulnerability patterns appear repeatedly across different proxy implementations. These common pitfalls are responsible for the majority of proxy-related exploits and should be systematically checked in any proxy implementation.

Security Checks

Initialization Vulnerabilities

  • Initialization front-running protection — Deployment and initialization should be atomic or access-controlled
  • Reinitialization prevention — Initializers can only be called once per proxy instance
  • Partial initialization protection — Failed initialization doesn't leave proxy in inconsistent state
  • Parameter validation — All initialization parameters validated for correctness and safety

Upgrade Vulnerabilities

  • Storage layout preservation — New implementations maintain compatible storage layout
  • Access control preservation — Admin/owner roles correctly transferred to new implementation
  • State migration safety — Any required state migrations are safe and tested
  • Rollback procedures — Procedures exist to rollback failed upgrades

Economic and MEV Vulnerabilities

  • No upgrade arbitrage opportunities — Upgrades don't create MEV extraction opportunities at user expense
  • Fee structure preservation — Upgrade doesn't manipulate fee calculations to drain funds
  • Tokenomics compatibility — Upgrades maintain tokenomics invariants (supply, distribution, etc.)

Integration Vulnerabilities

  • External protocol compatibility — Upgrades don't break integrations with other protocols
  • Oracle/price feed compatibility — Price feeds and oracles continue working correctly post-upgrade
  • Cross-chain consistency — For multi-chain deployments, upgrade coordination prevents inconsistencies

Red Flags

  • No systematic testing of upgrade procedures
  • Missing validation of upgrade impacts on external integrations
  • Upgrades that modify core tokenomics without user consent
  • No monitoring for post-upgrade behavior

UUPS Proxy Checklist

For teams implementing Universal Upgradeable Proxy Standard (UUPS):

Implementation Requirements

  • proxiableUUID() function present — Implementation must include correct UUID for UUPS compatibility: 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
  • Upgrade authorization in implementation — Upgrade logic resides in implementation, not proxy
  • Access control on upgrade functions — Only authorized parties can call upgrade functions
  • Implementation address validation — New implementation address validated before upgrade

Upgrade Function Safety

  • _authorizeUpgrade protection — Override _authorizeUpgrade with appropriate access control
  • Upgrade atomicity — Upgrade and any required initialization happen atomically
  • Upgrade event emission — Upgrades emit events for monitoring and transparency
  • Gas optimization — UUPS upgrades are more gas-efficient than Transparent Proxy upgrades

Storage Management

  • Implementation storage preservation — UUPS implementations can have storage variables (unlike Transparent Proxy implementations)
  • Storage layout documentation — Maintain clear documentation of storage layout across upgrades
  • Gap management — Use storage gaps appropriately for future expansion

Transparent Proxy Checklist

For teams using OpenZeppelin's Transparent Proxy pattern:

Admin Separation

  • Proxy admin contract used — Use ProxyAdmin contract, not direct admin EOA
  • Admin cannot call implementation — Transparent proxy admin can only call admin functions, users only call implementation
  • Admin function protection — Admin functions require ProxyAdmin contract authorization
  • Clear role separation — Obvious separation between admin operations and user operations

Implementation Restrictions

  • No admin functions in implementation — Implementation should not contain proxy admin functions (upgradeability is handled by proxy)
  • Implementation is stateless — Implementation contract itself holds no state, all state in proxy
  • Implementation initialization — Implementation calls _disableInitializers() in constructor

Upgrade Process

  • ProxyAdmin controls upgrades — All upgrades go through ProxyAdmin contract
  • Implementation validation — ProxyAdmin validates new implementation before upgrade
  • Upgrade transparency — All upgrades are transparent and auditable through ProxyAdmin

Diamond Standard Checklist

For teams implementing EIP-2535 Diamond Standard:

Facet Management

  • Facet function signatures tracked — Diamond storage tracks which facet implements each function selector
  • No selector collisions between facets — Function selectors are unique across all facets
  • Facet upgrade authorization — Only authorized parties can add/replace/remove facets
  • Facet address validation — New facet addresses validated as contracts before installation

Diamond Storage

  • Diamond storage pattern used — Use diamond storage structs to avoid storage collisions between facets
  • Storage namespace isolation — Each facet uses its own storage namespace
  • Consistent storage access — All facets access diamond storage consistently
  • Storage layout documentation — Document storage layout for each facet

Cut Function Security

  • diamondCut access control — Only authorized parties can modify diamond facets
  • Cut operation validation — Validate all add/replace/remove operations before execution
  • Atomic facet operations — Facet modifications are atomic (all succeed or all fail)
  • Cut event emission — All diamond modifications emit appropriate events

Fallback Function

  • Proper function routing — Fallback correctly routes calls to appropriate facets
  • Unknown selector handling — Graceful handling of calls to non-existent functions
  • Gas optimization — Efficient function selector lookup and routing
  • Reentrancy protection — Fallback function protected against reentrancy attacks

Testing Your Proxy Implementation

Security checks are only as good as your testing. Here's what your test suite should cover:

Storage Layout Testing

  • Cross-upgrade storage consistency — Deploy proxy, upgrade implementation, verify storage unchanged
  • Storage collision detection — Automated tests for storage slot conflicts
  • Multi-upgrade scenarios — Test multiple sequential upgrades for storage layout preservation
  • Inheritance testing — Verify storage layout with complex inheritance hierarchies

Initialization Testing

  • One-time initialization — Verify initializers can only be called once
  • Front-running resistance — Test initialization under front-running conditions
  • Failed initialization recovery — Test behavior when initialization fails partway through
  • Parameter validation — Test all edge cases for initialization parameters

Upgrade Process Testing

  • Authorization testing — Verify only authorized parties can upgrade
  • Implementation validation — Test upgrade process with invalid implementations
  • Storage migration testing — For upgrades requiring data migration, test migration safety
  • Rollback testing — Test ability to rollback to previous implementations

Access Control Testing

  • Role separation testing — Verify proxy admin vs implementation roles work correctly
  • Cross-upgrade role preservation — Verify roles preserved across upgrades
  • Edge case authorization — Test authorization edge cases and boundary conditions
  • Multi-signature integration — Test integration with multi-sig admin contracts

Security Scenario Testing

  • Malicious implementation testing — Test proxy behavior with malicious implementations
  • Selector collision testing — Test behavior when selectors collide
  • Reentrancy testing — Test all functions for reentrancy vulnerabilities
  • Gas griefing testing — Test resistance to gas griefing attacks

Before You Launch: Final Checklist

  • Multiple independent audits completed — At least two audits from reputable firms covering proxy patterns specifically
  • Formal verification considered — For high-value systems, consider formal verification of upgrade mechanisms
  • Upgrade procedures documented — Clear, tested procedures for performing upgrades
  • Emergency response plan — Plan for responding to proxy vulnerabilities, including upgrade and pause procedures
  • Monitoring and alerting operational — Real-time monitoring of upgrade events, admin actions, and anomalous behavior
  • Bug bounty program launched — Incentivize security researchers to find proxy-specific vulnerabilities
  • Graduated rollout planned — Start with limited functionality/funds and gradually increase
  • Storage layout tooling — Automated tools for storage layout validation integrated into CI/CD
  • Admin key security — Proxy admin keys secured with hardware wallets, multi-sig, or institutional custody
  • User communication plan — Clear communication about proxy upgrade policies and user protections

Conclusion: Build Upgradeable Contracts That Last

Proxy patterns unlock the ability to iterate and improve smart contracts post-deployment, but they introduce complexity that can be catastrophic if mishandled. The difference between a secure proxy implementation and a $100M exploit often comes down to subtle details: a missing storage gap, an unprotected initializer, or a function selector collision.
The upgrade capability that makes proxies powerful also makes them uniquely dangerous. Unlike regular smart contracts where bugs are contained, proxy vulnerabilities can affect entire ecosystems of dependent contracts and users.
Use this checklist as your foundation, not your ceiling. Every proxy implementation is unique, and your security analysis should account for your specific upgrade patterns, access control models, and integration requirements.
The cost of getting proxy security wrong is measured in hundreds of millions of dollars and broken user trust. The cost of getting it right? Disciplined development practices, thorough testing, and comprehensive audits.
Choose wisely. Your users' funds depend on it.

Get Expert Help

Building upgradeable contracts or auditing proxy implementations? Proxy security isn't just complex—it's specialized.
At Zealynx, we've audited dozens of proxy implementations across UUPS, Transparent, Diamond, and custom patterns. We know the subtle vulnerabilities that hide in storage layouts, initialization sequences, and upgrade mechanisms.
Ready to secure your upgradeable contracts? Get a quote or reach out directly to discuss your proxy implementation.

Additional Resources

FAQ: Proxy & Upgradeability Security

1. What's the most common cause of proxy exploits?
Storage collisions and unprotected initializers account for over 60% of proxy vulnerabilities. Storage collisions occur when proxy and implementation use the same storage slots, corrupting data. Unprotected initializers allow anyone to reinitialize contracts and gain admin access.
2. Should I use UUPS or Transparent Proxy pattern?
UUPS is more gas-efficient and flexible but puts upgrade logic in the implementation (more complex). Transparent Proxy is simpler and safer but costs more gas. For new projects, UUPS is generally recommended if you have the expertise to implement it safely.
3. How do I prevent storage collisions in upgrades?
Follow ERC-1967 for proxy storage slots, use storage gaps (uint256[50] private __gap) in all upgradeable contracts, document storage layouts, and use OpenZeppelin's storage layout validation tools. Never add variables to the middle of existing storage layouts.
4. Can I upgrade a proxy to a completely different contract?
Technically yes, but it's extremely dangerous. The new implementation must maintain compatible storage layout, function interfaces, and access control. It's safer to add new functions than replace existing logic entirely.
5. What happens if my implementation contract gets self-destructed?
All proxies using that implementation become permanently broken. This is why implementations should never include selfdestruct and should be treated as immutable infrastructure. Always verify implementation code before upgrade.
6. How many audits should a proxy implementation get?
Minimum two independent audits from firms experienced with proxy patterns. Proxy security is specialized—general smart contract auditors may miss proxy-specific vulnerabilities. Consider additional audits for high-value systems.

Glossary

TermDefinition
Implementation ContractThe contract containing the actual business logic, called by proxy contracts via delegatecall
Upgrade AuthorizationAccess control mechanisms that restrict who can upgrade proxy implementation contracts
Function Selector CollisionWhen proxy and implementation contracts have identical 4-byte function signatures, causing unpredictable behavior
Implementation InitializerA function that replaces constructors in proxy patterns, used to set up initial contract state
Unstructured StorageStorage pattern using keccak256 hash-derived slots to prevent collisions between proxy and implementation variables

oog
zealynx

Subscribe to Our Newsletter

Stay updated with our latest security insights and blog posts

© 2024 Zealynx