[ERC2767] ERC20トークンを使用した分散型のガバナンスの仕組みを理解しよう！

# はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、**ERC20**トークンを使用した、分散的な投票ベースのガバナンスの仕組みを提案している**ERC2767**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

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

他にも様々なEIPについてまとめています。

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

# 概要

**ERC2767**は、**ERC20**トークンを使って投票権を分配するガバナンス用スマートコントラクトのAPIを提案しています。
このガバナンスコントラクトは、他のスマートコントラクトの管理権限（オーナーシップ）を保持する設計となっており、**ERC173**（オーナーシップの標準仕様）に対応する既存のコントラクトに対しても、秘密鍵ベースのウォレットによる所有からガバナンスコントラクトによる所有へと移行可能です。

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

https://qiita.com/cardene/items/0b8cdc156404920a8cbd

# 動機

従来、多くのスマートコントラクトでは、管理者による操作や資金の引き出しなどを行うために**ERC173**のようなオーナーシップ標準が用いられてきました。
例えば以下のようなコードがその典型です。

```js
contract dApp {
  function doSomethingAdministrative() external onlyOwner {
    // 単一のウォレットによって行われる管理ロジック
  }
}
```

しかし、この設計では以下の問題があります。

- プロジェクトの分散性が信頼に依存してしまい、実際には単一のウォレットの管理者に権限が集中することになる
- 管理者の秘密鍵が漏洩した場合のセキュリティリスクが高い
- 緊急対応（Rescue操作）などでの判断がガバナンスによらず個人の判断になる

さらに、現在の多くのガバナンス実装（例：Compound、Uniswap、Sushiswap）は独自のAPIを持っており、ユーザーがそれぞれの専用UIを訪問しないとガバナンス状況を確認できません。
これは、もし**ERC20**が存在していなかったら、トークンごとに異なるブロックエクスプローラーが必要になるようなものです。

そのため、ガバナンスに関しても標準APIを導入することで、Etherscanなどの一般的なツールがガバナンス情報を統一的に表示でき、ユーザーにとっての透明性と信頼性が向上します。
加えて、**ERC20**ベースのトークンをそのままガバナンストークンとして使えるため、既存のツール群との互換性も高く導入が容易です。

これにより、従来の秘密鍵によるオーナーシップに依存した設計から、標準化されたコントラクトベースのガバナンスへと移行する流れが加速することが期待されます。

# 仕様

**ERC2767**は、ガバナンス用スマートコントラクトの標準インターフェースを定義しています。
このコントラクトは**ERC20トークンによって投票権が分配される設計となっており、他のスマートコントラクトの管理権限（オーナーシップ）を保持できます。

この仕様を実装することで、さまざまなプロジェクト間で共通のガバナンスAPIが提供されるようになり、ツールによる自動識別や情報取得が可能となります。
これは透明性の向上とユーザーの理解促進に寄与します。

## インターフェース

```js:ERC2767.sol
/// @title ERC-2767 Governance
/// @dev ERC-165 InterfaceID: 0xd8b04e0e
interface ERC2767 is ERC165 {
    /// @notice Gets number votes required for achieving consensus
    /// @dev Should cost less than 30000 gas
    /// @return Required number of votes for achieving consensus
    function quorumVotes() external view returns (uint256);

    /// @notice The address of the Governance ERC20 token
    function token() external view returns (address);
}
```

### `quorumVotes`

```javascript
function quorumVotes() external view returns (uint256);
```

ガバナンスにおいて合意形成（コンセンサス）に必要な票数を返す関数。
投票による意思決定を行う際に、提案を通過させるために必要な最小の票数（クオーラム）を取得します。
この値は固定であっても、動的（例：総発行量の51%）であっても問題ありません。
ガスコストは`30,000`未満であるべきです。

**戻り値**

* `uint256`
    * 合意形成に必要な票数。

### `token`

```javascript
function token() external view returns (address);
```

このガバナンスコントラクトが利用する**ERC20**トークンのアドレスを返す関数。
投票権を分配するための**ERC20**トークンのコントラクトアドレスを返します。
トークン機能がガバナンスコントラクト自身に含まれている場合は `address(this)` を返すことも可能です。
なお、**ERC20**の発行量が変動する場合でも、クオーラムの計算を柔軟に対応できる設計が推奨されます。

