原文

Contract Deactivation — AccessDenied403 (2026-07-21)

ERC: コントラクト無効化インターフェース — トークンコントラクトを永続的に無効化するための標準シグナル

ERCドラフト: ERCs/ERCS/erc-deactivation.md at erc-deactivation · rya-sge/ERCs · GitHub


概要

スマートコントラクトが永続的に無効化されたことを示す方法を標準化する最小限のERCを提案します。これは、一時的な一時停止とは異なる、一方向の終端状態です。

このERCは、単一の一方向操作 deactivateContract() と、deactivated() ステータスビューを定義します。これにより、ウォレット、取引所、カストディアン、インデクサー、およびプロトコルは、コントラクトがもはやアクティブではないことを確実に検出できます。

ドラフトERC: [提出後リンクを追加 — ERC番号は未割り当て]


動機

一時停止メカニズムは、一時的なインシデントには非常に有効です。しかし、発行者がコントラクトが再アクティブ化されることを意図していない(決して再アクティブ化されない)ことを伝える必要がある終端ライフサイクルイベントには不十分です。

これは特に規制された実世界資産 (RWA) トークンにとって重要ですが、その必要性はより広範です。具体的なケースは以下の通りです。

  • 法的再編後の新しいコントラクトへのセキュリティ移行
  • 古いユニットを固定化する必要がある資本イベント(合併、分割、株式併合)
  • 発行者が台帳ベースの表現を中止する決定
  • DeFi市場のシャットダウン — レンディングプールやAMMペアの廃止 — オペレーターが明確な「永続的に非アクティブ」シグナルを必要とする場合

今日、インテグレーターは以下の間を確実に区別できません。

  • 一時的な一時停止
  • 運用上の停止
  • 永続的な無効化

これらはすべて外部からは似て見えます。このERCは、「もはやアクティブではない、永続的に」というシグナルを標準化し、一貫して検出できるようにします。

また、EIP-6780 (Dencun) 以降、SELFDESTRUCT はデプロイされたコントラクトのコードやストレージを削除しなくなったことにも注目する価値があります。残りのイーサを転送するだけであり、完全な削除はコントラクトが作成された同じトランザクション内でのみ可能です。言い換えれば、デプロイされたコントラクトを実際に破壊する方法はもはやありません。そのコードを保持し、永遠に呼び出し可能であり続けます。したがって、明示的な、アプリケーションレベルの「永続的に無効化された」ステータスが、ライフサイクルの終了を知らせる唯一の方法となります。


仕様 (要約)

interface IERCDeactivation is IERC165 {
    /// @notice Emitted when the contract is permanently deactivated.
    event Deactivated(address indexed account);
 
    /// @notice Raised when deactivation is attempted after it is already final.
    error AlreadyDeactivated();
 
    /// @notice Permanently deactivates the contract.
    function deactivateContract() external;
 
    /// @notice Returns whether the contract has been deactivated.
    function deactivated() external view returns (bool isDeactivated);
}

必須動作 (ハイライト):

  • 一方向状態: deactivated() は無効化前は false を返し、無効化後は true を返します。アクティブな実装では、false に戻ってはなりません (MUST NOT)。
  • 呼び出し: deactivateContract() は状態を設定し、Deactivated(account) を発行し、アクセス制御され、既に無効化されている場合は AlreadyDeactivated() でリバートしなければなりません (MUST)。
  • 一時停止の前提条件 (オプション): 一時停止メカニズムを使用する実装は、コントラクトが最初に一時停止されていることを要求すべきです (SHOULD)。
  • 無効化後の保証: ホルダーが開始する資産移動 (transfer/transferFromERC-721/ERC-1155相当) および通常のライフサイクル mint/burn はリバートしなければなりません (MUST)。unpause が存在する場合、リバートしなければなりません (MUST)。明示的に指定された特権的な緊急/規制操作 (例: forcedTransfer) のみが残る可能性があり (MAY)、それらは無効化後有効として文書化されなければなりません (MUST)。
  • ホルダーの退出例外: 実装は、ユーザーが自身の資金を取り戻せるように、ホルダーが開始する退出操作を開いたままにしてもよく (MAY)、一方で資本追加操作はリバートしなければなりません (MUST)。ERC-4626ボルトの場合、withdrawredeem は無効化後も呼び出し可能である可能性があり (MAY)、一方で depositmint はリバートしなければなりません (MUST)。
  • 可視性: deactivated() はリバートしないビューでなければなりません (MUST)。インデクサーは Deactivated を公開ホルダー操作の終端ライフサイクルイベントとして扱うべきです (SHOULD)。

ERC-165: 実装はERC-165をサポートし、IERC165 (0x01ffc9a7) および IERCDeactivation (0xe9cd80b0) に対して true を返さなければなりません (MUST)。


設計の選択と根拠

なぜこれほど最小限なのか? 2つの関数と1つのイベントで広範な相互運用性には十分です。追加の要件はすべて、インターフェースを実装しない理由になります。

