---
eip: 7955
title: Permissionless CREATE2 Factory
description: A permissionless method and parameters for deploying a CREATE2 factory across EVM chains to a deterministic address using EIP-7702.
author: Nicholas Rodrigues Lordello (@nlordell), Richard Meissner (@rmeissner), Valentin Seehausen (@vseehausen)
discussions-to: https://ethereum-magicians.org/t/multi-chain-deployment-process-for-a-permissionless-contract-factory/24318
status: Draft
type: Standards Track
category: ERC
created: 2025-05-15
requires: 1014, 7702
---

## Abstract

This ERC defines a permissionless and deterministic deployment mechanism across all EVM-compatible chains. It uses the [EIP-7702](./eip-7702.md) `Set Code for EOAs (0x4)` transaction type to deploy a universal CREATE2 factory contract to a fixed address (`0xC0DEb853af168215879d284cc8B4d0A645fA9b0E`) with known bytecode. The factory can then create any new contract to a deterministic address using the [EIP-1014](./eip-1014.md) `CREATE2 (0xf5)` opcode. It does not require preinstalls, secret keys, or chain-specific infrastructure.

## Motivation

Ensuring that contracts share the same address and code on multiple chains is a hard problem. It is typically done by having a known CREATE2 factory contract at a specific address that can further deterministically deploy new contracts using the `CREATE2 (0xf5)` opcode.

However, there is a bootstrapping problem: how do you get a CREATE2 factory contract with a specific address and code?

### Existing Solutions

There are currently three main approaches to this problem:

#### 1. Nick's Method

Use Nick's method to randomly generate a signature for a transaction **without** [EIP-155](./eip-155.md) replay protection that deploys the CREATE2 factory. Nick's method ensures that there is no known private key for the account that deploys the CREATE2 factory, meaning that the resulting contract will have a deterministic address and code on all chains. This strategy is used by the _Deterministic Deployment Proxy_ (deployed to `0x4e59b44847b379578588920ca78fbf26c0b4956c`, including on Ethereum Mainnet), one of the most widely used CREATE2 factory contracts.

**Downsides**:

- It does not work on chains that only accept EIP-155 replay-protected transactions.
- It is sensitive to changes in gas parameters on the target chain since the gas price and limit in the deployment transaction is sealed, and a new one cannot be signed without a private key.
- Reverts, such as those caused by alternative gas schedules, make the CREATE2 factory no longer deployable.

#### 2. Secret Private Key

Keep a carefully guarded secret key and use it to sign transactions to deploy CREATE2 factory contracts. The resulting contract will have a deterministic address and code on all chains where the transaction at a given nonce of the deployer account is a CREATE2 factory deployment, which can be verified post-deployment to ensure trustlessness. Additionally, this method does not have the same gas sensitivity downsides as Nick's method, as the private key can sign a creation transaction with appropriate gas parameters at the time of execution. This is the strategy used by the _Safe Singleton Factory_ and _CreateX_ (deployed to `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` and `0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed` respectively, including on Ethereum Mainnet).

**Downsides**:

- It is permissioned: the party that holds the secret key has the ultimate say on which chains will get the CREATE2 factory deployments.
- This requires carefully guarding a secret key; if it is exposed or lost, deployments are no longer guaranteed on new chains.
- If the transaction at the given nonce is not a successful CREATE2 factory deployment, then it is no longer possible to have a CREATE2 factory at the canonical address; this can happen by human error, for example.

#### 3. Preinstalls

Have popular CREATE2 deployment factories deployed on new chains by default. This is, for example, what OP Stack and ZKsync do as part of their preinstalls, including the CREATE2 factory contracts mentioned above. This ensures that the CREATE2 factory contracts have known addresses and codes.

**Downsides**:

- It is not standardized nor adopted by all chains.
- It is permissioned as a chain can choose not to include a specific CREATE2 factory contract preinstalled.
- Attempts to standardize this with RIP-7740 have not been successful.

### Proposal: Using EIP-7702 Type `0x4` Transactions

This ERC proposes a permissionless alternative fourth mechanism to the existing ones described above with none of their downsides. Additionally, it standardizes a set of deployment parameters for a **universal** CREATE2 factory deployment. This ensures a common CREATE2 factory for the community instead of multiple competing copies with slightly different codes at different addresses. This single CREATE2 factory copy can bootstrap additional deterministic deployment infrastructure (such as the comprehensive CreateX universal contract deployer).

