# [ERC7955] 許可不要で全EVMチェーンにCREATE2ファクトリーをデプロイする仕組みを理解しよう！

> ERC7955とは、EIP7702のコード委任メカニズムを利用して、すべてのEVM互換チェーンの同一アドレス（0xC0DEb853af168215879d284cc8B4d0A645fA9b0E）にCREATE2ファクトリーコントラクトをデ

- URL: https://cardene.dev/articles/adf69fa6bb1b277d8101
- 公開日: 2026-03-23
- 更新日: 2026-03-23
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、**EIP7702**のコード委任を活用して、すべてのEVM互換チェーンに許可不要かつ決定的にCREATE2ファクトリーコントラクトをデプロイする仕組みを提案している**ERC7955**についてまとめていきます！

:::message
以下にまとめられているものを解説しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-7955

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

## 概要

**ERC7955**とは、**EIP7702**のコード委任メカニズムを利用して、すべてのEVM互換チェーンの同一アドレス（`0xC0DEb853af168215879d284cc8B4d0A645fA9b0E`）にCREATE2ファクトリーコントラクトをデプロイする方法を標準化する提案です。

:::message
**EIP7702**については以下の記事を参考にしてください。
:::

[\[EIP7702\] EOAをコントラクトアカウントに変換する仕組みを理解しよう！](/articles/13a828c97786aab953e4)

:::message
**CREATE2ファクトリーとは**

CREATE2ファクトリーとは、`CREATE2`オペコードを使って他のコントラクトを決定的なアドレスにデプロイするためのコントラクトです。
同じ初期化コードとsalt（ランダムな値）を使えば、どのチェーンでも同じアドレスにコントラクトをデプロイできます。
マルチチェーン対応のプロトコルにとって、全チェーンで同じアドレスを使えることは非常に重要です。
:::

しかし、CREATE2ファクトリー自体を全チェーンの同じアドレスにデプロイするにはどうすればいいかという「ブートストラップ問題」があります。
**ERC7955**はこの問題を、秘密鍵の管理不要、プリインストール不要、チェーン固有のインフラ不要で解決します。
誰でも、どのチェーンでも、許可なくCREATE2ファクトリーをデプロイできるようになります。

## 動機

#### コントラクトのマルチチェーンデプロイ問題

複数のチェーンで同じアドレスに同じコードのコントラクトをデプロイすることは難しい問題です。
DeFiプロトコルやウォレット、ブリッジなどのプロジェクトは、ユーザー体験の一貫性のために全チェーンで同一アドレスを使いたいと考えます。

これを実現するために、特定のアドレスに存在するCREATE2ファクトリーを経由してコントラクトをデプロイする方法が広く使われています。
しかし、そのCREATE2ファクトリー自体を全チェーンの同じアドレスにデプロイする方法が標準化されていません。

#### 既存の3つの手法とその課題

現在、この問題に対処するための手法は3つあります。
それぞれに深刻な課題があります。

##### Nick's Method

**EIP155**のリプレイ保護を使わないトランザクションに対して、ランダムな署名を生成する方法です。
秘密鍵が存在しないアカウントからのデプロイとなるため、結果のアドレスは全チェーンで決定的になります。
Deterministic Deployment Proxy（`0x4e59b44847b379578588920ca78fbf26c0b4956c`）がこの方式を使用しています。

しかし、**EIP155**のリプレイ保護を必須とするチェーンでは動作しません。
さらに、デプロイトランザクションのガスパラメータが署名に封印されているため、ガスパラメータが変更されたチェーンではデプロイが失敗します。
加えて、代替ガススケジュール等によるリバートが発生した場合も、そのアドレスに二度とデプロイできなくなります。

##### 秘密鍵方式

厳重に管理された秘密鍵を使ってデプロイトランザクションに署名する方法です。
Safe Singleton Factory（`0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7`）やCreateX（`0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed`）がこの方式を採用しています。
Nick's Methodと違い、デプロイ時のガスパラメータを柔軟に設定できます。

