Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Glossary

UUPS (Universal Upgradeable Proxy Standard)

UUPS is an Ethereum smart contract upgrade standard (EIP-1822) where the logic for upgrading is built into the implementation contract itself, not a separate admin contract.
Chainscore © 2026
definition
BLOCKCHAIN DEVELOPMENT

What is UUPS (Universal Upgradeable Proxy Standard)?

A technical standard for creating upgradeable smart contracts on the Ethereum blockchain, enabling logic updates while preserving contract state and address.

The Universal Upgradeable Proxy Standard (UUPS) is an Ethereum smart contract pattern, defined in EIP-1822, that separates a contract's storage and logic into two distinct contracts: a proxy contract that holds the state and a logic contract that contains the executable code. The proxy uses a delegatecall to execute all functions from the logic contract's address, meaning the logic contract's code runs in the context of the proxy's storage. This separation is the core mechanism that enables upgradeability, as the proxy can be pointed to a new, improved logic contract while the user-facing address and all stored data remain unchanged.

A key architectural distinction of UUPS from other patterns like the Transparent Proxy is where the upgrade logic resides. In UUPS, the upgrade authorization and function (upgradeTo) are implemented within the logic contract itself, not the proxy. This makes the proxy contract simpler and potentially more gas-efficient for users, as it avoids certain storage slot checks on every call. However, it places a critical responsibility on developers: if a new logic contract is deployed without the upgradeTo function, the proxy becomes irrevocably frozen and can never be upgraded again, making upgradeability management a central security consideration.

The upgrade process involves deploying a new version of the logic contract and then calling the upgradeTo(address newImplementation) function on the proxy, which updates the stored pointer. This must be executed by an account with the appropriate upgrade role, typically controlled by a multisig wallet or decentralized autonomous organization (DAO) for security. Because the storage layout between logic contract versions must be storage-layout compatible, developers must carefully follow patterns like inheriting storage variables or using unstructured storage to avoid corrupting the existing data when upgrading.

UUPS is widely used in major protocols like Uniswap V3 due to its gas efficiency for end-users. Its design encourages a more explicit and auditable upgrade process, as the upgrade capability is a visible part of the logic contract's interface. When implementing UUPS, rigorous testing with tools like OpenZeppelin Upgrades Plugins is essential to prevent storage collisions and ensure the security of the upgrade path, making it a powerful but advanced pattern for maintaining long-lived, evolvable decentralized applications.

how-it-works
MECHANISM

How Does UUPS Work?

An explanation of the technical architecture and execution flow that enables smart contract upgrades in the Universal Upgradeable Proxy Standard.

The Universal Upgradeable Proxy Standard (UUPS) is an upgrade pattern where a proxy contract delegates all function calls to a separate logic contract via the low-level delegatecall operation. This mechanism allows the proxy's storage and address to remain constant while its underlying code logic can be replaced by deploying a new implementation contract and updating the proxy's reference. The key distinction from other patterns like the Transparent Proxy is that the upgrade logic is embedded within the implementation contract itself, not the proxy.

The execution flow begins when a user interacts with the proxy's address. The proxy's fallback function uses delegatecall to execute the code from the logic contract in the context of the proxy's own storage. This means the logic contract manipulates the proxy's state directly. To perform an upgrade, an authorized account calls an upgradeTo(address newImplementation) function. Crucially, this function must be part of the logic contract's code, requiring each new implementation to include and properly secure the upgrade functionality.