**戻り値**

* `address`
    * **ERC20**トークンのコントラクトアドレス。

## ガバナンストークンとの連携

この仕様では、投票権の根拠となる**ERC20**トークンを明示的に定義し、`token()` でそのアドレスを取得できるようにします。
**ERC20**の機能をガバナンスコントラクト自体に内包する場合には、`token()` が `address(this)` を返す構成も許可されています。

その際、Diamond Standard（**ERC2535**）のようなアップグレード可能なアーキテクチャを採用することで、ガバナンス機能とトークン機能の統合によるコードサイズの最適化が可能です。

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

https://qiita.com/cardene/items/51fc6fc998421c4d931a

## クオーラム計算の柔軟性

`quorumVotes()` は固定値を返しても問題ありませんが、**ERC20**の`totalSupply()`が変動する場合には、クオーラム票数が全体に対する割合として設計されることが望ましいです。
例えば、「総発行量の51%」というような設計が可能であり、投票システムの公平性が保たれます。

## ERC165による識別機能

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

https://qiita.com/cardene/items/541184977a5cba51b759

### `supportsInterface`

```javascript
function supportsInterface(bytes4 interfaceID) external view returns (bool);
```

コントラクトが特定のインターフェース（ここでは**ERC2767**）を実装しているかを判定する関数。
**ERC165**仕様に基づいて、`interfaceID`を受け取り、そのIDがサポートされているかを判定します。
**ERC2767**のインターフェースIDは `0xd8b04e0e` であり、これを返すことでツールがこのコントラクトをガバナンス対応コントラクトとして自動認識できるようになります。

**引数**

* `interfaceID`
    * 判定対象となるインターフェースID（`bytes4` 型）。

**戻り値**

* `bool`
    * 対象インターフェースがサポートされていれば `true`、そうでなければ `false`。

### `ERC165`

