How to create a Transparent Proxy

Hariharan Iyappan
Coinmonks
5 min readSep 11, 2022

--

The proxy pattern is a smart contract design pattern used to make the smart contracts upgradeable. Note that smart contracts by themselves are immutable and some advanced solidity foot work is necessary to make them upgradeable. For a detailed overview of smart contract upgradeability and explanation of the transparent proxy patten please read this earlier article. In this article we will focus on the actually deploying your contract with the transparent proxy pattern.

This Github repository has the code for this article feel free to save it for future use. You can clone it if you want to follow along without setting up from scratch.

Project Set Up

We will be using Hardhat for our Ethereum development workflow. I am using WSL2 in a windows machine for this walkthrough. You can adjust the steps slightly in case you are using a different set up. Let’s get started!

Run the following commands to create a directory and initialize it as a node project.

Install hardhat in this directory.

Initialize a hardhat type script project in the directory. Run the below command and choose “Create a TypeScript project” option. Go with the default parameters for rest of the prompts.

Install the Open zeppelin hardhat upgrades plugin which we’re going to use to easily deploy our proxy.

Also install the upgradeable contracts from Open zeppelin which is the upgradeable counterpart of Open zeppelin contracts.

Copy and paste the following into the hardhat.config.ts file. This will do the basic hardhat set up we require for this project.

Implementation contract to deploy with Transparent Proxy

Inside contracts folder create a folder for the implementation contract for which we’re going to deploy a transparent proxy.

In the contracts directory create a file named VersionAware.sol and copy paste the following code in it.

Here we create a basic skeleton of our implementation contracts so that we can easily see the version upgrades visibly after deployment and upgrade.

In the contracts/transparent directory create two files named TransparentProxyPatternV1.sol and TransparentProxyPatternV2.sol and copy paste the following code into it.

TransparentProxyPatternV1.sol

TransparentProxyPatternV2.sol

We have two implementation contracts version 1 and 2. Note that the structure of version 1 and 2 need not be same for upgrade to work. Note that both the contracts inherit from ERC1967UpgradeUpgradeable contract from the Open zeppelin upgradeable package. Read the earlier article linked in the top of this article to learn more about ERC1967 standard.

We have two implementation contracts version 1 and 2. Note that the structure of version 1 and 2 need not be same for upgrade to work. Note that both the contracts inherit from ERC1967UpgradeUpgradeable contract from the Open zeppelin upgradeable package. Read the earlier article linked in the top of this article to learn more about ERC1967 standard.

Here I attempt to explain a few advanced details of the the above contracts. Consider skipping it now and coming back later if you have difficulty understanding this on first read. Typical upgradeable contracts should not have a constructor because the constructor of the implementation contract can never be run in the context of the proxy contract. We have added a constructor here which is safe as it does not set to any of the storage variables. Leaving a contract without initializing it can pose a security threat. Calling the _disableInitializers method in the constructor makes the implementation contract not initializable which is much safer than leaving the implementation without a constructor and not initialized. Note that I have used initializer modifier in the initialize method in V1. This modifier makes sure that this initialize method is called only once, like solidity ensures for constructors. Also note that in V2 the modifier of the initialize method is reinitializer(2). Here 2 represents the version of the implementation contract. The reinitializer modifier has to be used instead of initializer because the proxy contract has already been initialized once in V1. There are more things and details to know about Initializer.sol contract which all upgradeable smart contracts should inherit. I will write more detailed article on it in future.

Now, run the following command to compile the smart contracts.

Transparent Proxy Deployment and Upgrade

First we will deploy version 1 with transparent proxy and then upgrade it to version 2. We will use a hardhat script to do this. Create a script named transparent.js in scripts folder and copy paste the following code in it.

We first deploy version 1 of the smart contract with proxy and proxy admin. The Open zeppelin upgrades deployProxy method takes care of all these for us. Once version 1 is deployed with proxy we call the getContractNameWithVersion function on the proxy. This method will return a string according to what we made this method return in version 1 of the contract. Then we proceed to upgrade this contract with the upgradeProxy method. After the upgrade is over we call the getContractNameWithVersion function again to see the change in the string returned. Let’s run the script and see the results. Use the following command to run the script.

You should see the following printed on your console.

Yay! the results are as expected. The implementation contract is successfully upgraded to version 2. This is how you deploy and upgrade future versions of your contract with the transparent proxy pattern however complicated your smart contract gets.

Thanks for reading.

Who am I?

I am a full stack blockchain developer, passionate about building a decentralized and potentially more inclusive future. Have a blockchain development need?

Get in touch: 📧 hariharan@alumni.iitm.ac.in

Github

New to trading? Try crypto trading bots or copy trading

--

--

Hariharan Iyappan
Coinmonks

Passionate techie | IITM 2020 | Software Engineer @PhonePe