**Benefits**

- Universally applicable: It can be executed on any chain by any user and guarantees a reliable determination of smart contract deployments on any chain.
- Fault resistant: The method is secure against "out of gas" and other errors.
- Permissionless: The universal CREATE2 factory contract can be deployed by anyone.

## Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Parameters

| Parameter                   | Value                                                                          |
| --------------------------- | ------------------------------------------------------------------------------ |
| `DEPLOYER_PRIVATE_KEY`      | `0x942ba639ec667bdded6d727ad2e483648a34b584f916e6b826fdb7b512633731`           |
| `CREATE2_FACTORY_INIT_CODE` | `0x7c60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f33d52601d6003f3` |
| `CREATE2_FACTORY_SALT`      | `0x000000000000000000000000000000000000000000000000000000000001bec5`           |

### Derived Parameters

| Derived Parameter              | Value                                                                |
| ------------------------------ | -------------------------------------------------------------------- |
| `DEPLOYER_ADDRESS`             | `0x962560A0333190D57009A0aAAB7Bfa088f58461C`                         |
| `CREATE2_FACTORY_ADDRESS`      | `0xC0DEb853af168215879d284cc8B4d0A645fA9b0E`                         |
| `CREATE2_FACTORY_RUNTIME_CODE` | `0x60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f3`       |
| `CREATE2_FACTORY_CODE_HASH`    | `0x2ad75e1e9642e6fce7d293d52fa5a8f62a79a2079abb7402256add02d6e8bc30` |

### Definitions

- **Deployer**: The account corresponding to `DEPLOYER_PRIVATE_KEY` with address `DEPLOYER_ADDRESS`.
- **CREATE2 factory contract**: A contract that deploys other contracts with `CREATE2 (0xf5)` opcode, allowing smart contracts to be deployed to deterministic addresses.
- **Bootstrap contract**: The contract that the _deployer_ delegates to in order to deploy the _CREATE2 factory contract_.
- **Bootstrapping code**: The critical code in the _bootstrap contract_ that performs the `CREATE2 (0xf5)` deployment of the _CREATE2 factory contract_.

### Bootstrap Contract

The _bootstrap contract_ MUST execute the following or equivalent _bootstrapping code_ as an EIP-7702 delegation target for the _deployer_ account:

```solidity
bytes memory initCode = CREATE2_FACTORY_INIT_CODE;
bytes32 salt = CREATE2_FACTORY_SALT;
assembly ("memory-safe") {
    create2(0, add(initCode, 32), mload(initCode), salt)
}
```

The _bootstrap contract_ MAY implement additional features such as:

- Abort early if either _CREATE2 factory contract_ is already deployed or the _deployer_ is not correctly delegated to.
  - This can help mitigate gas griefing from the front-running issue described below.
- Additional verification that the deployment succeeded as expected.
- Emit events to facilitate tracking of either the _bootstrap contract_ or _CREATE2 factory contract_ deployments.

### Deployment Process

1. Deploy a _bootstrap contract_ described in the previous section.
2. Sign an EIP-7702 authorization using the `DEPLOYER_PRIVATE_KEY` delegating to the _bootstrap contract_.
3. Execute an EIP-7702 type `0x4` transaction with the authorization from step 2; the transaction MUST call `DEPLOYER_ADDRESS` (**either** directly or indirectly) which delegates to the _bootstrap contract_ and MUST perform the `CREATE2 (0xf5)` of the `CREATE2_FACTORY_INIT_CODE` with `CREATE2_FACTORY_SALT` in the _bootstrapping code_.

Assuming successful execution of the _bootstrapping code_ without reverting in the context of the _deployer_, the _CREATE2 factory contract_ will be deployed to `CREATE2_FACTORY_ADDRESS` with code `CREATE2_FACTORY_RUNTIME_CODE` and code hash `CREATE2_FACTORY_CODE_HASH`.

## Rationale

### Deployment Mechanism

