Deploying Upgradeable Contracts using UUPS with Foundry
UUPS (Universal Upgradeable Proxy Standard)
UUPS is an upgradeable proxy pattern that addresses some limitations of the transparent proxy pattern. Key features include:
- Upgrade Logic in Implementation: The upgrade functionality is placed in the implementation contract rather than the proxy.
- Gas Efficiency: More gas-efficient for users as there's no need to check the caller's identity on every function call.
- Smaller Proxy Contract: The proxy contract is simpler and smaller, potentially reducing deployment costs.
Comparison of Proxy Patterns
-
UUPS vs. Transparent Proxy:
- UUPS places upgrade logic in the implementation, while transparent proxy keeps it in the proxy contract.
- UUPS is more gas-efficient for regular function calls.
- Transparent proxy has a larger proxy contract but simpler implementation contracts.
-
UUPS vs. Regular Upgradeable Proxy:
- UUPS provides better security against accidental contract locking.
- Regular upgradeable proxies are simpler but may be more prone to errors during upgrades.
-
Common Features:
- All patterns allow upgrading contract logic without changing the contract address.
- They all use delegate calls to forward function calls to the implementation contract.
UUPS is often preferred for its balance of security, gas efficiency, and flexibility. In this tutorial, we'll implement and deploy upgradeable contracts using UUPS on Conflux eSpace.
Project Setup
- Create a new Foundry project:
forge init uups-proxy-foundry-demo
cd uups-proxy-foundry-demo
- Install OpenZeppelin contracts:
forge install OpenZeppelin/openzeppelin-contracts
forge install OpenZeppelin/openzeppelin-contracts-upgradeable
- Configure Foundry
Update your foundry.toml
:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.24"
remappings = [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/"
]