# How to test upgradeability for proxies

**URL:** <https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436>\
**Category:** Upgrades\
**Created:** [December 1, 2022, 8:44am UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436 "2022-12-01T08:44:14Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![novaknole](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/novaknole/32/3796_2.png) [@novaknole](https://forum.openzeppelin.com/u/novaknole)\
**Post date:** [December 1, 2022, 8:44am UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436/1 "2022-12-01T08:44:14Z")

</div>

My contract previously looked like this;

```auto
contract MyContract is UUPSUpgradeable, ERC20Upgradeable {

   function initialize(...) initializer {
      // ..... some code
   }
}

```

and my tests were fine. I was deploying `MyContract` with `.deploy()` function in my hardhat ethers and that was it. Now, I decided to bring extra safety in all my contracts, so most of them are upgradeable, which means in 99% of them, I had to add the following:

```auto
constructor() {
   _disableInitializers();
}

```

Now, Due to this, every test that I had was failing because, they can't call `initialize` anymore since constructor disables it. NOTE that I was deploying the contracts directly.

Due to this change, I got 1 option now:

- Update every test in a way that I don't use `deploy`, but I use `deployProxy` from OZ (This will ensure that in the end proxy will be deployed and initializers won't be disabled on the proxy, but on the implementation(which I don't care).

Problem with this is that tests pretty much slow down 2x times.(It now needs to deploy 2 contracts instead of 1). Are there any other ways you can think of which doesn't slow down tests, but also doesn't require too much work ?

---

<div class="post-metadata">

**Author:** ![ericglau](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/ericglau/32/15149_2.png) [@ericglau](https://forum.openzeppelin.com/u/ericglau)\
**Post date:** [December 1, 2022, 6:30pm UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436/2 "2022-12-01T18:30:54Z")

</div>

If an implementation was written to only be used with a proxy, then it seems reasonable to always use `deployProxy` to test with a proxy rather than testing the implementation directly. That would help ensure the tested behaviour is as close as possible to what it would be on a real network. I don't see a way to avoid deploying proxies in this case.

---

<div class="post-metadata">

**Author:** ![novaknole](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/novaknole/32/3796_2.png) [@novaknole](https://forum.openzeppelin.com/u/novaknole)\
**Post date:** [December 1, 2022, 7:17pm UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436/3 "2022-12-01T19:17:25Z")

</div>

Thanks for the answer, but implementation was not written only to be used with proxy, but the problem somehow is `disableInitializers` being in the constructor which then causes `initialize` to not be called !

---

<div class="post-metadata">

**Author:** ![ericglau](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/ericglau/32/15149_2.png) [@ericglau](https://forum.openzeppelin.com/u/ericglau)\
**Post date:** [December 1, 2022, 7:57pm UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436/4 "2022-12-01T19:57:29Z")

</div>

`disableInitializers` being in the constructor which then causes `initialize` to not be called is the intended effect. Having this in the constructor means the implementation is not meant to be usable directly, and therefore only usable with a proxy.

---

<div class="post-metadata">

**Author:** ![maxareo](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/maxareo/32/11606_2.png) [@maxareo](https://forum.openzeppelin.com/u/maxareo)\
**Post date:** [December 2, 2022, 6:55am UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436/5 "2022-12-02T06:55:41Z")

</div>

Does this imply having `_disableInitializers();` in the constructor is a new standard way or at least recommended way of using `UUPSUpgradeable` compliant logic contract?

---

<div class="post-metadata">

**Author:** ![novaknole](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/novaknole/32/3796_2.png) [@novaknole](https://forum.openzeppelin.com/u/novaknole)\
**Post date:** [December 2, 2022, 8:10am UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436/6 "2022-12-02T08:10:49Z")

</div>

@ericglau I also am curious how it would actually work.

The OZ already fixed the problem by adding `onlyProxy` modifier to upgrade functions. This means nobody can call `upgradeToAndCall` on the implementation. What other risks do you see if you leave implementation uninitialized?

---

<div class="post-metadata">

**Author:** ![ericglau](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/ericglau/32/15149_2.png) [@ericglau](https://forum.openzeppelin.com/u/ericglau)\
**Post date:** [December 2, 2022, 2:19pm UTC](https://forum.openzeppelin.com/t/how-to-test-upgradeability-for-proxies/33436/7 "2022-12-02T14:19:43Z")

</div>

> Does this imply having `_disableInitializers();` in the constructor is a new standard way or at least recommended way of using `UUPSUpgradeable` compliant logic contract?

Yes, this is recommended as described in [https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable](https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable)

> The OZ already fixed the problem by adding `onlyProxy` modifier to upgrade functions. This means nobody can call `upgradeToAndCall` on the implementation. What other risks do you see if you leave implementation uninitialized?

You are correct that the [previous UUPS vulnerability](https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680) was fixed by restricting the upgrade functions to `onlyProxy`, but disabling initializers is still recommended as a best practice to provide an extra layer of protection against these types of attacks.