The deployment mechanism was chosen such that it is uniquely parameterized by the `DEPLOYER_ADDRESS` (which itself is derived from the `DEPLOYER_PRIVATE_KEY` and is therefore deterministic), the `CREATE2_FACTORY_INIT_CODE` and the `CREATE2_FACTORY_SALT` which are both fixed and deterministic. Additionally, since the `DEPLOYER_ADDRESS` will deploy the CREATE2 factory contract with the `CREATE2 (0xf5)` opcode, this guarantees that the address and code of the contract are deterministic.

The use of a publicly known private key enables this mechanism, as anyone can permissionlessly generate a delegation signature to **any** bootstrap contract that would cause the `DEPLOYER_ADDRESS` to execute the specified `CREATE2 (0xf5)` operation and deploy the factory contract to a completely deterministic address. Because of the use of `CREATE2 (0xf5)`, the CREATE2 factory will be deployed to `CREATE2_FACTORY_ADDRESS` if and only if it is deployed with `CREATE2_FACTORY_INIT_CODE`, thus guaranteeing a deployed code hash of `CREATE2_FACTORY_CODE_HASH`. Additionally, the semantics of `CREATE2 (0xf5)` make it so no transaction executed by `DEPLOYER_ADDRESS` can permanently block the deployment of the CREATE2 factory contract to `CREATE2_FACTORY_ADDRESS`.

One issue with this method is that because the `DEPLOYER_PRIVATE_KEY` is public, anyone can sign alternative delegations or transactions and front-run a legitimate CREATE2 factory deployment. The front-running would increase the nonce of the `DEPLOYER_ADDRESS` account and render the EIP-7702 authorization in the legitimate CREATE2 factory deployment transaction invalid, causing the deployment to potentially fail. This is not considered to be a serious issue, however, as:

1. Doing so does not prevent future deployments - meaning that an attacker can only delay the deployment of the CREATE2 factory with a sustained attack at a gas cost to the attacker, but not permanently prevent it from happening.
2. The damage is limited to gas griefing for accounts that are legitimately trying to deploy the CREATE2 factory contract. Furthermore, the reference implementation was coded to minimize the gas griefing damage.
3. In the case of a very persistent malicious actor, their attack can be circumvented by either making use of private transactions or working directly with block builders.

Another known issue with this method is that a future network upgrade may introduce new mechanisms (such as a new opcode or transaction type) to permanently set an account's code. If this were to happen, and since the `DEPLOYER_PRIVATE_KEY` is publicly known, the `DEPLOYER_ADDRESS` account's code could be mistakenly or maliciously set to something that does not execute the necessary bootstrapping code, permanently preventing any future deployment of the CREATE2 factory contract. If this ERC were to gain sufficient adoption, this is not believed to be an issue as:

1. The deployment on Ethereum Mainnet would already exist, and the `DEPLOYER_PRIVATE_KEY` would no longer have any value on Ethereum Mainnet.
2. An RIP can be adopted to ensure that `CREATE2_FACTORY_ADDRESS` has code `CREATE2_FACTORY_RUNTIME_CODE`.

### Publicly Known Private Key Instead of Nick's Method

Instead of using a publicly known `DEPLOYER_PRIVATE_KEY`, Nick's method can be used to generate a random EIP-7702 authorization signature. This would prevent the front-running and forward compatibility issues described above.

However, in order for Nick's method to work, the EIP-7702 authorization message that is signed, defined as `keccak(MAGIC || rlp([chain_id, address, nonce]))`, must be constant. `MAGIC` is already a constant; `chain_id` can be trivially fixed to `0` to specify a chain-agnostic EIP-7702 authorization; `nonce` can also be trivially fixed to `0` because Nick's method ensures the authority has no known private key, meaning it cannot sign another message that would increment the nonce. However, fixing `address` is problematic. Doing so would require a contract with specific code to be deployed to the same address on all chains, which is the original bootstrapping problem the proposed permissionless CREATE2 factory aims to solve. Therefore, this creates a "chicken and egg problem", making it not a viable way to generate an EIP-7702 authorization signature.

### Use of CREATE2 Factory Contract

This mechanism allows the `DEPLOYER_ADDRESS` to do any `CREATE2 (0xf5)` deployment, so it would be possible to forgo the intermediary CREATE2 factory contract and use the deployer technique for all deployments. There are multiple downsides to this, however:

