为什么 _initializing 和 isTopLevelCall 变量用于 Openzeppelin 的 Initializable 合约?
Why are _initializing and isTopLevelCall variables used in Initializable contract of Openzeppelin?
这是代理模式上下文中的抽象合约:
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;
}
}
我不明白_initializing 和isTopLevelCall 的必要性。仅使用 _initialized 进行控制还不够吗?
谢谢,
_initializing
和 isTopLevelCall
组合允许使用 initializer
修饰符进行链式调用:
contract UpgradebleTest1 is Initializable {
uint public x;
function initialize(uint _x) public initializer {
internalInit(_x);
}
function internalInit(uint _x) internal initializer {
x = _x;
}
}
如果没有 _initializing
和 isTopLevelCall
检查,initializer
修饰符将在第一次调用 (initialize()
) 上传递,但在第二次调用 (internalInit()
).
modifier initializer() {
require(!_initialized, "Initializable: contract is already initialized");
_initialized = true;
}
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);
}
}
如果和上面一样,会执行同样的逻辑,但是_initialized = true;会被不必要地执行两次,对吧?但是,它似乎比以前多一个变量和相关附加说明的便宜吗?不是吗?
这是代理模式上下文中的抽象合约:
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;
}
}
我不明白_initializing 和isTopLevelCall 的必要性。仅使用 _initialized 进行控制还不够吗?
谢谢,
_initializing
和 isTopLevelCall
组合允许使用 initializer
修饰符进行链式调用:
contract UpgradebleTest1 is Initializable {
uint public x;
function initialize(uint _x) public initializer {
internalInit(_x);
}
function internalInit(uint _x) internal initializer {
x = _x;
}
}
如果没有 _initializing
和 isTopLevelCall
检查,initializer
修饰符将在第一次调用 (initialize()
) 上传递,但在第二次调用 (internalInit()
).
modifier initializer() {
require(!_initialized, "Initializable: contract is already initialized");
_initialized = true;
}
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);
}
}
如果和上面一样,会执行同样的逻辑,但是_initialized = true;会被不必要地执行两次,对吧?但是,它似乎比以前多一个变量和相关附加说明的便宜吗?不是吗?