しかし、秘密鍵の保有者に許可を得なければ新しいチェーンにデプロイできません。
秘密鍵が漏洩・紛失した場合、新しいチェーンへのデプロイが保証されなくなります。
また、指定したnonceのトランザクションがCREATE2ファクトリーのデプロイでなかった場合（人的ミスなど）、正規のアドレスにデプロイできなくなります。

##### プリインストール

チェーンの起動時にCREATE2ファクトリーをあらかじめ組み込む方法です。
OP StackやZKsyncなどのL2がこの方式を採用しています。

しかし、すべてのチェーンで標準化されていません。
チェーンの運営者が特定のCREATE2ファクトリーを組み込まないと選択することもあり、許可制です。
RIP-7740による標準化の試みも成功していません。

#### この提案による解決策

以下の図は、既存手法の課題と**ERC7955**の解決策を比較したものです。

![fig2-comparison.png](/images/qiita-d8812df4-f5e1-42cc-8a50-f079b4ea89a3.webp)

**ERC7955**は上記3つの手法の課題をすべて解消する第4の方法を提案しています。
この提案には以下の利点があります。

- 誰でもどのチェーンでも実行でき、スマートコントラクトの決定的デプロイを保証する（汎用性）
- out of gasやリバートなどのエラーに対して安全で、エラー後も再デプロイが可能（耐障害性）
- CREATE2ファクトリーのデプロイに許可を必要としない（許可不要）

| 比較項目 | Nick's Method | 秘密鍵方式 | プリインストール | **ERC7955** |
|---------|-------------|----------|------------|----------|
| 許可不要 | ✅ | ❌ | ❌ | ✅ |
| ガス変更耐性 | ❌ | ✅ | ✅ | ✅ |
| 全チェーン対応 | ❌ | ❌ | ❌ | ✅ |
| 秘密鍵の管理不要 | ✅ | ❌ | ✅ | ✅ |
| エラー耐性 | ❌ | ❌ | ✅ | ✅ |

## 仕様

#### 用語定義

この提案で使用される主要な用語は以下の通りです。

| 用語 | 説明 |
|------|------|
| デプロイヤー | `DEPLOYER_PRIVATE_KEY`に対応するアカウント（`DEPLOYER_ADDRESS`）。公開された秘密鍵を持つ。 |
| CREATE2ファクトリーコントラクト | `CREATE2`オペコードを使って他のコントラクトを決定的アドレスにデプロイするコントラクト。 |
| ブートストラップコントラクト | デプロイヤーが**EIP7702**で委任する先のコントラクト。CREATE2ファクトリーのデプロイを実行する。 |
| ブートストラッピングコード | ブートストラップコントラクト内の、`CREATE2`デプロイを実行する核心的なコード部分。 |

#### パラメータ

**ERC7955**では以下のパラメータが定義されています。

| パラメータ | 値 | 説明 |
|----------|-----|------|
| `DEPLOYER_PRIVATE_KEY` | `0x942ba6...` | デプロイヤーの秘密鍵。公開されている。 |
| `CREATE2_FACTORY_INIT_CODE` | `0x7c6020...` | CREATE2ファクトリーの初期化コード。 |
| `CREATE2_FACTORY_SALT` | `0x0000...01bec5` | CREATE2デプロイ時のsalt値。 |

これらのパラメータから以下の値が導出されます。

| 導出パラメータ | 値 | 説明 |
|-------------|-----|------|
| `DEPLOYER_ADDRESS` | `0x962560A0...` | デプロイヤーのアドレス。秘密鍵から導出。 |
| `CREATE2_FACTORY_ADDRESS` | `0xC0DEb853...` | CREATE2ファクトリーのデプロイ先アドレス。 |
| `CREATE2_FACTORY_RUNTIME_CODE` | `0x60203d3d...` | ファクトリーのランタイムコード（29バイト）。 |
| `CREATE2_FACTORY_CODE_HASH` | `0x2ad75e1e...` | ランタイムコードのkeccak256ハッシュ。 |