- All contract deployments are subject to the front-running issue described above, which could become an annoyance
- Concurrent deployments from the deployer are subject to race conditions since EIP-7702 authorizations increase the account nonce. This means that if two deployments are submitted to the mempool without knowing about each other, only the first one will actually succeed, because the EIP-7702 authorization in the second transaction is for an outdated nonce. This is not an issue when deployers are trying to deploy the same contract as proposed in this ERC since even if the second delegation and transaction fails, the contract would have been deployed as desired.

### Multiple Transaction Procedure

Unfortunately, EIP-7702 type `0x4` transactions are restricted to `to` values that are not `null`, meaning that you cannot simultaneously deploy the _bootstrap contract_ and delegate to it in a single transaction.

### Choice of Deployer Private Key

The `DEPLOYER_PRIVATE_KEY` was chosen as the private key at derivation path `m/44'/60'/0'/0/0` for the mnemonic `make code code code code code code code code code code coconut`.

### Choice of Salt

The `CREATE2_FACTORY_SALT` was chosen as the **first** salt value starting from `0` such that the CREATE2 factory's [ERC-55](./eip-55.md) checksum address starts with the case sensitive `0xC0DE...` prefix. A verifiable method for mining a vanity address for the CREATE2 factory contract was chosen in order to ensure that the ERC authors did not find a CREATE2 hash collision on the `CREATE2_FACTORY_ADDRESS` that they can exploit at some point in the future.

### CREATE2 Factory Bytecode

The CREATE2 factory has a similar interface to existing implementations. Namely, it accepts `salt || init_code` as input, which is a 32-byte `salt` value concatenated with the `init_code` of the contract to deploy. It will execute a `CREATE2` with the specified `salt` and `init_code`, deploying a contract with `init_code` to `keccak256(0xff || CREATE2_FACTORY_ADDRESS || salt || keccak256(init_code))[12:]`. This contract returns the address of the created contract padded to 32 bytes. This differs from some existing implementations, but was done to maintain consistency with the 32-byte word size on the EVM (same encoding as `ecrecover` precompile for example). A product of this is that the return data from CREATE2 factory is compatible with the Solidity ABI. In the case where the execution of `init_code` were to fail, any revert data is propagated to the caller.

Throughout both the CREATE2 factory contract initialization and runtime code, `RETURNDATASIZE (0x3d)` is used to push `0` onto the stack instead of the dedicated `PUSH0 (0x5f)` opcode. This is done to increase compatibility with chains that support EIP-7702 but not [EIP-3855](./eip-3855.md), while remaining a 1-byte and 2-gas opcode.

The `CREATE2_FACTORY_INIT_CODE` corresponds to the following assembly:

```
# SPDX-License-Identifier: CC0-1.0

### Constructor Code ###

0x0000: PUSH29 0x60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f3
                        # Stack: [runcode]                      | Push the CREATE2 factory runtime code, left padded
                                                                # with three 0 bytes
0x001e: RETURNDATASIZE  # Stack: [0; runcode]                   | Push the offset in memory to store the code
0x001f: MSTORE          # Stack: []                             | The runtime code is now in `memory[3:32]`, because of
                                                                # the 3 bytes of 0-padding
0x0020: PUSH1 29        # Stack: [29]                           | Push the code length
0x0022: PUSH1 3         # Stack: [3; 29]                        | Push the memory offset of the start of code
0x0024: RETURN          # Stack: []                             | Return the runtime code
```

The `CREATE2_FACTORY_RUNTIME_CODE` corresponds to the following assembly:

