Which UUPSUpgradeable contract should I use on the implementation side: the contracts-upgradable version or the plain one?

When describing proxies the docs point to “vanila” UUPSUpgradeable contract here. But there’s also a contracts-upgradable version of UUPSUpgradeable here.

What are those different versions are for? Which one should I use? Or rather what are decision points towards different versions?

The recommended practice is to only use @openzeppelin/contracts-upgradeable for writing upgradeable contracts. So this applies to UUPSUpgradeable as well.

For an example, go to https://wizard.openzeppelin.com/ and select UUPS under the Upgradeability section.


Some additional context: contracts-upgradeable are transpiled from contracts to include the recommended practices for upgradeable contracts, which include initializers and storage gaps. In other words, contracts are the source of contracts-upgradeable.

In the case of UUPSUpgradeable, while the one in contracts should be safe to use because it does not use constructors or storage slots, we still recommend to just use contracts-upgradeable for consistency. The one in contracts-upgradeable also contains a storage gap, so that in a future version if any additional state variables are needed, those can use up some of the storage gap without affecting the storage layout of the rest of your implementation.

2 Likes

Cool! Thanks for the very comprehensive answer!

1 Like

Thanks! This is the explanation that I was missing from the docs (It should be added there)