A critical security consideration in UUPS is the potential for function selector clashes. Since upgrade functions reside in the implementation, developers must ensure these selectors do not conflict with the selectors of the core business logic. Proper use of inheritance from a base UUPS contract (like OpenZeppelin's UUPSUpgradeable) helps manage this risk. Furthermore, the final implementation can be made immutable by omitting the upgrade function, permanently freezing the logic—a common practice for finalizing a protocol after extensive testing and audits.

key-features
UPGRADEABLE PROXY PATTERN

Key Features of UUPS

The Universal Upgradeable Proxy Standard (EIP-1822) is a smart contract pattern that separates a contract's logic from its storage, enabling seamless upgrades while preserving user data and contract address.

01

Logic & Storage Separation

A UUPS proxy is a minimal contract that delegates all function calls to a separate logic contract via delegatecall. This creates a clean separation where the proxy holds all state (storage) and the logic contract contains the executable code. This architecture is fundamental to enabling upgrades without data migration.

02

Upgrade Mechanism

The upgrade is performed by calling a function (e.g., upgradeTo(address newImplementation)) on the proxy contract, which updates the stored address of the logic contract. This function must be protected by appropriate access controls (like onlyOwner). Subsequent calls are automatically routed to the new logic, enabling bug fixes and feature additions.

03

Initialization vs Constructor

Because the logic contract's constructor code runs only once during its own deployment, UUPS uses a separate initializer function. This function, often named initialize, must be called after the proxy links to the logic contract to set up initial state. It is critical to protect this function from being re-executed, typically using an initializer modifier.

04

Gas Efficiency & Size

Compared to the Transparent Proxy pattern, UUPS proxies are more gas-efficient for users. The proxy contract itself contains the upgrade logic, eliminating the need for an external ProxyAdmin contract and the associated overhead of checking the caller's role for every transaction. This results in lower gas costs for regular function calls.

05

Security & Self-Destruct Risk

A key consideration is that the upgrade logic resides in the implementation contract itself. If an upgrade function contains a bug or the implementation is self-destructed, the proxy can become permanently frozen and un-upgradeable. This contrasts with Transparent Proxies, where the upgrade admin is a separate contract.

code-example
IMPLEMENTATION

UUPS Code Example

A practical demonstration of the Universal Upgradeable Proxy Standard (UUPS) pattern, showing how to separate a contract's logic from its storage to enable seamless upgrades.

A minimal UUPS implementation consists of three core components: a Proxy contract, a Logic contract, and an optional ProxyAdmin. The proxy holds the state (storage) and delegates all function calls to the current logic contract address via a low-level delegatecall. The logic contract contains the executable code but stores no persistent data itself. The upgrade mechanism is a function (e.g., upgradeTo(address newImplementation)) that resides within the logic contract, allowing the proxy to update its logic address. This design is encapsulated in the OpenZeppelin UUPSUpgradeable library.

The key security consideration in UUPS is that the upgrade function must be protected by appropriate access controls, such as the onlyOwner modifier. Since the upgrade logic is part of the implementation, a flawed or unprotected upgrade function can permanently lock the contract or be exploited. Developers must also ensure storage compatibility between old and new logic contracts to prevent storage collisions. The initializer function, which replaces the constructor for upgradeable contracts, must be called only once to set up the initial state.

Here is a simplified code structure. First, the Logic Contract (Implementation):

solidity
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyLogicV1 is UUPSUpgradeable {
    address public owner;
    uint256 public value;

    function initialize() public initializer {
        owner = msg.sender;
    }
    // Function to upgrade the proxy to a new implementation
    function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

    function setValue(uint256 newValue) public {
        value = newValue;
    }
}

The _authorizeUpgrade hook is where upgrade permissions are enforced.

Second, the Proxy is deployed using a factory or manually, pointing to the initial logic contract. In practice, you would use OpenZeppelin's ERC1967Proxy:

solidity
// Deployment script (JavaScript/Pseudocode)
const LogicV1 = await ethers.getContractFactory("MyLogicV1");
const logicV1 = await LogicV1.deploy();
await logicV1.deployed();

const Proxy = await ethers.getContractFactory("ERC1967Proxy");
const proxy = await Proxy.deploy(logicV1.address, "0x"); // "0x" represents empty initialization data
await proxy.deployed();

// Connect to the proxy as the logic contract
const proxiedContract = await ethers.getContractAt("MyLogicV1", proxy.address);
await proxiedContract.initialize();

After deployment, interactions are made with the proxy address, which delegates calls to the logic.

To execute an upgrade, a new version of the logic contract (MyLogicV2) is deployed. The upgrade is then performed by calling the upgradeTo function on the proxy, which is actually executed in the context of the old logic contract but updates the proxy's stored implementation address. The call must be made by the authorized account (e.g., the owner):

solidity
// In MyLogicV2, which inherits from MyLogicV1 and UUPSUpgradeable
contract MyLogicV2 is MyLogicV1 {
    function newFeature() public pure returns (string memory) {
        return "V2 Feature";
    }
}
// Upgrade transaction
await proxiedContract.upgradeTo(MyLogicV2.address);

All subsequent calls to the proxy will use the new MyLogicV2 code while preserving the existing contract state and address.

Compared to the Transparent Proxy pattern, UUPS is more gas-efficient for users because it avoids an extra storage read to check if the caller is the admin. However, it places the burden of upgrade safety and execution entirely on the logic contract itself. This example underscores the pattern's elegance and its critical requirement for rigorous testing of the upgrade mechanism to prevent irrevocable errors, making it a preferred choice for sophisticated, upgradeable contract systems where gas optimization is a priority.

UPGRADEABLE CONTRACT PATTERNS

UUPS vs. Transparent Proxy Pattern

A technical comparison of the two primary proxy patterns for upgradeable smart contracts on Ethereum.

Feature / MechanismUUPS (Universal Upgradeable Proxy Standard)Transparent Proxy Pattern

Upgrade Logic Location

Implementation Contract

Proxy Contract

Proxy Size (Deployment Gas)

Smaller (~1.1M gas)

Larger (~1.3M gas)

Implementation Contract Size

Larger (includes upgrade logic)

Smaller (pure logic)

Storage Overhead

No extra slots

No extra slots

Admin Function Call Overhead

None

~2.4k gas per call

Upgrade Function Selector Clash Risk

Present (must be managed)

None (admin calls are protected)

Implementation Self-Destruct Risk

Present (if upgrade function is removed)

None (admin logic is in proxy)

EIP-1967 Compliance

Yes

Yes

security-considerations
UPPS

Security Considerations & Risks

The Universal Upgradeable Proxy Standard (UUPS) is a pattern for creating upgradeable smart contracts, but its power introduces specific security vectors that developers and auditors must rigorously address.

01

Implementation Initialization Vulnerability

A critical risk in UUPS is that the implementation contract's constructor code is not executed when the proxy points to it. Initialization logic must be placed in a separate, explicit initialize function. If this function lacks proper access control or can be called multiple times, it can lead to contract hijacking. Best practices include using the initializer modifier from OpenZeppelin and storing the initialization state to prevent reentrancy.

02

Selfdestruct in Implementation

Unlike the Transparent Proxy pattern, the upgrade logic resides in the implementation contract itself. If a malicious upgrade introduces a selfdestruct operation, calling it will destroy the implementation, permanently bricking all associated proxies and locking all user funds. This makes rigorous auditing of every new implementation version paramount, as a single bad upgrade can be catastrophic.

03

Function Selector Clashes

The upgradeTo function must have a unique signature that does not clash with the logic contract's public interface. A clash would allow a user to accidentally call the upgrade function, potentially leading to unauthorized upgrades. UUPS implementations (like OpenZeppelin's) mitigate this by using an uncommon function signature (upgradeToAndCall) and ensuring it is not overridden by the logic contract's API.