```
# SPDX-License-Identifier: CC0-1.0

### Runtime Code ###

# Prepare the stack, push 32, a value that will used a lot and can summon with
# `DUP*` to save on one byte of code (over `PUSH1 32`), and a 0 which will be
# used by either the `RETURN` or `REVERT` branches at the end.
0x0000: PUSH1 32        # Stack: [32]
0x0002: RETURNDATASIZE  # Stack: [0; 32]

# First, load the salt value and compute the actual code size for the CREATE2
# call, this is the calldata length minus 32 for the salt prefix.
                        # Stack: [0; 32]
0x0003: RETURNDATASIZE  # Stack: [0; 0; 32]                     | Push the calldata offset 0 of the `salt` parameter
0x0004: CALLDATALOAD    # Stack: [salt; 0; 32]                  | Load the `salt` from calldata
0x0005: DUP3            # Stack: [32; salt; 0; 32]              | Push 32 to the stack
0x0006: CALLDATASIZE    # Stack: [msg.data.len; 32; salt; ...]  | Followed by the calldata length
0x0007: SUB             # Stack: [code.len; salt; 0; 32]        | Compute `msg.data.length - 32`, which is the length of
                                                                # the init `code`

# Copy the init code to memory offset 0. Note that if the call to the contract
# incorrectly encoded, this will revert with "out of gas", as it will attempt
# to copy ~2**256 bytes of calldata to memory.
                        # Stack: [code.len; salt; 0; 32]
0x0008: DUP1            # Stack: [code.len; .; salt; 0; 32]     | Duplicate the length of the init code
0x0009: DUP5            # Stack: [32; code.len; ...]            | Push the offset in calldata of the code, which is 32
                                                                # as it comes immediately after the 32-byte `salt`; use
                                                                # the 32 value at the bottom of the stack
0x000a: RETURNDATASIZE  # Stack: [0; 32; code.len; ...]         | Push the offset (0) in memory to copy the code to
0x000b: CALLDATACOPY    # Stack: [code.len; salt; 0; 32]        | Copy the init code, `memory[0:code.len]` contains the
                                                                # init `code`

# Deploy the contract.
                        # Stack: [code.len; salt; 0; 32]
0x000c: RETURNDATASIZE  # Stack: [0; code.len; salt; 0; 32]     | Push the offset in memory starting of the start of
                                                                # init `code`, which is 0
0x000d: CALLVALUE       # Stack: [v; 0; code.len; salt; 0; 32]  | Forward the call value to the contract constructor
0x000e: CREATE2         # Stack: [address; 0; 32]               | Do `create2(v, code, salt)`, which leaves the address
                                                                # of the contract on the stack, or 0 if the contract
                                                                # creation reverted

# Verify the deployment was successful and return the address.
                        # Stack: [address; 0; 32]
0x000f: DUP1            # Stack: [address; .; 0; 32]            | Duplicate the address value
0x0010: PUSH1 0x19      # Stack: [0x0019; address; .; 0; 32]    | Push the jump destination offset for the code which
                                                                # handles successful deployments
0x0012: JUMPI           # Stack: [address; 0; 32]               | Jump if `address != 0`, i.e. `CREATE2` succeeded

# CREATE2 reverted, propagate the revert data.
                        # Stack: [address = 0; 0; 32]
0x0013: RETURNDATASIZE  # Stack: [r.len; 0; 0; 32]              | Push the revert data length onto the stack
0x0014: DUP2            # Stack: [0; r.len; 0; 0; 32]           | Push 0 on to the stack by duplicating; note that
                                                                # `PUSH0` is intentionally do not used for increased
                                                                # compatibility with chains that do not implement that
                                                                # specific opcode
0x0015: RETURNDATASIZE  # Stack: [r.len; 0; r.len; 0; 0; 32]    | Push the revert data length onto the stack again
0x0016: SWAP4           # Stack: [0; 0; r.len; 0; r.len; 32]    | Reorder the stack so that both `RETURNDATACOPY` and
                                                                # `REVERT` can be called; this is done by swapping the
                                                                # revert data length on the top of the stack with the
                                                                # bottom-most 0
0x0017: RETURNDATACOPY  # Stack: [0; r.len; 32]                 | Copy the revert data to `memory[0:r.len]`
0x0018: REVERT          # Stack: [32]                           | Revert with `memory[0:r.len]`

# CREATE2 succeeded.
0x0019: JUMPDEST        # Stack: [address; 0; 32]
0x001a: RETURNDATASIZE  # Stack: [0; address; 0; 32]            | Push the memory offset (0) to store return data at,
                                                                # `RETURNDATASIZE` is used as contract creation was
                                                                # successful, and therefore the return data has size 0
0x001b: MSTORE          # Stack: [0; 32]                        | Store the address in memory, `memory[0:32]` contains
                                                                # the `address` left padded to 32-bytes
0x001c: RETURN          # Stack: []                             | Return `memory[0:32]`, i.e. the address
```

## Backwards Compatibility

There are a few backwards compatibility considerations with the new proposal:

