2

I'm reading the OpenZeppelin documentation about upgradeable contracts, and I'm getting a bit confused with these modifiers:

  1. initializer
  2. onlyInitializing

I think I understand how initializer works. It's just a modifiers which checks that the upgradeable contract has not been already initialized, playing the role of a constructor. But the documentation later, states:

Note that the initializer modifier can only be called once even when using inheritance, so parent contracts should use the onlyInitializing modifier:

// contracts/MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

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

contract BaseContract is Initializable {
    uint256 public y;

    function initialize() public onlyInitializing {
        y = 42;
    }
}

contract MyContract is BaseContract {
    uint256 public x;

    function initialize(uint256 _x) public initializer {
        BaseContract.initialize(); // Do not forget this call!
        x = _x;
    }
}

My main doubts are the following:

  1. Does it means that if I expect my contract (BaseContract) to be
    inherited, I should use the initialize() function with
    onlyInitializing modifier?
  2. And when inheriting the BaseContract, in the child contract the initialize() function should use the
    initializer modifier?
  3. So, if I'm not expecting to inherit my BaseContract I could use the initialize() function with initializer modifier from the begining?

1 Answer 1

2

All of your points are correct.

The main problem stems from the fact that constructors can't be used. That's upgradeable contracts have to use regular functions to initialize them. But this should only be possible to be done once.

Since upgradeable contracts can have normal inheritance, there has to be a way to make sure that the initializing happens only once. Therefore, only one function should have the initializer modifier. It theory it can be in the parent contract, as long as no child contract has it.

To call initializers in parents, there is that separate modifier onlyInitializing.

Yes, the system is a bit confusing, but the whole point is to try to make sure that initializing can be done only once.

Once the contract has been deployed, it can't be inherited any more, so you only need to know whether your code plans to inherit an upgradeable contract or not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.