# [ERC7947] スマートアカウントの鍵を失っても復旧できるリカバリインターフェースの仕組みを理解しよう！

> ERC7947は、Account Abstraction Recovery Interface（AARI）と呼ばれるスマートアカウント向けのリカバリインターフェースです。

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

## はじめに

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

https://amzn.asia/d/gxvJ0Pw

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください！

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://twitter.com/cardene777

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

今回は、スマートアカウントのアクセスを安全に復旧するための共通インターフェースを提案している「**ERC7947**」についてまとめていきます。

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

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

秘密鍵を紛失してもアカウントを復旧できるように、複数のリカバリプロバイダを組み合わせて使える標準的なインターフェースです。

## 概要

**ERC7947**は、Account Abstraction Recovery Interface（AARI）と呼ばれるスマートアカウント向けのリカバリインターフェースです。

スマートアカウントが秘密鍵を失った時に、あらかじめ登録しておいたリカバリプロバイダを通じてアクセスを復旧できる仕組みを提供します。
`recoverAccess(subject, provider, proof)` という関数を中心に、リカバリプロバイダの追加・削除・検証を行う共通インターフェースを定義しています。
どのAccount Abstraction標準（**EIP4337**や**EIP7702**等）とも組み合わせられる設計になっており、スマートアカウントの種類を問わず利用できます。

![recovery-overview.png](/images/qiita-ed872b30-8a2d-4d66-b1ba-8f514115dde3.webp)

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

[\[ERC4337\] プロトコルの変更をせずにAAを実装する仕組みを理解しよう！](/articles/8c97ca7c93c4557ebfc2)

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

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

## 動機

Account Abstraction（アカウント抽象化）によりスマートアカウントが普及すると、ユーザーは秘密鍵を直接管理しなくてもよい体験が実現します。
しかし、秘密鍵を紛失した場合のアクセス復旧方法が標準化されていないという課題がありました。

#### 秘密鍵紛失の課題

EOA（Externally Owned Account）では秘密鍵を失うとアカウントのすべてにアクセスできなくなります。
スマートアカウントでも同様のリスクがあり、何らかのリカバリ手段が必要です。
しかし、現在のスマートアカウントは各プロジェクトが独自のリカバリ方法を実装しており、互換性がありません。

#### ZKAIとZK2FAの可能性

Zero-Knowledge Artificial Intelligence（ZKAI）やZero-Knowledge Two Factor Authentication（ZK2FA）といった技術が登場しています。
これらの技術を活用すれば、秘密鍵以外の方法で本人であることを証明し、アカウントへのアクセスを復旧できます。

:::message
**ZKAIとZK2FA**

ZKAIはゼロ知識証明とAIを組み合わせた技術で、例えば生体認証データをプライバシーを保護したまま検証できます。
ZK2FAはゼロ知識証明による二要素認証で、秘密の情報（パスワードやワンタイムコード等）を直接公開せずにその知識を証明できます。
これらはリカバリプロバイダとして実装でき、秘密鍵に代わる復旧手段を提供します。
:::

#### リカバリプロバイダマーケットプレイス

**ERC7947**では、スマートアカウントが複数のリカバリプロバイダを登録できる「**リカバリプロバイダアグリゲータ**」として機能します。
ユーザーは複数のリカバリ手段を組み合わせられるため、中央集権的なサービスやプロジェクトに依存する必要がなくなります。
共通インターフェースが標準化されることで、リカバリプロバイダのマーケットプレイスが生まれる可能性もあります。

## 仕様

#### `IAccountRecovery`インターフェース

スマートアカウントが実装するインターフェースです。
リカバリプロバイダの管理とアクセス復旧の機能を提供します。

```javascript
interface IAccountRecovery {
    event AccessRecovered(bytes subject);
    event RecoveryProviderAdded(address indexed provider);
    event RecoveryProviderRemoved(address indexed provider);

    function addRecoveryProvider(address provider, bytes memory recoveryData) external payable;
    function removeRecoveryProvider(address provider) external payable;
    function recoveryProviderAdded(address provider) external view returns (bool);
    function recoverAccess(
        bytes memory subject,
        address provider,
        bytes memory proof
    ) external returns (bool);
}
```