04

Governance & Admin Key Risk

The entity holding the upgrade authority (e.g., a multi-sig wallet, DAO, or single admin key) represents a central point of failure. Compromise of these keys allows an attacker to upgrade the proxy to a malicious implementation. Mitigation involves using decentralized governance (e.g., timelocks, multi-sig with high thresholds) and ensuring the upgrade mechanism itself is non-upgradeable to prevent privilege escalation.

05

Storage Layout Incompatibility

When upgrading to a new implementation, the storage layout must remain compatible. Adding, removing, or reordering state variables in the new contract will corrupt the proxy's existing storage, leading to undefined behavior and loss of funds. Developers must follow strict inheritance and storage append rules, often using tools like the OpenZeppelin Upgrades Plugins to validate storage compatibility automatically.

06

Proxy vs. Implementation Distinction

A key operational risk is confusion between the Proxy address (where users hold assets) and the Implementation address (where logic lives). Sending funds or interacting directly with the implementation is a common user error that results in permanent loss. Clear documentation, verified source code, and user interface design must emphasize which address is the canonical entry point.

ecosystem-usage
UPPS

Ecosystem Usage & Examples

The Universal Upgradeable Proxy Standard (UUPS) is a design pattern for smart contracts that separates logic from storage, enabling secure and gas-efficient upgrades. This section details its core mechanisms and real-world applications.

01

Core Upgrade Mechanism

The UUPS pattern relies on a proxy contract that delegates all function calls to a separate logic contract via delegatecall. The proxy stores the logic contract's address, which can be updated by an authorized account, instantly upgrading the system's behavior without migrating state.

  • delegatecall: Executes code from the logic contract in the context of the proxy's storage.
  • Upgrade Function: A function (e.g., upgradeTo(address newImplementation)) in the logic contract itself that updates the proxy's stored address.
  • Initialization: Uses an initializer function instead of a constructor to set up the logic contract's initial state.
02

Comparison with Transparent Proxy

UUPS is often compared to the Transparent Proxy Pattern. The key difference is the location of the upgrade logic.

  • Transparent Proxy: Upgrade logic is in the proxy contract. It uses a ProxyAdmin to manage upgrades, preventing function selector clashes between the proxy and logic.
  • UUPS: Upgrade logic is in the logic (implementation) contract. This makes the proxy contract simpler and reduces gas costs for users, as the proxy doesn't need to check msg.sender for every call.

The trade-off is that UUPS requires upgradeability to be explicitly designed into the logic contract, which can be omitted, making it permanently immutable.

03

Security & Initialization Risks

While gas-efficient, UUPS introduces specific security considerations that developers must address.

  • Uninitialized Implementation: A UUPS logic contract must be initialized after deployment. If the initializer function is not called, or is callable by anyone, it can lead to takeover vulnerabilities.
  • Accidental Immutability: If the upgradeTo function is omitted from the final, deployed logic contract, the system becomes permanently frozen and un-upgradeable.
  • Implementation Self-Destruct: Since upgrade logic resides in the implementation, a bug or malicious upgrade could include a selfdestruct call, destroying the logic and bricking all associated proxies.
