UUPS Proxy Example
Let us dive into the UUPS (Universal Upgradeable Proxy Standard) proxy pattern with a practical example. This will allow us to create upgradeable smart contracts while minimizing gas costs and maintaining a clear separation between your contract logic and storage.
What is UUPS Proxy?
UUPS is an upgradeable proxy pattern that leverages a single implementation contract and a proxy to delegate calls to the implementation. The proxy holds the state, while the implementation contract contains the logic. UUPS allows the implementation to be upgraded through a function call on the proxy itself, reducing gas costs compared to other patterns like Transparent Proxies.
Key Components
Proxy Contract: This is the contract that users interact with. It holds the state and delegates calls to the implementation.
Implementation Contract: This contains the actual logic of the contract. It can be upgraded by deploying a new version and pointing the proxy to the new implementation.
Admin Functionality: The proxy needs to have a way to authorize upgrades.
UUPS Proxy Implementation
Step 1: Set Up Your Project
First, make sure you have a working environment with Node.js, Hardhat, and OpenZeppelin:
Step 2: Create the Implementation Contract
Create a file named MyContract.sol
in the contracts
folder:
Explanation:
The contract uses
UUPSUpgradeable
for the upgrade mechanism.The
initialize
function sets the initial state.The
_authorizeUpgrade
function restricts who can upgrade the contract to the owner.
Step 4: Create the Proxy Contract
With UUPS, the proxy is automatically handled by OpenZeppelin, so you don't need to create a separate proxy contract manually. Instead, you will deploy the implementation contract and interact with it via the proxy mechanism.
Step 5: Write the Deployment Script
In the scripts
folder, create a file named deploy.js
:
Step 6: Deploy the Contract
Run the deployment script:
Step 7: Upgrade the Contract
Let’s say you want to add new functionality in the future. Create a new version of your contract. Create MyContractV2.sol
:
Explanation:
This version extends
MyContract
and adds a new functionincrementValue
.
Step 8: Deploy the New Implementation
In the scripts
folder, create a new script named upgrade.js
:
Step 9: Upgrade Your Contract
Run the upgrade script:
Step 10: Interact with the Upgraded Contract
You can now call the new incrementValue
function on the upgraded contract. Create a script named interact.js
:
Run the interaction script:
You’ve successfully implemented a UUPS proxy pattern for upgradeable contracts! Here’s a recap of what we did:
Created an implementation contract with upgradeable functionality.
Deployed the contract to the network.
Added a new version of the contract with additional features.
Upgraded the contract to the new implementation.
Interacted with the upgraded contract to demonstrate its new capabilities.
This UUPS pattern provides a flexible way to maintain and upgrade your smart contracts while optimizing for gas costs, making it an ideal choice for modern Ethereum development.
Last updated