Usage of UUPS

I can't understand how to implement UUPS proxies. Should I create another proxy contract for this contract:

// 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");

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

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

    function _authorizeUpgrade(address) internal override onlyOwner {}

Or is this enough? If it is, how can I upgrade this contract?

Hi, I think you can have a look at this tutorial:

1 Like

Thank you @Skyge! I read it. I got the basics things. But I don't understand this: Let's say we upgraded our contract. Then what happens to the balances in v1? Do I need a Proxy contract and my state (in this case, balances) in that Proxy contract or something else? I can't get it

still I need an answer for this question.

Hello @0fatih

UUPS, just like all upgradeable proxy pattern rely on two things:

  • A proxy
  • An implementation

The code you shared corresponds to the code for an implementation with UUPS support. This means that you'll need a UUPS proxy pointing to that implementation.

The proxy is what users will interact with, and where all the state is stored. The implementation is just here to tell the proxy how to behave.

If you ever do an upgrade, you'll need to create a new implementation (that codes for a new behavior) and tell the proxy to use that instead. There is no new proxy. You keep the same proxy, at the same address, with the same data in storage. You just "upgrade" its implementation.

1 Like