# UUPS Proxies: Tutorial (Solidity + JavaScript)

**URL:** <https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786>\
**Category:** Guides and Tutorials\
**Created:** [May 4, 2021, 8:34pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786 "2021-05-04T20:34:01Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [May 4, 2021, 8:34pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/1 "2021-05-04T20:34:02Z")

</div>

# UUPS Proxies: A Tutorial

In this tutorial we will deploy an upgradeable contract using the UUPS proxy pattern. We assume some familiarity with Ethereum upgradeable proxies.

## Introduction to UUPS

The original proxies included in OpenZeppelin followed the [Transparent Proxy Pattern](https://blog.openzeppelin.com/the-transparent-proxy-pattern/). While this pattern is still provided, our recommendation is now shifting towards UUPS proxies, which are both lightweight and versatile. The name UUPS comes from [EIP1822](https://eips.ethereum.org/EIPS/eip-1822), which first documented the pattern.

While both of these share the same interface for upgrades, in UUPS proxies the upgrade is handled by the implementation, and can eventually be removed. Transparent proxies, on the other hand, include the upgrade and admin logic in the proxy itself. This means [`TransparentUpgradeableProxy`](https://docs.openzeppelin.com/contracts/4.x/api/proxy#TransparentUpgradeableProxy) is more expensive to deploy than what is possible with UUPS proxies.

UUPS proxies are implemented using an [`ERC1967Proxy`](https://docs.openzeppelin.com/contracts/4.x/api/proxy#ERC1967Proxy). Note that this proxy is not by itself upgradeable. It is the role of the implementation to include, alongside the contract's logic, all the code necessary to update the implementation's address that is stored at a specific slot in the proxy's storage space. This is where the [`UUPSUpgradeable`](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable) contract comes in. Inheriting from it (and overriding the [`_authorizeUpgrade`](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable-_authorizeUpgrade-address-) function with the relevant access control mechanism) will turn your contract into a UUPS compliant implementation.

Let's delve into the details.

## OpenZeppelin Tooling

We will use OpenZeppelin tooling to easily and securely deploy an upgradeable contract using the UUPS proxy pattern.

1. We will write our contract source code using [OpenZeppelin Upgradeable Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable).
2. We will deploy this contract behind a proxy using [OpenZeppelin Upgrades Plugins](https://github.com/OpenZeppelin/openzeppelin-upgrades), which additionally provides security checks to make sure we respect some [basic rules of upgradeability](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable).

## Project Setup

In a new directory, start an npm project and install Hardhat along with the OpenZeppelin tools we mentioned in the previous section:

```auto
npm init -y
npm install hardhat @nomiclabs/hardhat-ethers ethers
npm install @openzeppelin/contracts-upgradeable @openzeppelin/hardhat-upgrades

```

Create the Hardhat config set to use Solidity 0.8.2 and the plugins we've installed:

```javascript
// hardhat.config.js

require('@nomiclabs/hardhat-ethers');
require('@openzeppelin/hardhat-upgrades');

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.3",
};

```

> Solidity 0.8.2 is technically supported, but the Windows build of the compiler currently has an unresolved issue, so 0.8.3 is recommended.

## Writing the Contract

We will start with a basic ERC20 token with some initial supply minted for the deployer. We will see below that this contract is not yet ready for UUPS deployment.

```solidity
// contracts/MyTokenV1.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";

contract MyTokenV1 is Initializable, ERC20Upgradeable {
    function initialize() initializer public {
      __ERC20_init("MyToken", "MTK");

      _mint(msg.sender, 1000 * 10 ** decimals());
    }

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() initializer {}
}

```

Because this is a upgradeable contact we do not initialize the contract state in the constructor, and instead we have an initializer function decorated with the modifier `initializer`, provided by `Initializable`. Because of this requirement, we also made sure to use the Upgradeable variant of OpenZeppelin Contracts, which similarly provides contracts with initializer functions such as `__ERC20_init`, all following the same naming convention.

## Upgradeable Deployment

We can now write a test and start by deploying this contract normally:

```js
// test/MyToken.test.js

const { ethers, upgrades } = require('hardhat');

describe('MyToken', function () {
  it('deploys', async function () {
    const MyTokenV1 = await ethers.getContractFactory('MyTokenV1');
    await MyTokenV1.deploy();
  });
});

```

Run the test using `npx hardhat test`, and you should see it run successfully.

```auto
  MyToken
    ✓ deploys (923ms)

```

In order to make this an upgradeable deployment, we need to use the function `deployProxy` from the Upgrades plugin.

```javascript
    await upgrades.deployProxy(MyTokenV1); // instead of MyTokenV1.deploy()

```

This function will be doing several things behind the scenes. The contract will be checked for [unsafe patterns](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable) that shouldn't be used in an upgradeable deployment, such as using the `selfdestruct` operation. If these checks pass, it will then deploy the implementation contract, and then deploy a proxy connected to that implementation. The result is a contract that can then be upgraded using `upgrades.upgradeProxy` as we will see later.

The proxy we just deployed was not a UUPS proxy, however, as the current default is still Transparent Proxies. In order to use UUPS we have to manually specify so with the option `kind: 'uups'`.

```javascript
    await upgrades.deployProxy(MyTokenV1, { kind: 'uups' });

```

If we try to run this test now, we will actually see it fail with this error.

```plaintext
contracts/MyTokenV1.sol:7: Implementation is missing a public `upgradeTo(address)` function
    Inherit UUPSUpgradeable to include this function in your contract
    @openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol
    https://zpl.in/upgrades/error-008

```

This is because, as we mentioned at the beginning of the tutorial, UUPS proxies do not contain an upgrade mechanism on the proxy, and it has to be included in the implementation. We can add this mechanism by inheriting `UUPSUpgradeable`, and this will also require that we implement an authorization function to define who should be allowed to upgrade the contract. For the example we will use `Ownable`.

```solidity
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
 
contract MyTokenV1 is Initializable, ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable {
    function initialize() initializer public {
      __ERC20_init("MyToken", "MTK");
      __Ownable_init();
      __UUPSUpgradeable_init();

```

To authorize the owner to upgrade the contract we implement `_authorizeUpgrade` with the `onlyOwner` modifier.

```solidity
    function _authorizeUpgrade(address) internal override onlyOwner {}

```

> **Click here to see the full Solidity code.**
>
> ```solidity
> // contract/MyTokenV1.sol
> 
> // SPDX-License-Identifier: MIT
> pragma solidity ^0.8.0;
> 
> import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
> import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
> import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
> import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
> 
> contract MyTokenV1 is Initializable, ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable {
> function initialize() initializer public {
> __ERC20_init("MyToken", "MTK");
> __Ownable_init();
> __UUPSUpgradeable_init();
> 
> _mint(msg.sender, 1000 * 10 ** decimals());
> }
> 
> /// @custom:oz-upgrades-unsafe-allow constructor
> constructor() initializer {}
> 
> function _authorizeUpgrade(address) internal override onlyOwner {}
> }
> 
> ```

Now that the contract is done we can run our test to deploy a UUPS proxy.

> **Click here to see the full test code.**
>
> ```javascript
> // test/MyToken.test.js
> 
> const { ethers, upgrades } = require('hardhat');
> 
> describe('MyToken', function () {
> it('deploys', async function () {
> const MyTokenV1 = await ethers.getContractFactory('MyTokenV1');
> await upgrades.deployProxy(MyTokenV1, { kind: 'uups' });
> });
> });
> 
> ```

Once we have a new version of the contract code and we want to upgrade a proxy, we can use `upgrades.upgradeProxy`. It's no longer necessary to specify `kind: 'uups'` since it is now inferred from the proxy address.

```javascript
await upgrades.upgradeProxy(proxyAddress, MyTokenV2);

```

## More Resources

You can find an updated list of resources related to upgradeability in the [Upgrades](https://docs.openzeppelin.com/openzeppelin/upgrades) page of the documentation.

---

<div class="post-metadata">

**Author:** ![phuson](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/phuson/32/4153_2.png) [@phuson](https://forum.openzeppelin.com/u/phuson)\
**Post date:** [July 5, 2021, 7:18am UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/2 "2021-07-05T07:18:22Z")

</div>

Thanks for the tutorial!

Quick question, is there a tutorial on how to verify the contract code on Etherscan/Polyscan for the deployed contracts?

---

<div class="post-metadata">

**Author:** ![Skyge](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/skyge/32/343_2.png) [@Skyge](https://forum.openzeppelin.com/u/Skyge)\
**Post date:** [July 5, 2021, 7:51am UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/3 "2021-07-05T07:51:24Z")

</div>

Hi, welcome! 👋

I think you can have a look at this tutorial: [Verify smart contract inheriting from OpenZeppelin Contracts - General / Guides and Tutorials - OpenZeppelin Community](https://forum.openzeppelin.com/t/verify-smart-contract-inheriting-from-openzeppelin-contracts/4119)

As for Polyscan, I am not sure.

---

<div class="post-metadata">

**Author:** ![phuson](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/phuson/32/4153_2.png) [@phuson](https://forum.openzeppelin.com/u/phuson)\
**Post date:** [July 5, 2021, 4:32pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/4 "2021-07-05T16:32:10Z")

</div>

Thanks for the reply. I was able to verify my implementation contract (since I have the source code for that). However, as for the Proxy contract, I’m not sure how or what to retrieve so that I can flatten to submit to Etherscan/Polyscan for verification.

I tried flattening various files in the locally installed proxy folder ([https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/tree/master/contracts/proxy](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/tree/master/contracts/proxy)). Nothing seems to work or has the matching bytecode as the code that was deployed using the  
`await upgrades.deployProxy(ERCToken, { kind: 'uups' });` command.

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [July 5, 2021, 6:31pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/5 "2021-07-05T18:31:08Z")

</div>

Can you share the address of the proxy contract you’re trying to verify?

---

<div class="post-metadata">

**Author:** ![phuson](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/phuson/32/4153_2.png) [@phuson](https://forum.openzeppelin.com/u/phuson)\
**Post date:** [July 5, 2021, 6:57pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/6 "2021-07-05T18:57:31Z")

</div>

Here’s the address on Polygon Testnet: [https://mumbai.polygonscan.com/address/0xa4059faa4f829564fd08943ef1a1bd574286038f](https://mumbai.polygonscan.com/address/0xa4059faa4f829564fd08943ef1a1bd574286038f)

I tried the same thing on Rinkeby and it seems like the ERC1967Proxy contract source code is already verified on Rinkeby.

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [July 5, 2021, 10:59pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/7 "2021-07-05T22:59:56Z")

</div>

I’ve verified your contract now. We currently rely on manual verification once for each network (afterwards it’s cached by Etherscan/Polygonscan). The Solc JSON Input can be obtained by building the contracts in the repository ([https://github.com/OpenZeppelin/openzeppelin-upgrades](https://github.com/OpenZeppelin/openzeppelin-upgrades)) if anyone is interested to know.

Soon this should be automated.

---

<div class="post-metadata">

**Author:** ![phuson](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/phuson/32/4153_2.png) [@phuson](https://forum.openzeppelin.com/u/phuson)\
**Post date:** [July 6, 2021, 6:19am UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/8 "2021-07-06T06:19:05Z")

</div>

Thank you for verifying it on Mumbai testnet! Looking forward to see this get automated. 👍

---

<div class="post-metadata">

**Author:** ![shodan](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/shodan/32/7764_2.png) [@shodan](https://forum.openzeppelin.com/u/shodan)\
**Post date:** [July 21, 2021, 1:23pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/9 "2021-07-21T13:23:25Z")

</div>

Hi,  
Is there a way to kill upgradeability without using selfdestruct?. From '[https://docs.openzeppelin.com/contracts/4.x/api/proxy#transparent-vs-uups](https://docs.openzeppelin.com/contracts/4.x/api/proxy#transparent-vs-uups)' there is a clause that says "While both of these share the same interface for upgrades, in UUPS proxies the upgrade is handled by the implementation, and can eventually be **removed**." How can i permanently kill upgrade functionality? considering you cannot use selfdestruct.

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [July 21, 2021, 1:29pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/10 "2021-07-21T13:29:18Z")

</div>

What it means is that a subsequent implementation can omit the `upgradeTo` function, and this renders the UUPS proxy not upgradeable anymore.

This situation is not easily allowed by our `UUPSUpgradeable` contract as it will verify that upgradeability is preserved. But you can achieve it by first upgrading to a contract that contains a custom `upgradeTo` function (can be `ERC1967Upgrade._upgradeTo`), and then upgrading again to a contract that no longer has the `upgradeTo` function.

---

<div class="post-metadata">

**Author:** ![shodan](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/shodan/32/7764_2.png) [@shodan](https://forum.openzeppelin.com/u/shodan)\
**Post date:** [July 21, 2021, 7:10pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/11 "2021-07-21T19:10:43Z")

</div>

Thanks Frangio. 👍

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [July 21, 2021, 10:25pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/12 "2021-07-21T22:25:44Z")

</div>

Split this topic on July 21, 2021, 10:25pm UTC

2 posts were split to a new topic: [Deploy on Kovan fails while Ganache succeeds](https://forum.openzeppelin.com/t/deploy-on-kovan-fails-while-ganache-succeeds/12870)

---

<div class="post-metadata">

**Author:** ![David\_Hoang](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/david_hoang/32/8251_2.png) [@David\_Hoang](https://forum.openzeppelin.com/u/David_Hoang)\
**Post date:** [August 16, 2021, 7:30pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/13 "2021-08-16T19:30:33Z")

</div>

Hi, Thanks for the great tutorial!  
I tried to verify my ERC20 token contract that created with UUPS, but it did not work, I ran this command:  
npx hardhat verify --network rinkeby 0x6957a76BA2C12359E1Ea0F75Ec302F0c27ba4972  
Any ideas for this? Thanks!

---

<div class="post-metadata">

**Author:** ![18dew](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/18dew/32/8275_2.png) [@18dew](https://forum.openzeppelin.com/u/18dew)\
**Post date:** [August 16, 2021, 8:15pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/14 "2021-08-16T20:15:23Z")

</div>

You are verifying the proxy addess u need to verify the implementation address and on etherscan u need to point proxy address to implementation addess once verification of implementation of address is done

---

<div class="post-metadata">

**Author:** ![David\_Hoang](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/david_hoang/32/8251_2.png) [@David\_Hoang](https://forum.openzeppelin.com/u/David_Hoang)\
**Post date:** [August 17, 2021, 6:21am UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/15 "2021-08-17T06:21:24Z")

</div>

@18dew Thanks, it works!  
Quick question, with UUPS pattern, let's say I have Contract1, and then Contract2 is Contract1  
, and then Contract3 is Contract1. As I understand Contract3 must be declared all the variables from Contract2, so now we are at Contract3 but there are some unused variables in Contract2 we must declare in Contract3. Is that a problem? and is there a solution for that?

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [August 18, 2021, 7:46pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/16 "2021-08-18T19:46:31Z")

</div>

@David_Hoang Can you create a new post and share some examples of code to describe this situation?

---

<div class="post-metadata">

**Author:** ![David\_Hoang](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/david_hoang/32/8251_2.png) [@David\_Hoang](https://forum.openzeppelin.com/u/David_Hoang)\
**Post date:** [August 19, 2021, 5:31am UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/17 "2021-08-19T05:31:36Z")

</div>

@frangio Yes, sure  
Since I'm not really sure if this is an issue yet so I think I reply here first

````auto
//SPDX-Lincense-Identifier: MIT
pragma solidity ^0.8.0;
contract Contract1 {
	uint ct1data;

}

contract Contract2 is Contract1{
	uint ct2data;
}

//and now I dont wanna use ct2data variable so new version:

contract Contract3 is Contract1 {
	// this one must be declared here otherwise error with storage layout
	// seems an issue?
	// as later on we may have so many ununsed variables?
	uint ct2data; 
	uint ct3data;

}```
````

---

<div class="post-metadata">

**Author:** ![hasanza](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/hasanza/32/8321_2.png) [@hasanza](https://forum.openzeppelin.com/u/hasanza)\
**Post date:** [August 19, 2021, 10:26am UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/18 "2021-08-19T10:26:22Z")

</div>

If I understand this correctly, the the proxy contract which is auto-generated is identical to the contract I write as far as the storage (variables etc.) is concerned?

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [August 19, 2021, 2:27pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/19 "2021-08-19T14:27:28Z")

</div>

I'm assuming this would initially deploy `Contract1`, then upgrade it to `Contract2`, then upgrade it to `Contract 3`.

Yes, in this scenario `Contract3` has to redeclare `ct2data`. Otherwise, `ct3data` would be allocated in the place where `ct2data` had been before, and this potentially corrupts the storage.

This can result in unused variables. You can add a comment saying that the variable is unused and only kept for storage compatibility.

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [August 19, 2021, 2:29pm UTC](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786/20 "2021-08-19T14:29:41Z")

</div>

The proxy contract is always the same for all contracts, and doesn't have storage variables in the Solidity code of the proxy.

But the proxy instance will share the storage _space_ with its implementation contract. As a consequence, all of the variables declared in the implementation contract are going to be stored in the proxy.

I illustrated this storage sharing in my workshop below:

[![](https://us1.discourse-cdn.com/flex022/uploads/zeppelin/original/3X/3/3/33960a22541e232c3691f5e335a7f126c38f0bc2.jpeg "Deploying More Efficient Upgradeable Contracts") ](https://www.youtube.com/watch?v=kWUDTZhxKZI)

[Next page](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786.md?page=2)
