Is it mandatory to call __Pausable_init or any init functions within upgradable contracts? What happens if you dont?

Let say contract A inherits PausableUpgradeable, if contract deployed without calling the __Pausable_init, is it safe to assume that the contract is defaulted to $._paused = false; since solidity default Boolean value is false, why is there a need to call __Pausable_init()?

Will the _pause still be callable? and modifier whenNotPaused check correctly?

// contracts/utils/PausableUpgradeable.sol
    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal onlyInitializing {
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal onlyInitializing {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = false;
    }
    function _pause() internal virtual whenNotPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = true;
        emit Paused(_msgSender());
    }

Im not too sure what happens for other contracts such as ReentrancyGuardUpgradeable, will there be any similar issues occurring as stated above?

// contracts/utils/ReentrancyGuardUpgradeable.sol
    function __ReentrancyGuard_init() internal onlyInitializing {
        __ReentrancyGuard_init_unchained();
    }
2 Likes

From your initializer, you should always call the __{ContractName}_init functions of the parent contracts that you inherit. See https://docs.openzeppelin.com/contracts/5.x/upgradeable#usage

These are important to call because they initialize those contracts and their linearized parent contracts, if any.

If you don't, some contracts may not be initialized. In the case of PausableUpgradeable, it may not make any difference for that specific case as you noticed. But as a best practice, we recommend calling __{ContractName}_init functions for all directly inherited contracts.

2 Likes