Proxy Pattern
In the proxy pattern, we have two smart contracts: proxy contract and implementation contract.
The proxy contract acts as a proxy, delegating all calls to the contract it is the proxy for. In this context, it will also be referred to as the Storage Layer. The implementation contract is the contract that you want to upgrade or patch. This is the contract that the Proxy contract will be acting as a proxy for. In this context, it is the Logic Layer.
The Proxy contract stores the address of the implementation contract or logic layer as a state variable. Unlike normal contracts, the user doesn't actually send calls directly to the logic layer, which is your original contract. Instead, all calls go through the proxy and this proxy delegates the calls to this logic layer — the implementation contract at the address that the proxy has stored — returning any data it received from the logic layer to the caller or reverting for errors.
The key thing to note here is that the proxy calls the logic contract through the delegatecall function. Therefore, it is the proxy contract that actually stores state variables, i.e. it is the storage layer. It is like you only borrow the logic from the implementation contract (logic layer) and execute it in the proxy's context affecting the proxy's state variables in storage.
Openzeppelin provides a library to create an upgradeable proxy pattern called TransparentUpgradeableProxy
.
Creating the Proxy and Proxy Admin Implicitly
Below are two samples of the creation of a TransparentUpgradeableProxy, one in Hardhat using @openzeppelin/hardhat-upgrades
and the other one in Truffle using @openzeppelin/truffle-upgrades
When you deploy, the package behind the scenes creates a ProxyAdmin
and a TransparentUpgradeableProxy
as well.
In the Hardhat configuration, you just need to verify the TransparentUpgradeableProxy. The Hardhat utility will also verify the ProxyAdmin and the logic smart contract, Box. Unfortunately, in the Truffle configuration, we can’t do this. We can only verify the logic smart contract.
Creating the Proxy and Proxy Admin Explicitly
We can create the proxy and proxy admin explicitly by inheriting TransparentUpgradeableProxy
in @openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol
and ProxyAdmin
in @openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol.
Below are two samples of creating the proxy and proxy admin explicitly.
Unfortunately, MyProxy
can’t be verified using the command line in Hardhat or Truffle, but we can flatten it and then verify it on FTMScan directly.