#### ブートストラップコントラクト

デプロイプロセスの鍵となるのがブートストラップコントラクトです。
これは、デプロイヤーアカウントが**EIP7702**で委任する先のコントラクトで、以下のブートストラッピングコードを実行します。

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

このコードは`CREATE2`オペコードを実行し、指定された初期化コードとsaltでCREATE2ファクトリーをデプロイします。
ブートストラップコントラクトには以下のような追加機能を実装できます。

- CREATE2ファクトリーが既にデプロイ済みか、デプロイヤーの委任が正しく設定されているかを確認し、条件を満たさない場合は早期リターンする
- デプロイが期待通りに成功したかの追加検証
- ブートストラップコントラクトやCREATE2ファクトリーのデプロイを追跡するためのイベント発行

#### デプロイプロセス

以下の図はデプロイの全体フローです。

![fig1-deploy-flow.png](/images/qiita-7ff2a5b0-5b0f-4e88-a27a-fda2f25fa069.webp)

CREATE2ファクトリーのデプロイは以下の3ステップで行われます。

1. **ブートストラップコントラクトのデプロイ**
    前述のブートストラッピングコードを含むコントラクトをデプロイします。
2. **EIP7702認可の署名**
    `DEPLOYER_PRIVATE_KEY`を使って、ブートストラップコントラクトへの委任を認可する**EIP7702**署名を生成します。
3. **EIP7702トランザクションの実行**
    ステップ2の認可を含む`0x04`タイプのトランザクションを実行します。
    このトランザクションは`DEPLOYER_ADDRESS`を直接または間接的に呼び出し、ブートストラップコントラクトに委任された状態で`CREATE2`を実行します。
    参考実装ではブートストラップコントラクトをエントリーポイントとして間接的に呼び出す方式を採用しており、事前チェックによるガスグリーフィングの軽減が可能です。

```mermaid
sequenceDiagram
    participant Anyone as 誰でも
    participant Bootstrap as ブートストラップ
    participant Deployer as デプロイヤー<br/>（0x9625...）
    participant Factory as CREATE2ファクトリー<br/>（0xC0DE...）

    Anyone->>Bootstrap: 1. ブートストラップをデプロイ
    Anyone->>Deployer: 2. EIP-7702 認可署名を生成
    Anyone->>Bootstrap: 3. 0x04 tx実行（認可含む）
    Bootstrap->>Deployer: deploy()を呼び出し
    Deployer->>Factory: CREATE2で生成
    Note over Factory: 固定アドレスに<br/>ファクトリーが誕生
```

ブートストラッピングコードが正常に実行されると、`CREATE2_FACTORY_ADDRESS`にCREATE2ファクトリーがデプロイされます。

#### CREATE2ファクトリーの動作

デプロイされたCREATE2ファクトリーは、`salt || init_code`（32バイトのsalt値と初期化コードを連結したもの）をcalldataとして受け取ります。
指定されたsaltと初期化コードを使い`CREATE2`を実行し、`keccak256(0xff || CREATE2_FACTORY_ADDRESS || salt || keccak256(init_code))[12:]`のアドレスにコントラクトをデプロイします。

成功時はデプロイされたコントラクトのアドレスを32バイトにパディングして返します。
初期化コードの実行が失敗した場合は、revertデータがそのまま呼び出し元に伝播されます。

CREATE2ファクトリーのランタイムコードでは、互換性向上のために`PUSH0`（`0x5f`）オペコードの代わりに`RETURNDATASIZE`（`0x3d`）を使用してスタックに0をプッシュしています。
これは**EIP7702**をサポートしているが**EIP3855**（`PUSH0`を導入したEIP）をサポートしていないチェーンとの互換性を確保するためです。

