Role of modifiers initializer
and onlyInitializing
in renewable contracts
When implementing renewable contracts using the Solidity Ethereum programming language, it is important to understand the correct use of two modifiers: initializer
and onlyInitializing
. These modifiers are critical to ensuring the expected behavior of the contract during the initialization phase.
What are initializer
and onlyInitializing
modifiers?
In Solidity, both initializer
and onlyInitializing
are used to specify the conditions under which a function can be called. The main difference between them lies in the moment of activation:
initializer
: This modifier is used to call a constructor that has been executed by the runtime or an external entity (eg, a contract with automatic reentry). In other words, it works during the boot phase.
onlyInitializing
: This modifier is used to call a function that should only be called when the contract is initialized. This ensures that the function will be called only once during initialization, and not on subsequent calls.
Correct use of initializer
and onlyInitializing
modifiers in multilevel inheritance
In cases of multi-level inheritance, when one contract inherits another contract, it is important to use these modifiers correctly to avoid possible problems. Here are some key points to consider:
Load sequence
When using multilevel inheritance, the initialization sequence must be carefully managed to ensure that the correct call order is maintained. The initializer' modifier can be used at the top level of a contract to call its constructor.
pragma solidity ^0.8.0;
contract MultiLevelInheritanceExample {
// Top level initializer
function __init() internal initializer {
require(msg.sender == "ContractA", "Only ContractA");
}
// Subcontract 1
struct SubContract1 {
private address value;
uint auditor;
}
contract SubContract1 is a MultiLevelInheritanceExample {
Subcontract1 public subcontract;
constructor() extern initializer {
subcontract = new subcontract1("Value", 0);
}
}
// Subcontract 2
struct SubContract2 {
private address value;
uint auditor;
}
contract SubContract2 is a MultiLevelInheritanceExample {
Subcontract2 public subcontract;
constructor() extern initializer {
subContract = new SubContract2("Value", 0);
}
}
}
In this example, SubContract1will be executed before
subContract, which ensures that it is called only once during initialization.
Several subscribers
If multiple calls to the same function use different modifiers (for exampleonlyInitializing), the behavior can become unpredictable. To avoid such problems:
“durability
pragma solidity ^0.8.0;
contract MultiLevelInheritanceExample {
// Top level initializer
function __init() internal initializer {
required (message