
Ethereum でdApp(分散型アプリケーション)を作ると、ユーザーに「ウォレットを用意して」「ETHを買って」「ガス代を払って」とお願いすることになります。これが普及の壁です。
Account Abstraction(アカウント抽象化)は、この壁を崩すための仕組みです。EIP-4337 とEIP-7702 という2つの仕様があります。
結論から言うと、EIP-7702の登場で、4337の出番は大幅に減りました。単一ユーザーのバッチ実行や権限管理は7702だけで実現できます。4337が必要なのは「パーミッションレスなガススポンサー」と「複数ユーザー集約」の2つのケースに限られます。
本記事では、まず「なぜAccount Abstractionが必要か」を整理し、その上で7702と4337の使い分けを具体的に示します。
そもそもAccount Abstractionとは何か
従来のEOA(普通のウォレット)の問題
Ethereumには2種類のアカウントがあります:
- EOA(Externally Owned Account): 秘密鍵で操作する普通のウォレット(MetaMaskなど)
- コントラクトアカウント: コードで動くスマートコントラクト
ほとんどのユーザーはEOAを使いますが、EOAには厳しい制約があります:
| 制約 | 具体的な問題 |
|---|---|
| 秘密鍵が全て | 秘密鍵を失くしたら資産は永久に失われる。リカバリー手段がない |
| ガス代は自分持ち | ETHを持っていないと何もできない。新規ユーザーは「まずETHを買え」と言われる |
| 1トランザクション1操作 | approve→swapのような2段階操作は2回署名が必要。UXが悪い |
| 署名方式が固定 | ECDSA一択。生体認証やマルチシグを使いたくても無理 |
Account Abstractionが解決すること
Account Abstractionは、「アカウントの振る舞いをプログラム可能にする」ことでこれらを解決します:
| 解決策 | できるようになること |
|---|---|
| リカバリー | 信頼できる友人やサービスを使って、秘密鍵なしでアカウントを復旧 |
| ガススポンサー | dApp運営者がガス代を肩代わり。ユーザーはETHなしで操作可能 |
| バッチ実行 | 複数操作を1トランザクションにまとめて、署名1回で完了 |
| 柔軟な署名 | パスキー(指紋/顔認証)、マルチシグ、セッションキーなど自由に選べる |
要するに、「EOAの不便さをコントラクトの柔軟さで補う」のがAccount Abstractionです。
2つのアプローチ:EIP-4337とEIP-7702
Account Abstractionを実現する方法は1つではありません。EIP-4337とEIP-7702は、異なるアプローチで同じゴールを目指しています。
EIP-4337: コントラクト+周辺インフラの解決策
EIP-4337は、チェーンのトランザクション形式を増やさずに、Account Abstractionを実現します。仕組みはこうです:
- EntryPoint(実行ゲートウェイ): UserOperationを検証・実行するスマートコントラクト。代表的な実装はeth-infinitism/account-abstraction
- Bundler(束ね役): UserOperationを集約してEntryPointに送信するオフチェーンサービス
- Paymaster(スポンサー): ガス代(手数料)を肩代わりするスマートコントラクト
ユーザーは従来のトランザクションではなく、UserOperationという疑似トランザクションを作成します。Bundlerがこれを集約し、EntryPointに送信することで、ガススポンサーシップやバッチ実行が可能になります。
UserOperationの構造
UserOperationは、従来のトランザクションを拡張した構造体です。主要なフィールドを見てみます:
| |
重要なフィールドの役割:
- initCode: アカウントが存在しない場合、このコードでデプロイします。既存アカウントなら空にします
- callData:
execute(address dest, uint256 value, bytes data)のようなスマートアカウントの関数呼び出しをエンコードしたもの - paymasterAndData: 最初の20バイトがPaymasterアドレス、残りがPaymasterに渡すデータ。空ならユーザー自身がガス代を払います
- preVerificationGas: calldata のサイズに応じたBundlerへの補償。Bundlerがトランザクションを送信するコストをカバーします
実行フロー
EntryPointのhandleOps関数が呼ばれると、以下の順序で処理されます:
sequenceDiagram
participant B as Bundler
participant E as EntryPoint
participant A as SmartAccount
participant P as Paymaster
participant T as Target Contract
B->>E: handleOps(userOps)
loop 各UserOperation
E->>A: validateUserOp(userOp)
A-->>E: 検証結果
opt Paymaster使用時
E->>P: validatePaymasterUserOp(userOp)
P-->>E: 検証結果
end
E->>A: callData実行
A->>T: 実際の操作
T-->>A: 結果
opt Paymaster使用時
E->>P: postOp(実行結果)
end
end
E-->>B: 完了
- 検証フェーズ: スマートアカウントの
validateUserOpで署名を検証 - Paymaster検証: Paymasterがある場合、
validatePaymasterUserOpでスポンサー条件を確認 - 実行フェーズ:
callDataに基づいてスマートアカウントが操作を実行 - 後処理: Paymasterの
postOpで課金処理など
ユーザーの操作はシンプルにできますが、その裏側でBundler/Paymasterを運用する「提供側の複雑さ」が発生します。
EIP-7702: トランザクション形式の解決策
EIP-7702は、新しいトランザクションタイプ(Type 4)を導入します。これにより、EOA(authority)宛の呼び出しが、別アドレスに置かれたコードへ「委任」され、EOAの状態(残高・ストレージ)を使って実行されるようになります。
この「委任」は、EIP本文ではDelegation Indicator(委任マーカー)と呼ばれる値(0xef0100 + delegate address)をauthorityのaccount codeに書き込むことで実現します。本記事ではこの値を「委任マーカー」と呼びます。
登場人物の整理
EIP-7702では、以下の3つの役割を区別することが重要です:
| 役割 | 説明 |
|---|---|
| tx.origin(送信者) | Type 4トランザクションをネットワークに送信する人。ガス代を払う |
| authority(委任元EOA) | authorization_listに署名するEOA。自分のアカウントに委任マーカーを設定される |
| delegate(委任先コントラクト) | 実際のコードが置かれているアドレス。authorityのコンテキストで実行される |
重要: tx.originとauthorityは同一でも別人でも構いません。スポンサーがtx.originとなり、別のEOAのauthority委任を設定することも可能です。
委任の仕組み
graph TB
subgraph "1. 委任マーカーの設定"
Sender[tx.origin
送信者] -->|Type 4 Tx送信| EVM[EVM]
EVM -->|authorization_list検証| Auth[authorityの署名検証]
Auth -->|委任マーカーを書き込み| EOA_Code["authorityのcode領域
0xef0100 + delegate address"]
end
graph TB
subgraph "2. 委任先コードの実行"
Caller[任意の呼び出し元] -->|"CALL(authority)"| EOA[authority EOA]
EOA -->|委任マーカーを検出| Lookup[delegateのコードを参照]
Lookup -->|コードをロード| Delegate[delegate contract
のバイトコード]
Delegate -->|authorityのコンテキストで実行| Exec["実行環境:
address(this) = authority
storage = authorityのもの
balance = authorityのもの"]
end
具体例で理解する
Alice(EOA)が、BatchExecutorコントラクトのコードを「借りて」複数操作を1トランザクションで実行する例です:
sequenceDiagram
participant Alice as Alice (authority)
0xAlice...
participant Bob as Bob (tx.origin)
0xBob...
participant EVM as EVM
participant Batch as BatchExecutor
0xBatch...
participant DEX as DEX Contract
Note over Alice,Bob: 1. Aliceが委任に署名(オフチェーン)
Alice->>Bob: authorization署名を渡す
Note over Bob,EVM: 2. BobがType 4 Txを送信
Bob->>EVM: Type 4 Tx
to=Alice, data=executeBatch(...), authorization_list
EVM->>EVM: authorization_listを処理(Alice署名を検証)
Note right of EVM: 状態更新: Aliceのcodeに委任マーカーを設定
Note right of EVM: code = 0xef0100 + 0xBatch...
Note over EVM,DEX: 3. Aliceへの呼び出しが委任実行される
Note over EVM: トランザクションの宛先はAlice(to=Alice)
EVM->>Batch: delegateのコードをロード
Note right of Batch: 実行コンテキストはAlice
Note right of Batch: address(this)=Alice, msg.sender=Bob
Batch->>DEX: swap() [Aliceとして]
DEX-->>Batch: 結果
この例のポイント:
- Bobがガス代を払う(tx.origin)
- Aliceのアカウントに委任マーカーが設定される(authority)
- BatchExecutorのコードが使われる(delegate)
- 実行時の
address(this)はAlice、msg.senderはBob
7702時代に4337が必要なケース
EIP-7702の登場で、4337の出番は大幅に減りました。単一ユーザーのバッチ実行、権限委譲、セッションキーなどは7702だけで実現できます。
では4337は不要になったのか? 2つの具体的なケースで、まだ4337が必要です。
ケース1: パーミッションレスなガススポンサー
ガススポンサー自体は7702でも実現できます。運営者がtx.originとしてトランザクションを送信し、運営者が管理するdelegateコントラクトを使えば、revertリスクも事前検証で管理できます。
4337が必要になるのは「パーミッションレス」なスポンサーを作る場合です。
Open Paymaster のような「誰でも使えるPaymaster」をDeFiとして運用する場合、7702では成り立ちません。
7702の問題:
1. 不特定多数がスポンサーに「実行してほしい操作」を投げられる
2. 悪意あるユーザーがrevertするトランザクションを送信
3. スポンサーはガス代だけ取られ、操作は失敗
4. これを繰り返されると破綻
事前にシミュレーション(eth_call)はできますが、送信までの間に状態が変わる可能性があります。パーミッションレスな環境では、悪意あるユーザーを排除できません。
4337の解決策: 検証フェーズと実行フェーズが分離しています。
| |
Bundlerが事前にUserOperationをシミュレーションし、検証に通るものだけをEntryPointに送ります。検証段階で弾けるものはガス損失なしで弾けるため、パーミッションレスでも運用が成り立ちます。
Open Paymasterの設計(リバランサーのインセンティブで持続性を確保する仕組み)については「Open Paymaster: 誰も運営しないのに回るリバランス設計 」を参照してください。
ケース2: 複数ユーザーの操作を1トランザクションに集約
4337の場合:
| |
7702の場合:
// Aliceの操作 → 1 tx(21000 base fee)
// Bobの操作 → 1 tx(21000 base fee)
// Charlieの操作 → 1 tx(21000 base fee)
// → 3トランザクション、3回のbase fee
7702のauthorization_listには複数のauthorityを入れられますが、それは「複数EOAに委任マーカーを設定する」だけです。設定後の実行は各authorityへの個別CALLが必要で、1 txにまとめるには「全員の署名を集めて呼ぶコントラクト」を自前で作ることになります。つまり4337のEntryPoint相当を再発明することになります。
このケースが重要な場面:
- 高頻度取引プラットフォーム(多数ユーザーの注文を効率的に処理)
- ガス代の「まとめ買い」でコスト削減したいリレイヤー運用
レアケース: 7702非対応チェーン
2025年現在、主要チェーン(Ethereum mainnet、Arbitrum、Optimism、Base、Polygon等)はEIP-7702に対応済みです。ただし、一部のEVM互換チェーンやプライベートチェーンでは未対応の場合があります。
4337はEntryPointコントラクトをデプロイすれば動くため、7702非対応チェーンでも同じ設計を持ち込めます。マルチチェーン展開で「全チェーンで同じコードベース」を維持したい場合は、4337の方が安全な選択です。
比較まとめ
| ユースケース | 7702 | 4337 |
|---|---|---|
| 単一ユーザーのバッチ実行 | ◎ | ○ |
| 運営者によるガススポンサー | ◎ | ○ |
| パーミッションレスなスポンサー | ✗ | ◎ |
| 複数ユーザー集約 | △ 自前実装 | ◎ Bundler標準 |
| 既存EOAの継続利用 | ◎ | △ 新アドレス |
| ガスオーバーヘッド | ◎ 小さい | △ EntryPoint経由 |
| 7702非対応チェーン | ✗ | ◎ |
コード例(最小コンパイル): 4337 vs 7702
比較のために、4337側(スマートアカウント)と7702側(delegate)の最小サンプルを分けて置いておきます。
4337: 最小のスマートアカウント
| |
7702: delegate側コード(authorityコンテキストで実行)
| |
結論: ほとんどのdAppは7702だけで十分
ガスレス体験も7702で実現できます。運営者がtx.originとしてトランザクションを送信し、運営者が提供するdelegateコントラクトを使えば、revertリスクも管理できます。
4337が必要になるのは以下のケースだけです:
- パーミッションレスなスポンサー: 不特定多数が使う公開型Paymaster(Open Paymaster のような)では、検証フェーズで弾く仕組みが必須
- 複数ユーザーの集約: リレイヤーとして多数ユーザーのトランザクションを1つにまとめたい場合
ガスコストの見積もり方(実務)
「4337と7702、どっちが安い?」はケース依存です。なので、最初から固定の数値を置くより、まずは見積もりルートを用意するのが安全です。
7702(通常トランザクションとして見積もる)
7702は基本的に通常トランザクションの延長なので、まずはeth_estimateGasで見積もります。
| |
4337(Bundler RPCで見積もる)
4337はUserOperationの検証/実行コストが絡むので、BundlerのRPCで見積もるのが現実的です。
| |
この見積もりで出た値を元に、操作の種類ごとに「スポンサーあり/なし」「高頻度/低頻度」で分岐させると、実装と運用が安定します。
セキュリティ考慮事項
EIP-4337
ユーザーにとってのリスク: Bundlerの順序操作
Bundlerが悪意を持つ場合、トランザクションの順序を操作できます(MEV抽出)。ただし資金を直接盗むことはできません。対策として、複数のBundlerを使用するか、レピュテーションのあるBundlerを選びます。
Paymaster運営者/LPにとってのリスク: ガス吸い取り
検証ロジックが甘いと、悪意あるユーザーにガスを吸い取られます。
| |
EIP-7702
ユーザーにとってのリスク: 悪意ある委任先
委任先コントラクトはEOAの全権限(残高・ストレージ)で実行されます。悪意あるコードや脆弱性があると、資金を全て失います。信頼できる監査済みのdelegateのみを使うこと。
まとめ: 7702がデフォルト、4337は特定用途
EIP-7702の登場で、Account Abstractionの実装方針は明確になりました。
基本方針:
- デフォルトは7702: 単一ユーザーのバッチ実行、権限管理、ガススポンサー(運営者による)は7702で十分
- 4337は2つの用途に限定: パーミッションレスなスポンサー、複数ユーザー集約
4337が「obsolete」かと言われると、上記2つの用途がある限りは生き残ります。ただし、「とりあえず4337」という時代は終わり、7702で済むなら7702を選ぶのが合理的です。
個人的には、7702の登場でAccount Abstractionの敷居が大きく下がったと感じています。「4337特有の実装・運用の重さ(ユーザーには見せない部分)」を避けられるケースが増えたのは、エコシステム全体にとって良いことです。