05

Gas Efficiency Advantage

A primary advantage of UUPS over Transparent Proxies is reduced gas overhead for end-users.

  • No Proxy Admin Check: In a Transparent Proxy, every call checks if msg.sender is the admin to decide whether to delegate or not. UUPS proxies skip this check, saving ~2,700 gas per regular user call.
  • Smaller Proxy Footprint: The UUPS proxy contract is simpler, costing less to deploy. The trade-off is slightly higher deployment cost for the logic contract, which contains the upgrade logic. This makes UUPS ideal for functions called frequently by users, such as token transfers or swaps.
06

Deployment & Tooling

Deploying and managing UUPS upgradeable contracts requires specific tools and workflows to ensure safety.

  • Upgrade Plugins: Tools like OpenZeppelin's Upgrades Plugin for Hardhat/Foundry automate the deployment of proxies, manage implementation addresses, and validate upgrades for storage layout compatibility.
  • Storage Layout: Developers must preserve the order and types of state variables in the logic contract across upgrades. Changing this layout corrupts stored data.
  • Testing: Requires testing both the initial deployment and upgrade scenarios, including the initialization and authorization of the upgradeTo function.
CLARIFYING THE PROXY STANDARD

Common Misconceptions About UUPS

The Universal Upgradeable Proxy Standard (UUPS) is a powerful pattern for smart contract upgradeability, but it is often misunderstood. This section addresses the most frequent points of confusion regarding its security, implementation, and comparison to other standards.

No, UUPS is not inherently less secure than the Transparent Proxy Pattern; the security model is simply different and shifts more responsibility to the implementation contract. In the Transparent Proxy Pattern, upgrade logic is in the proxy itself, managed by an admin address. In UUPS, the upgrade logic is part of the implementation contract's code. This means a flawed upgrade function in a UUPS implementation can lead to the contract being permanently frozen or self-destructed if not designed correctly. However, a well-audited UUPS contract with proper access controls is equally secure and is often preferred for its gas efficiency, as it avoids the proxy's overhead for regular users.

Key Security Consideration: The implementation contract in UUPS must be upgradeable itself, and its upgradeTo function must be protected (e.g., by an onlyOwner modifier) to prevent unauthorized upgrades.

UPGRADEABLE CONTRACTS

Technical Deep Dive

The Universal Upgradeable Proxy Standard (UUPS) is a sophisticated Ethereum smart contract pattern that separates a contract's logic from its storage, enabling seamless upgrades without data migration. This section dissects its core mechanisms, security considerations, and implementation details.

The Universal Upgradeable Proxy Standard (UUPS) is a smart contract upgrade pattern where a proxy contract delegates all function calls to a separate logic contract using the delegatecall opcode, allowing the logic to be upgraded while preserving the proxy's state and address. The proxy contract stores the address of the current logic implementation. When a user calls the proxy, it uses a delegatecall to execute the code from the logic contract within the proxy's own storage context. This separation means you can deploy a new version of the logic contract and simply update the pointer in the proxy, instantly upgrading all users' interactions without moving their data.

Key Mechanism: delegatecall executes code from another contract but uses the storage of the calling (proxy) contract. This is the core enabler of state preservation during upgrades.

UPGRADEABLE PROXIES

Frequently Asked Questions (FAQ)

Essential questions and answers about the Universal Upgradeable Proxy Standard (UUPS), a critical pattern for building upgradeable smart contracts on Ethereum and other EVM-compatible blockchains.

The Universal Upgradeable Proxy Standard (UUPS) is a design pattern for smart contracts that separates a contract's logic from its storage, enabling the logic to be upgraded while preserving the contract's state and address. It works by using a proxy contract that delegates all function calls to a separate logic contract via a low-level delegatecall. The proxy stores the address of the logic contract, and only this address can be updated by an authorized party, effectively upgrading the contract's behavior without migrating assets or changing the user-facing contract address.

Key Mechanism:

  • The proxy's fallback() or receive() function uses delegatecall to execute code in the logic contract's context.
  • The logic contract's address is stored in a specific storage slot (e.g., _IMPLEMENTATION_SLOT) to prevent collisions.
  • The upgrade logic itself can be embedded in the logic contract, following the UUPS pattern, rather than in a separate admin contract.
ENQUIRY

Get In Touch
today.

Our experts will offer a free quote and a 30min call to discuss your project.

NDA Protected
24h Response
Directly to Engineering Team
10+
Protocols Shipped
$20M+
TVL Overall
NDA Protected Directly to Engineering Team