なぜ無効化を一時停止と分離するのか? 一時停止は「今は一時停止中」を意味します。無効化は「完了、終端」を意味します。これらを混同すると、インテグレーターはライフサイクル終了に関する信頼性の高いUXや会計を構築できません。一時停止モジュールが既に存在する場合、無効化はそれと組み合わされて永続的な終端一時停止として機能します。

なぜガバナンスに中立的なのか? このERCは、特定のアクセス制御モデル、一時停止設計、または法的ワークフローを義務付けていません。それはポリシーではなく、シグナルを標準化します。

なぜデプロイメントモデルに中立的なのか? 不変コントラクトとアップグレード可能なプロキシの両方が互換性があります。しかし、正直な注意点として、プロキシのアップグレードは任意のロジックを変更できるため、この標準は deactivated() がそれ自体では、アップグレード可能なプロキシの下での不可逆性の暗号学的保証ではないことを明示しています。厳密な永続性が必要な場合は、不変デプロイメントを使用するか、アップグレード権限を不可逆的に放棄してください。プロキシの場合、インテグレーターは保守的なデフォルトを採用することを推奨されます。一度無効化されたら、ガバナンス文書に別段の記載がない限り、永続的に無効化されたものとして扱います。


このERCが定義しないこと

  • アクセス制御モデル: マルチシグ、タイムロック、ロールベース — 実装者に委ねられます。
  • 一時停止設計: 一時停止の前提条件はオプションであり、意見を述べません。
  • 法的または移行ワークフロー: オフチェーンの企業行動は範囲外です。
  • プロキシに対するオンチェーン永続性強制: インターフェースは意図を伝えます。アップグレード権限を上書きすることはできません。

未解決の質問

さらに検討が必要な点のリスト

  1. 一時停止の前提条件の強度。 現状: 一時停止メカニズムを使用する実装は、deactivateContract() が成功する前にコントラクトが一時停止されていることを要求すべきであり (SHOULD)、その前提条件が使用されているが満たされていない場合、呼び出しはリバートしなければなりません (MUST)。前提条件自体はオプションです (一時停止不可能なコントラクトも許可されます)。これは SHOULD ではなく、より強い要件 (MUST) にすべきでしょうか、それとも一時停止不可能なコントラクトを過度に制約することになるでしょうか?

  2. 関数命名。 現状: 操作は deactivateContract() と命名されており、その不可逆性は名前ではなく仕様 (一方向状態、再入時の AlreadyDeactivated()) を通じて伝えられます。deactivateContract() は適切な名前でしょうか、それとも permanentlyDeactivate() のような名前の方が呼び出しサイトで不可逆性をよりよく伝えるでしょうか?

  3. プロキシの永続性。 現状: このERCは、deactivated() がそれ自体では、アップグレード可能なプロキシの下での不可逆的なファイナリティのオンチェーン保証ではないことを明示しています。インテグレーターには保守的なデフォルト (ガバナンス文書に別段の記載がない限り、永続的に無効化されたものとして扱う) を採用することを推奨し、厳密な永続性が必要な場合は不変デプロイメントまたはアップグレード権限の放棄を提案していますが、これに対するオンチェーンシグナルは標準化していません。「保守的なデフォルト」のガイダンスで十分でしょうか、それともERCはオンチェーンフラグ (例: アップグレード権限が放棄されたかどうかを公開する) を推奨すべきでしょうか?

  4. 無効化後の保証。 現状: deactivated() == true の後、ホルダーが開始する資産移動およびすべての非特権/非ビュー/非ピュアなホルダー操作はリバートしなければならず (MUST)、通常のライフサイクル mint/burn はリバートしなければならず (MUST)、unpause (存在する場合) はリバートしなければなりません (MUST)。明示的に指定された特権的な緊急/規制操作 (例: forcedTransfer) のみが利用可能である可能性があり (MAY)、利用可能なものはすべて無効化後有効として文書化されなければなりません (MUST)。名前のない特権操作はリバートしなければなりません (MUST)。このデフォルトのセットは、RWAとDeFiの両方のユースケースに適しているでしょうか?

  5. インターフェースIDとイベント。 現状: インターフェースは、deactivateContract() によって一度発行される単一の Deactivated(address indexed account) イベントを公開し、ERC-165を介してインターフェースID 0xe9cd80b0 をアドバタイズします。無効化後に実行される特権操作のための個別のイベントはありません。0xe9cd80b0 は合意可能でしょうか、それとも追加のイベント (例: 無効化後の特権操作が実行されたときの明確なシグナル) が必要でしょうか?


先行技術と参考文献

  • ERC-165 — インターフェース検出標準。このERCで必須とされています。
  • ERC-20ERC-721ERC-1155 — このインターフェースが構成されるベーストークン標準。
  • Pausableトークンパターン (例: OpenZeppelin Pausable) — 無効化はこれらの上に永続的な終端一時停止として機能します。

ご意見がありましたらお知らせください。

PR: Add ERC: Contract Deactivation by rya-sge · Pull Request #1900 · ethereum/ERCs · GitHub

1投稿 - 1参加者

トピック全文を読む