An initializer function is where a contract initializes its state.
Initializer functions are similar to constructors:
can only be called once
external non-initializer functions cannot be called until one of the initializers has ben called
The only exception are noinitcheck functions, which can be called even if none of the initializers has been
called.
Initialization Commitment
All contract instances have their address include a commitment to one of their initializer functions, along with
parameters and calling address. Any of the following will therefore fail:
calling the wrong initializer function
calling the initializer function with incorrect parameters
calling the initializer function from the incorrect address
It is possible however to allow for any account to call the specified initializer by setting the intended caller to
the zero address. These are called 'universal deployments'.
Multiple Initializers
A contract can have multiple initializer functions, but it is not possible to call multiple initializers on the same
instance: all initializers become disabled once any of them executes. Each individual instance can call any of the
initializers.
Initializers can be either private or public. If a contract needs to initialize both private and public
state, then it should have an external private function marked as initializer which then enqueues a call to an
external public function not marked as initializer and instead marked as only_self (so that it can only be
called in this manner).
Lack of Initializers
If a contract has no initializer function, initialization is then not required and all functions can be called at
any time. Contracts that do have initializers can also make some of their functions available prior to
initialization by marking them with the #[noinitcheck] attribute - though any contract state initialization will
of course not have taken place.
Cost
The initialization process emits a nullifier which marks the contract as initialized. All other external functions
are automatically made to check that this nullifier exists, ensuring initialization.
An initializer function is where a contract initializes its state.
Initializer functions are similar to constructors:
The only exception are noinitcheck functions, which can be called even if none of the initializers has been called.
Initialization Commitment
All contract instances have their address include a commitment to one of their initializer functions, along with parameters and calling address. Any of the following will therefore fail:
It is possible however to allow for any account to call the specified initializer by setting the intended caller to the zero address. These are called 'universal deployments'.
Multiple Initializers
A contract can have multiple initializer functions, but it is not possible to call multiple initializers on the same instance: all initializers become disabled once any of them executes. Each individual instance can call any of the initializers.
Initializers can be either private or public. If a contract needs to initialize both private and public state, then it should have an external private function marked as initializer which then enqueues a call to an external public function not marked as initializer and instead marked as only_self (so that it can only be called in this manner).
Lack of Initializers
If a contract has no initializer function, initialization is then not required and all functions can be called at any time. Contracts that do have initializers can also make some of their functions available prior to initialization by marking them with the
#[noinitcheck]attribute - though any contract state initialization will of course not have taken place.Cost
The initialization process emits a nullifier which marks the contract as initialized. All other external functions are automatically made to check that this nullifier exists, ensuring initialization.
For private non-initializer functions, the cost of this check is equivalent to that of a call to PrivateContext::push_nullifier_read_request. For public ones, it is equivalent to a call to PublicContext::nullifier_exists_unsafe.
The noinitcheck attribute can be used to skip the initialization nullifer checks.