##### `addRecoveryProvider`

リカバリプロバイダを追加する関数です。

- **引数**
    - `provider`
        追加するリカバリプロバイダのアドレス。
    - `recoveryData`
        リカバリプロバイダに渡すカスタムデータ（コミットメント）。
- アクセス制御されるべきです。
- `provider`が`address(0)`でないことを確認しなければなりません。
- `provider`の`subscribe`関数を呼び出し、`recoveryData`を渡さなければなりません。

##### `removeRecoveryProvider`

登録済みのリカバリプロバイダを削除する関数です。

- **引数**
    - `provider`
        削除するリカバリプロバイダのアドレス。
- アクセス制御されるべきです。
- `provider`の`unsubscribe`関数を呼び出さなければなりません。

##### `recoveryProviderAdded`

リカバリプロバイダが登録済みかどうかを確認するview関数です。

- **引数**
    - `provider`
        確認するプロバイダのアドレス。
- **戻り値**
    - 登録済みなら`true`、未登録なら`false`。

##### `recoverAccess`

アカウントのアクセスを復旧する関数です。

- **引数**
    - `subject`
        復旧対象（エンコードされたオーナーアドレス、アクセス制御ロール等）。
    - `provider`
        使用するリカバリプロバイダのアドレス。
    - `proof`
        リカバリの証明（ZKP/ZKAI、署名等）。
- **戻り値**
    - 復旧成功なら`true`、失敗なら`false`またはリバート。
- `provider`がアカウントに登録されていることを確認しなければなりません。
- `provider`の`recover`関数を呼び出さなければなりません。
- 証明の検証に成功した場合、`subject`に従ってアカウントのアクセスを更新しなければなりません。

:::message
**リカバリフロー**

アカウント復旧は以下の流れで行われます。

1. ユーザーは事前に`addRecoveryProvider`でリカバリプロバイダを登録しておきます。この時、リカバリプロバイダに「コミットメント」（秘密のハッシュ値等）を渡します。
2. 秘密鍵を紛失した場合、ユーザーは`recoverAccess`を呼び出します。
3. `recoverAccess`はリカバリプロバイダの`recover`関数を呼び出し、ユーザーが提出した証明（proof）を検証・実行します（nonceを更新して再利用を防止します）。
4. 証明が正しければ、スマートアカウントのアクセス権が`subject`に基づいて更新されます。

```mermaid
sequenceDiagram
    participant U as ユーザー
    participant SA as スマートアカウント
    participant RP as リカバリプロバイダ

    Note over U,RP: 事前登録フェーズ
    U->>SA: addRecoveryProvider(provider, recoveryData)
    SA->>RP: subscribe(recoveryData)
    RP-->>SA: コミットメントを保存

    Note over U,RP: 復旧フェーズ
    U->>SA: recoverAccess(subject, provider, proof)
    SA->>RP: recover(object, proof)
    RP-->>SA: 証明を検証
    SA-->>U: アクセス権を更新
```
:::

![interface-structure.png](/images/qiita-00bacbd7-a198-4e87-9b30-7d58a4e0085a.webp)

#### `IRecoveryProvider`インターフェース

リカバリプロバイダが実装するインターフェースです。
スマートアカウントからのサブスクリプション管理とリカバリ証明の検証を行います。

```javascript
interface IRecoveryProvider {
    event AccountSubscribed(address indexed account);
    event AccountUnsubscribed(address indexed account);

    function subscribe(bytes memory recoveryData) external payable;
    function unsubscribe() external payable;
    function getRecoveryData(address account) external view returns (bytes memory);
    function recover(bytes memory object, bytes memory proof) external;
}
```

##### `subscribe`

スマートアカウント（`msg.sender`）をリカバリプロバイダに登録する関数です。
`recoveryData`を`msg.sender`に紐づけて保存し、後の`recover`関数での証明検証に使われるコミットメントとして管理します。

- **引数**
    - `recoveryData`
        リカバリのコミットメント（ハッシュ値やZKP公開出力等）。

##### `unsubscribe`

スマートアカウントのサブスクリプションを取り消す関数です。

- `msg.sender`に関連するすべてのリカバリデータを削除しなければなりません。

##### `getRecoveryData`

