Proxy Pattern
Learn how to deploy smart contracts wallets using a proxy pattern to save gas fees and simplify user experience.
Deploying smart contracts for all users
A contract account will have a lot of code needed to implement complex use cases for an application. A naive approach to using account abstraction would be to deploy the same smart contract for all your users. But this is a mistake for a few reasons.
- It's more expensive for user's to deploy big contracts with a lot of complexity.
- You'll be deploying the same contract over and over again but just initialized in different ways.
- User's will need to deploy a whole new account address every time your application has a contract update.
Save gas with a Proxy
A Proxy
is the solution to these problems. The account is split into two separate contracts, the Proxy
and the Implementation
. The first is a light weight contract that receives a call and delegates it to the second contract which has the logic.
A user can always switch the Implementation
used by the Proxy
. But the Proxy
address will always remain consistent. This is what allows applications to have upgradable accounts for their users.
Lastly, the Proxy
is also a lot smaller in size compared to the Implementation
which means deployment cost for users is minimal.
Deploying a Proxy
Fortunately, there are already great packages available for building with proxies. Using an ERC1967Proxy from OpenZeppelin we can deploy one with less than 10 lines of code.
pragma solidity 0.8.9;
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
contract AccountProxy is ERC1967Proxy {
constructor(address logic, bytes memory data) ERC1967Proxy(logic, data) {}
}
The constructor takes two arguments:
logic
: The address of theImplementation
contract.data
: Typically encoded instructions to call aninitialize
function on theImplementation
. This is used to setup storage on theProxy
.
Building the implementation
Although there are several mechanisms for building proxies and implementations, the current recommendation is to use UUPS Proxies. In this pattern, the upgrade is handled by the Implementation
rather than in the Proxy
. Less code in the Proxy
means a smaller contract size and cheaper deployment!
Additional resources
A proxy pattern is core to building account abstraction that is fit for production. This was a quick summary, but we recommend developers also checkout the following links for a deeper dive:
Updated about 1 month ago