# Tutorial 37: initializer and onlyInitializing

In smart contracts, especially in upgradeable contracts, the initialization process is used to set up the contract's state and configure its settings. A special function, often called `initialize()`, is typically used instead of the constructor because constructors do not work well with proxy contracts (commonly used for upgradeable patterns).

An **initialization vulnerability** occurs when the initialization function is incorrectly implemented, leading to the contract being locked out of initialization or reinitialization after upgrades. This type of vulnerability is particularly concerning in upgradeable contracts because it can prevent new functionality from being properly configured, potentially breaking the contract.

In this context, initialization should be carefully managed using modifiers like `initializer` and `onlyInitializing` to ensure that contracts can be upgraded safely without accidentally blocking further updates.

***

#### Understanding the EIP-712 Meta-Transaction Initialization Vulnerability

The EIP-712 standard is commonly used to sign messages and verify the authenticity of transactions, enabling **meta-transactions**. A meta-transaction allows users to submit a transaction without needing to pay for gas fees themselves. Instead, a third party (the relayer) pays the gas fees on behalf of the user. To ensure the security of meta-transactions, proper initialization of the EIP-712 domain is critical.

In a real-world vulnerability example related to the EIP-712 Meta-Transaction implementation, the contract's initialization process was incorrectly handled. The contract used the `initializer` modifier in its initialization function, which prevented reinitialization after upgrades. This could result in the contract being permanently locked out from setting up the EIP-712 domain again during contract upgrades, potentially leading to failure in the meta-transaction mechanism.

**Problematic Code:**\


```
function initializeEIP712(string memory _name, string memory _version)
    public
    initializer
{
    name = _name;
    version = _version;

    __EIP712_init(_name, _version);
}

```

In this example, the `initializer` modifier was used, which restricts the function from being called more than once. In the case of upgradeable contracts, each upgrade might require reinitialization to set up the new state. The use of `initializer` in this context prevents that, causing reinitialization to fail and making the contract inoperable after upgrades.

***

#### Consequences of Incorrect Initialization

1. **Contract Lockout**: Using the wrong initialization function can prevent upgrades from being properly configured. If the initialization process fails, new contract logic may not function as expected, leading to partial or full contract lockout.
2. **Reentrancy Issues**: Incorrect use of initialization can lead to reentrancy attacks or the contract perceiving itself as being in a state of initialization when it is not, causing security issues in future contract executions.
3. **Upgrade Failures**: If the contract cannot be reinitialized after an upgrade, new versions of the contract may not be able to configure crucial state variables, resulting in unexpected behavior.

***

#### Example Scenario: Incorrect Initialization in EIP-712 Meta-Transactions

Let’s go through a hypothetical scenario where the incorrect implementation of the `initialize` function leads to issues in the upgradeable contract.

1. **Initial Deployment**: The EIP-712 Meta-Transaction contract is deployed with the `initializer` modifier. During the initial deployment, the contract is correctly initialized with the name and version for EIP-712 signing.
2. **Contract Upgrade**: Six months later, the contract is upgraded to introduce a new feature, and a new version of the EIP-712 domain is required. However, since the `initializer` modifier was used, the upgrade process attempts to reinitialize the contract but fails. The contract reverts because the `initializeEIP712` function can only be called once.
3. **System Failure**: Due to the failed reinitialization, the meta-transaction feature stops working as the new domain data is never set. Users can no longer sign transactions, and the entire upgrade is deemed a failure.

***

#### Mitigation Strategies

To prevent initialization vulnerabilities, developers must ensure that initialization functions are implemented correctly in upgradeable contracts. Below are the steps to mitigate the risk:

**1. Use `onlyInitializing` Instead of `initializer` for Upgradeable Contracts**

In upgradeable contracts, use the `onlyInitializing` modifier rather than `initializer` when creating functions that need to be called during upgrades. This allows the function to be executed during upgrades, without restricting it to a single use.

The `onlyInitializing` modifier ensures that the function can be called whenever the contract is being initialized or reinitialized during an upgrade, preventing the contract from locking out future upgrades.

**2. Use the Correct Modifier for Initialization**

* Ensure that you use `initializer` only for functions that should be called **once** (during the initial deployment).
* For functions that need to be called on upgrades, always use `onlyInitializing` to allow multiple initializations during the contract's lifecycle.

**3. Make Use of Proxy Patterns**

* In upgradeable contracts, use proxy patterns to ensure that contracts can be safely reinitialized after each upgrade. Proxy patterns allow the logic contract to be upgraded while maintaining the state, ensuring that initialization functions can be used properly.

**4. Leverage OpenZeppelin Contracts**

* Use trusted libraries like **OpenZeppelin** to handle common contract patterns. OpenZeppelin provides well-audited and secure implementations of initialization logic for upgradeable contracts, including **EIP-712** support.
