Upgradeable Contracts

Why Use Upgradeable Smart Contracts?

When developing smart contracts, upgrades are sometimes necessary. Once deployed, a smart contract is immutable, meaning it can’t be changed directly. If there’s a bug or you want to add new features, redeploying the entire contract is impractical because:

  1. User data: Redeplying would erase all data stored in the contract.

  2. User experience: Users would need to switch to the new contract address, which can be confusing.

  3. Gas efficiency: Redeploying can be costly for both developers and users.

Instead, upgradeable smart contracts separate storage (user data) from logic (contract functions). When you want to upgrade, you just switch out the logic, while keeping the storage the same. This is done through proxy patterns.

What is a Proxy Pattern?

In a proxy pattern, we have:

  1. Proxy Contract: The contract that users interact with. This contract holds the user’s data and “delegates” or “forwards” calls to the logic contract.

  2. Implementation Contract: Also known as the “logic” or “upgrade” contract. This is where the business logic lives, and it can be changed without affecting user data.

  3. Admin Account: For upgradeable contracts, an admin account (often the contract owner) controls upgrades. Only the admin can change the logic contract address to a new one.

When users interact with a function, the proxy forwards their requests to the implementation (logic) contract, allowing the contract to be upgraded without affecting the data or address users interact with.

The Two Main Upgradeable Patterns: Transparent Proxy and UUPS Proxy

Now that we know the basics of proxy patterns, let’s dive into the two main patterns: Transparent Proxy and UUPS Proxy.

1. Transparent Proxy Pattern

The Transparent Proxy Pattern is one of the original patterns used for upgradeable contracts. It’s simple but reliable and widely adopted.

How Transparent Proxy Works

  1. User and Admin Access Separation:

    • Users: Regular users send their function calls through the proxy, which forwards them to the logic contract. Users don’t need to worry about how the forwarding works; they interact with the proxy as if it were the logic contract.

    • Admin: The admin account, often the contract’s owner, has special permissions. It’s the only account that can trigger upgrades by updating the address of the logic contract.

  2. Storage Separation:

    • The proxy holds all user data, while the logic contract is stateless (doesn’t store data directly). When upgrading, the proxy simply points to a new logic contract address, and the stored data remains intact.

  3. Implementation:

    • Only the admin can access upgrade functions, which means there’s a clear separation between users who interact with regular functions and the admin, who manages upgrades. This is enforced by adding checks in the proxy contract.

Advantages of Transparent Proxy

  • Security: Since only the admin can upgrade the contract, it’s easy to prevent unauthorized upgrades.

  • User Simplicity: Users only interact with the proxy and are unaware of the underlying logic changes.

Disadvantages of Transparent Proxy

  • Higher Gas Costs: The extra checks (for user vs. admin access) make it slightly more expensive in gas compared to other methods.

  • Complexity in Design: The proxy contract has to manage both user interactions and admin upgrade logic, adding complexity.

2. UUPS (Universal Upgradeable Proxy Standard) Proxy Pattern

The UUPS Proxy Pattern is a more recent and gas-efficient approach, designed to simplify upgradeable contracts. Instead of having the proxy manage upgrade logic, the implementation (logic) contract itself manages its upgrades.

How UUPS Proxy Works

  1. Proxy Contract:

    • The proxy contract only stores data. It forwards function calls to the logic contract but doesn’t include any upgrade logic.

  2. Implementation Contract with Upgrade Logic:

    • The logic contract includes the upgrade functions, specifically _authorizeUpgrade, which allows only authorized users to change the implementation address.

    • This function is usually restricted to an admin account, so only the admin can authorize upgrades.

    • When an upgrade is needed, the proxy points to a new version of the logic contract by calling upgradeTo in the current implementation contract.

  3. Reduced Gas Costs:

    • By keeping upgrade logic in the implementation rather than the proxy, UUPS saves on gas costs by simplifying the proxy.

Advantages of UUPS Proxy

  • Lower Gas Usage: UUPS is more efficient because it doesn’t include upgrade functions in the proxy, which reduces costs.

  • Flexible Design: All upgrade logic is in the logic contract, meaning that only one function _authorizeUpgrade manages upgrades.

Disadvantages of UUPS Proxy

  • Security Concerns: Because the upgrade function is in the logic contract, the function must be secured carefully to prevent unauthorized upgrades.

  • Newer Approach: Since UUPS is more recent, it may not be as widely understood, which could lead to issues if misused.

Comparison of Transparent Proxy vs. UUPS Proxy

Feature
Transparent Proxy
UUPS Proxy

Where Upgrade Logic Is

Proxy Contract

Implementation Contract

Admin/User Separation

Yes, enforced by proxy

Handled in _authorizeUpgrade function

Gas Costs

Higher due to additional checks

Lower, since upgrade logic is in logic contract

Complexity

More complex due to proxy role

Simpler proxy; logic contract manages upgrades

Adoption

Widely adopted

Gaining popularity, supported by OpenZeppelin

Security Model

Clear admin/user distinction

Requires careful authorization handling

When to Use Each Pattern

  • Use Transparent Proxy if: Security and access separation are a priority, or you’re comfortable with a slightly more complex proxy design.

  • Use UUPS Proxy if: You need a gas-efficient solution, are working with the latest standards, and have a trusted admin setup for managing upgrades.

Both the Transparent Proxy and UUPS Proxy patterns are valuable for creating upgradeable contracts. Understanding the differences helps to choose the best pattern for the project’s security, cost, and complexity needs.

Last updated