## 補足

#### なぜ公開秘密鍵を使うのか

**ERC7955**のデプロイメカニズムでは、`DEPLOYER_PRIVATE_KEY`が公開されています。
これは意図的な設計で、誰でもこの秘密鍵を使ってデプロイヤーアカウントの**EIP7702**認可署名を生成し、任意のチェーンでCREATE2ファクトリーをデプロイできるようにするためです。

Nick's Methodでは秘密鍵が存在しないため署名の偽造は不可能ですが、`keccak(MAGIC || rlp([chain_id, address, nonce]))`の**EIP7702**認可メッセージにおいて`address`を固定する必要があります。
しかし、`address`を固定するには特定のコードを持つコントラクトが全チェーンで同じアドレスに存在する必要があり、これはまさにCREATE2ファクトリーが解決しようとしている「ブートストラップ問題」そのものです。
つまり「鶏と卵」の問題が発生するため、Nick's Methodは**EIP7702**の認可署名生成には使えません。

#### フロントランニングの考慮

`DEPLOYER_PRIVATE_KEY`が公開されているため、悪意のある第三者が別の委任や別のトランザクションに署名してフロントランニングし、正当なCREATE2ファクトリーのデプロイを妨害する可能性があります。
フロントランニングによりデプロイヤーアカウントのnonceが増加し、**EIP7702**の認可が無効になります。

しかし、以下の理由から深刻な問題とは考えられていません。

- 攻撃者はデプロイを遅延させることはできますが、永久に阻止することはできません。
    持続的な攻撃にはガスコストがかかります。
- ダメージはデプロイを試みるアカウントへのガス消費（ガスグリーフィング）に限られます。
    参考実装ではガスグリーフィングの影響を最小化するよう設計されています。
- 執拗な攻撃者に対しては、プライベートトランザクションの利用やブロックビルダーとの直接連携で回避できます。

#### saltの選定理由

`CREATE2_FACTORY_SALT`は、`0`から始めて最初にCREATE2ファクトリーの**ERC55**チェックサムアドレスが`0xC0DE...`で始まる値として選ばれました。
このvanityアドレスのマイニング方法を検証可能にすることで、ERC著者がCREATE2ファクトリーのアドレスに対するハッシュ衝突を悪用する可能性を排除しています。

#### デプロイヤーの秘密鍵の選定

`DEPLOYER_PRIVATE_KEY`は、ニーモニック`make code code code code code code code code code code coconut`の導出パス`m/44'/60'/0'/0/0`として選ばれています。

#### なぜ複数トランザクションが必要か

**EIP7702**のタイプ`0x04`トランザクションは`to`フィールドが`null`であることを許可しません。
そのため、ブートストラップコントラクトのデプロイとそれへの委任を1つのトランザクションで同時に行うことはできません。
ブートストラップコントラクトを先にデプロイし、その後で**EIP7702**トランザクションを送信する2段階の手順が必要になります。

#### なぜCREATE2ファクトリーを中間に置くのか

デプロイヤーアカウントは任意の`CREATE2`デプロイを実行できるため、中間のCREATE2ファクトリーを介さずに直接コントラクトをデプロイすることも可能です。
しかし、直接デプロイには以下の問題があります。

- すべてのデプロイがフロントランニングのリスクにさらされる
- **EIP7702**認可がnonceを増加させるため、同時に複数のデプロイを送信するとnonce競合が発生する

CREATE2ファクトリーを中間に置くことで、ファクトリーのデプロイ時のみフロントランニングリスクを負い、その後のコントラクトデプロイはファクトリー経由で安全に行えます。

## 互換性

この提案にはいくつかの互換性に関する考慮事項があります。

- **EIP7702**が有効なチェーンでのみ使用可能です。
    **EIP7702**をサポートしていないチェーンではこのデプロイ方法は使えません。