```javascript
interface ERC165 {
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

コントラクトがどのインターフェースをサポートしているかを照会するためのインターフェース。
**ERC165**は、ツールが**動的にインターフェースの互換性をチェックするための標準仕様**です。これを実装することで、ガバナンス対応コントラクトが外部から明示的に識別可能になります。

**パラメータ**

* `interfaceID`
    * 照会対象となるインターフェースID（`bytes4` 型）。

# 補足

**ERC2767**の目的は、ガバナンス機能を標準化することで、より多くのプロジェクトが透明性のある管理体制を実現できるようにすることです。
以下のような意図があります。

* ガバナンスコントラクトのAPIを標準化することで、分析ツールやダッシュボードの開発を容易にします。
* 大規模プロジェクトにおいて、最大50名程度までの所有者しか設定できないマルチシグよりも、**ERC20**ベースの重み付きガバナンスの利用を推奨します。
* 既存の**ERC173**互換コントラクトが、カスタムUIを作成することなくガバナンスに移行できるよう支援します。
* 監査済みのガバナンスコントラクトの公開利用を推進し、**ERC20**と同様に誰でも安全な実装を活用できるようにします。
* 既存の**ERC20**向け分析ツールを、そのままガバナンストークン分析にも利用できるようにします。
* 複数プロジェクトのガバナンス情報に連携するような将来のプロトコルを実現可能にします。
* **ERC2767**はあえて最小限の機能だけにとどめ、他のEIPで特定機能の標準化を進められるようにします。

# 互換性

**ERC173**に準拠した既存のスマートコントラクトは、所有権を**ERC2767**に準拠したガバナンスコントラクトへ移譲することで、そのままガバナンス制御可能な構成へと移行できます。

ただし、現在すでに運用されている多くのガバナンスシステム（例：Compound, Uniswap, Sushiswap）は独自のAPIを持っており、標準化が存在しなかったため、ツール側でプロジェクトごとに個別対応が必要となっています。

**ERC2767**に準拠するための方法として、以下のようなアプローチが可能です。

新しい**ERC2767**準拠のガバナンスコントラクトをデプロイし、既存コントラクトの所有権を移譲することで対応可能です。
これは特に、Multi-sigをガバナンスに使用していたプロジェクトに適しています。

一方で、再デプロイが困難な場合や、既存ガバナンスが**ERC20**に似た重み付き投票構造を持っている場合、フォワーダーコントラクトという手法で対応できます。
これは、**ERC2767**に準拠したラッパーを介して、既存の非標準APIを透過的に呼び出す方法です。
分析ツールはこのフォワーダーコントラクトを対象にすることで、カスタムコードなしに情報を取得可能になります。

なお、このフォワーダーコントラクトの仕様はこのEIPの範囲外とされており、必要であれば別のEIPで規定される予定です。

**ERC2767**の本質的な特徴は「**ガバナンスの分散性の強化と透明性の向上**」にありますが、それによって以下のようなセキュリティ的利点も得られます。

* **秘密鍵に依存しない管理体制**
    * **ERC173**のような単一オーナー制では、鍵の漏洩が致命的でしたが、**ERC2767**により分散された投票での管理が可能となります。
* **既知のインターフェースによる識別**
    * **ERC165**との連携によって、外部ツールからガバナンスコントラクトとして識別できるようになり、不正または偽装された契約との区別が容易になります。
* **再利用可能な監査済み実装**
    * 標準化されたガバナンスコントラクトは、第三者によるレビューや監査が容易になり、再利用されることでセキュリティリスクを低減できます。
* **プロジェクトごとのカスタム実装に依存しない**
    * 独自ガバナンスの構築を避けられることで、実装ミスや過剰な複雑化によるバグや脆弱性のリスクを減らします。

このように、**ERC2767**は機能性だけでなく、セキュリティ観点からも現代的なプロジェクトにとって望ましい設計となっています。

# セキュリティ

**ERC2767**では、ガバナンスの合意形成（コンセンサス）をオンチェーンで行うか、オフチェーンで行うかは実装者に委ねられており、明確な実装仕様は定義されていません。
それぞれの方式において、考慮すべきポイントがいくつか挙げられています。

## オンチェーンガバナンス

オンチェーン方式では、コミュニティのメンバーがトランザクション提案を作成し、それに対してオンチェーンで投票を行う構成になります。
この方式の主な利点は、透明性と即時の検証可能性です。

**ダブルボーティング（二重投票）の防止策**として、[OpenZeppelinのSnapshot機能](https://docs.openzeppelin.com/contracts/4.x/api/governance#IGovernor-getVotes)を活用できます。
これは、特定ブロック時点でのトークン保有状況を固定し、後からトークンを移動させてもその投票には影響しないようにする仕組みです。

## オフチェーンガバナンス

オフチェーン方式では、署名を用いた投票や意思表明を参加者が行い、それを後からオンチェーンに送信して実行する形になります。
この方式はガス代の削減や柔軟な設計が可能ですが、署名の検証やリプレイ攻撃に対する対策が必要です。

署名の形式としては、**ERC191**や**ERC712**の推奨仕様に従うことで、安全性と互換性を保つことができます。

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

https://qiita.com/cardene/items/ee4edd15ad6fe7f58f7e

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

https://qiita.com/cardene/items/f54bc85cb66de5a54257

リプレイ攻撃（過去の署名の再利用）を防ぐためには、署名者のアドレス順にソートしてから処理することが望ましいとされています。
これにより、同一の署名セットを異なる順序で再提出されることによる不正実行のリスクを軽減できます。

このように、ガバナンス方式の選択によって考慮すべきセキュリティポイントが異なり、それぞれに応じた実装と対策が求められます。
標準仕様としては明示的な実装を含まないため、今後の別のEIPで詳細を標準化することが想定されています。

# 引用

Soham Zemse (@zemse), Nick Mudge (@mudgen), "ERC-2767: Contract Ownership Governance [DRAFT]," Ethereum Improvement Proposals, no. 2767, July 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2767.

# 最後に

今回は「**ERC20**トークンを使用した、分散的な投票ベースのガバナンスの仕組みを提案している**ERC2767**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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