2

This is abstract contract in the context of Proxy pattern:

abstract contract Initializable {
    bool private _initialized;
    bool private _initializing;

    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}

contract UpgradebleTest1 is Initializable {
    uint public x;

    function initialize(uint _x) public initializer {
        x = _x;
    }
}

I don't understand the necessity of _initializing and isTopLevelCall. Is not enough doing control using only _initialized?

Thanks,

Cengo
  • 93
  • 5

2 Answers2

1

The _initializing and isTopLevelCall combination allow for chained calls with the initializer modifier:

contract UpgradebleTest1 is Initializable {
    uint public x;

    function initialize(uint _x) public initializer {
        internalInit(_x);
    }

    function internalInit(uint _x) internal initializer {
        x = _x;
    }
}

Without the _initializing and isTopLevelCall check, the initializer modifier would pass on the first call (initialize()) but fail on the second call (internalInit()).

modifier initializer() {
    require(!_initialized, "Initializable: contract is already initialized");
    _initialized = true;
}
Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
1
abstract contract Initializable {
        bool private _initialized;
    
        modifier initializer() {
            require(!_initialized, "Initializable: co...");
            _;
            _initialized = true;
        }
    }
    
contract UpgradebleTestParent is Initializable {
    uint public x;

    function initialize(uint _x) internal initializer {
        x = _x;
    }
}

contract UpgradebleTestMain is UpgradebleTestParent {
    function init(uint _x) public initializer {
        initialize(_x);
    }
}

If it is as above, it would execute same logic, but _initialized = true; would be executed twice unnecessarily, right? However, it seems like cheaper than the previous one which has a one more variable and related additional instructions? Isn't it?

Cengo
  • 93
  • 5
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 02 '21 at 16:26