- 既存のCREATE2ファクトリーとは別のコントラクトがデプロイされるため、ツーリングの対応が必要です。
- 既存のCREATE2ファクトリーの一部は、作成されたコントラクトのアドレスを20バイトのままパディングなしで返しますが、この提案のファクトリーは32バイトにパディングして返します。
- 既存のCREATE2ファクトリーの一部は、初期化コードの実行失敗時に空のデータでrevertしますが、この提案のファクトリーはrevertデータをそのまま伝播します。

## 参考実装

以下はブートストラップコントラクトの参考実装です。
`deploy()`関数を呼び出すことで、**EIP7702**の認可とともにCREATE2ファクトリーをデプロイします。

```javascript
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());
    }
}
```

`deploy()`関数はまずCREATE2ファクトリーが既にデプロイされているかを確認し、デプロイ済みであれば早期リターンします。
次にデプロイヤーアカウントがブートストラップコントラクトに正しく委任されているかを検証します。
検証が通ると`bootstrap()`を呼び出し、`CREATE2`でファクトリーをデプロイします。

この事前チェックにより、ファクトリーが既にデプロイされている場合やデプロイヤーの委任が正しくない場合のガス消費を最小限に抑え、フロントランニングによるガスグリーフィングの影響を軽減しています。

#### 最小構成のブートストラップ

事前チェックを省略した最小構成のブートストラップコントラクトも実装可能です。
この場合は`DEPLOYER_ADDRESS`を直接呼び出す方式になりますが、ガスグリーフィングのリスクが高くなります。

```javascript
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))
        }
    }
}
```

`fallback()`関数が直接`CREATE2`を実行するシンプルな構成です。
フル実装版の`Bootstrap`コントラクトと比較すると、デプロイ済みチェックや委任検証がないため、不要な場合でもガスが消費されます。

## セキュリティ

#### フロントランニングによる妨害

`DEPLOYER_PRIVATE_KEY`が公開されているため、攻撃者はデプロイヤーの**EIP7702**委任を無効化するトランザクションをフロントランニングで送信し、デプロイを失敗させることができます。
しかし、攻撃者が負担するガスコストに対して得られる利益はデプロイの遅延のみであり、攻撃のインセンティブは限定的です。

執拗な攻撃に対しては、プライベートトランザクションキューの利用やブロックビルダーとの直接連携により、**EIP7702**ブートストラッピングトランザクションがフロントランニングされないようにすることで回避できます。

#### 将来のネットワークアップグレードへの影響

将来のネットワークアップグレードで、アカウントのコードを永続的に設定する新しいオペコードやトランザクションタイプが導入された場合、この方法が機能しなくなる可能性があります。
`DEPLOYER_PRIVATE_KEY`が公開されているため、悪意のある第三者がデプロイヤーアカウントのコードをブートストラッピングコードを含まないものに永続的に設定できてしまいます。

しかし、**ERC7955**が十分に普及していればEthereumメインネット上のデプロイは既に完了しているため、秘密鍵の価値はなくなります。
他のチェーンについては、RIPを採用して`CREATE2_FACTORY_ADDRESS`に正しいコードがプリインストールされるよう保証できます。

## 引用

https://eips.ethereum.org/EIPS/eip-7955

https://ethereum-magicians.org/t/multi-chain-deployment-process-for-a-permissionless-contract-factory/24318

https://eips.ethereum.org/EIPS/eip-7702

https://eips.ethereum.org/EIPS/eip-1014

## 最後に

今回は「**ERC7955**による許可不要のCREATE2ファクトリーデプロイ」についてまとめてきました。
いかがだったでしょうか？

マルチチェーン時代において、全チェーンで同じアドレスにコントラクトをデプロイしたいというニーズはますます高まっています。
**ERC7955**は公開秘密鍵と**EIP7702**を組み合わせることで、既存手法の課題をすべて解消し、誰でもどのチェーンでもCREATE2ファクトリーをデプロイできる仕組みを実現しています。

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4