アカウントのリカバリデータ（コミットメント）を取得するview関数です。

- **引数**
    - `account`
        リカバリデータを取得するアカウントのアドレス。
- **戻り値**
    - 関連するリカバリデータ。

##### `recover`

`msg.sender`（スマートアカウント）のリカバリを実行する関数です。
`msg.sender`の`recoveryData`を使って`proof`の妥当性を確認し、証明の再利用を防ぐためにnonceなどを更新しなければなりません。
証明が無効な場合はリバートします。

- **引数**
    - `object`
        新しいオブジェクト（`subject`とは異なる場合がある）。
    - `proof`
        リカバリの証明。

:::message
**subscribe/recoverの流れ**

リカバリプロバイダとスマートアカウントの関係は「サブスクリプションモデル」になっています。

`subscribe`では、スマートアカウントがリカバリプロバイダに「コミットメント」を渡して登録します。
このコミットメントは、秘密の情報のハッシュ値やZKPの公開出力のようなもので、秘密そのものは渡しません。

`recover`では、ユーザーが提出した`proof`がコミットメントと整合するかを検証します。
例えばZKP（ゼロ知識証明）を使えば、秘密の情報を明かさずに「自分がその秘密を知っている」ことを証明できます。
証明の再利用を防ぐためにnonceの更新が求められており、リプレイ攻撃（同じ証明を使い回す攻撃）が防止されます。
:::

## 補足

#### 設計の背景

**ERC7947**はいくつかの設計判断に基づいています。

##### 任意のAA標準との互換性

この提案は特定のAccount Abstraction標準に依存しません。
**EIP4337**でも**EIP7702**でも、スマートアカウントが`IAccountRecovery`インターフェースを実装するだけでリカバリ機能を利用できます。
これにより、アカウントリカバリの市場が特定のAA標準に縛られずに成長できます。

##### `subject`と`object`がbytesである理由

`recoverAccess`の`subject`パラメータと`recover`の`object`パラメータは、アドレスではなく`bytes`型です。
スマートアカウントの中にはオーナーアドレスを持たないものもあり、ロールベースのアクセス制御を採用しているケースもあります。
`bytes`型にすることで、エンコードされたオーナーアドレス、アクセス制御ロール、その他のカスタムデータなど、柔軟な復旧対象を指定できます。

##### 再コミットの方法

セキュリティ上の理由でコミットメントを更新したい場合は、`unsubscribe`と`subscribe`をマルチコールで連続実行します。
これにより、古いコミットメントを削除してから新しいコミットメントを登録できます。

##### 後方互換性

**ERC7947**は既存のスマートアカウントの仕様に影響を与えません。
`IAccountRecovery`インターフェースを実装しない既存のコントラクトはそのまま動作し続けます。

## セキュリティ

アカウントリカバリには重要なセキュリティ上の考慮事項があります。

#### アクセス制御の重要性

`addRecoveryProvider`と`removeRecoveryProvider`関数は適切にアクセス制御されなければなりません。
これらの関数が誰でも呼び出せる状態だと、攻撃者が悪意のあるリカバリプロバイダを追加してアカウントを乗っ取る可能性があります。

#### フィッシング攻撃のリスク

ユーザーが騙されて悪意のあるリカバリプロバイダを追加してしまうリスクがあります。
悪意のあるリカバリプロバイダは偽のリカバリ証明を受け入れることで、アカウントの完全な制御権を得る可能性があります。
リカバリプロバイダの追加時にはプロバイダの信頼性を十分に確認することが重要です。

## 引用

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

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

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

## 最後に

今回は「**ERC7947（Account Abstraction Recovery Interface）**」についてまとめてきました。

スマートアカウントの秘密鍵を紛失した時に、あらかじめ登録しておいたリカバリプロバイダを通じてアクセスを復旧できる共通インターフェースを定義した提案です。
ZKPやZKAIを活用したリカバリプロバイダのマーケットプレイスが生まれる可能性もあり、Account Abstractionのユーザー体験をさらに向上させる重要な仕組みです。

他でも色々記事を書いているのでぜひよろしければ読んでいってください！

https://amzn.asia/d/gxvJ0Pw

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://twitter.com/cardene777

https://cardene.substack.com/