1. It requires an EVM chain with EIP-7702 enabled. This means not all chains can use this deployment method.
2. It would deploy yet another CREATE2 factory contract that would need to be adopted by tooling.
3. The proposed CREATE2 factory implementation returns the newly created contract address padded to 32 bytes. This is different to some existing contracts that return unpadded 20-byte address value.
4. The proposed CREATE2 factory implementation propagates revert data. This is different to some existing contracts that just revert with empty data in case executing the CREATE2 initialization code fails.

## Reference Implementation

This proposal includes a reference implementation of a bootstrap contract to which the deployer account can delegate. The reference implementation expects a call to `Bootstrap` to the function `deploy()` in an EIP-7702 type `0x4` transaction including the EIP-7702 authorization delegating `DEPLOYER_ADDRESS` to `Bootstrap` (NOTE: the `Bootstrap` is called as an entry point, instead of calling `DEPLOYER_ADDRESS` directly which allows the contract to do some up-front checks to minimize gas griefing risk):

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.29;

contract Bootstrap {
    address private constant _DEPLOYER_ADDRESS = 0x962560A0333190D57009A0aAAB7Bfa088f58461C;
    address private constant _CREATE2_FACTORY_ADDRESS = 0xC0DEb853af168215879d284cc8B4d0A645fA9b0E;
    bytes32 private constant _CREATE2_FACTORY_CODE_HASH = hex"2ad75e1e9642e6fce7d293d52fa5a8f62a79a2079abb7402256add02d6e8bc30";
    bytes private constant _CREATE2_FACTORY_INIT_CODE = hex"7c60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f33d52601d6003f3";
    bytes32 private constant _CREATE2_FACTORY_SALT = hex"000000000000000000000000000000000000000000000000000000000001bec5";

    error InvalidDelegation();
    error CreationFailed();

    function deploy() external {
        if (_CREATE2_FACTORY_ADDRESS.codehash == _CREATE2_FACTORY_CODE_HASH) {
            return;
        }

        bytes32 delegation = keccak256(abi.encodePacked(hex"ef0100", this));
        require(_DEPLOYER_ADDRESS.codehash == delegation, InvalidDelegation());

        Bootstrap(_DEPLOYER_ADDRESS).bootstrap();
    }

    function bootstrap() external {
        bytes memory initCode = _CREATE2_FACTORY_INIT_CODE;
        bytes32 salt = _CREATE2_FACTORY_SALT;

        address factory;
        assembly ("memory-safe") {
            factory := create2(0, add(initCode, 32), mload(initCode), salt)
        }

        require(factory == _CREATE2_FACTORY_ADDRESS, CreationFailed());
    }
}
```

A minimal bootstrap contract implementation is also possible (although this has a higher potential for gas griefing). The minimal bootstrap contract expects a call directly to the `DEPLOYER_ADDRESS` in an EIP-7702 type `0x4` transaction including the EIP-7702 authorization delegating `DEPLOYER_ADDRESS` to `MiniBootstrap`:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.29;

contract MiniBootstrap {
    bytes private constant _CREATE2_FACTORY_INIT_CODE = hex"7c60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f33d52601d6003f3";
    bytes32 private constant _CREATE2_FACTORY_SALT = hex"000000000000000000000000000000000000000000000000000000000001bec5";

    fallback() external {
        bytes memory initCode = _CREATE2_FACTORY_INIT_CODE;
        assembly ("memory-safe") {
            pop(create2(0, add(initCode, 32), mload(initCode), _CREATE2_FACTORY_SALT))
        }
    }
}
```

## Security Considerations

It is possible to front-run transactions that invalidate the deployer's EIP-7702 delegation and cause the deployment to fail. This, however, comes at a gas cost to the attacker, with limited benefit beyond delaying the deployment of the CREATE2 factory. Additionally, persistent attackers can be circumvented by either using private transaction queues or working with block builders directly to ensure that the EIP-7702 bootstrapping transaction is not front-run.

### Future Network Upgrades

If new EVM opcodes or transaction types are introduced in future network upgrades that allow an account to permanently set its code, then this method is no longer guaranteed to work. The deployer account can permanently change its code to a contract that does not have the required bootstrapping code. This can trivially be done by a malicious actor using the publicly known `DEPLOYER_PRIVATE_KEY` and would prevent any future deployments of CREATE2 factory.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
