[ERC4824] DAOのためのAPIの仕組みを理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、オンチェーンとオフチェーンを繋ぐ、分散型自律組織（DAO）のためのAPIの仕組みを提案している規格である**ERC4824**についてまとめていきます！

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

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

:::note warn
**4824**は現在（2023年12月14日）では「**Draft**」段階です。
:::

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

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

# 概要

この提案では分散型自律組織（DAO）のためのAPI規格について説明しています。

このAPI規格は、ブロックチェーン上（オンチェーン）とブロックチェーン外（オフチェーン）の活動を連携させるためのものです。
具体的には以下のようになります。

## オンチェーンのやり取り
これは、ブロックチェーン上で行われるコントラクトや取引を指します。
たとえば、**ERC20**や**ERC721**などのトークンを使って、DAOのメンバーがどのように所有権や投票権を持つかを表現します。

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

https://chaldene.net/erc20

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

https://chaldene.net/erc721

## オフチェーンのやり取り
これは、ブロックチェーン外で行われる活動を指し、メンバー間の議論や提案の内容、投票による意思決定などが含まれます。

このAPI規格の目的は、オンチェーンとオフチェーンの情報をスムーズにつなぎ、DAOの運営を効率的で透明にすることです。
メンバーシップの確認、投票権の管理、提案の提出と追跡などが、ブロックチェーン技術を通じて行われます。
これにより、DAO内のロールや責任が明確になり、提案の進行状況を追跡しやすくなり、投票が正確かつ公正に行われるようになります。

:::note info
このAPI規格は、ブロックチェーンの技術的なメリットとオフチェーンの現実の複雑さを組み合わせることで、DAOの運営を改善することを目指しています。
:::

# 動機

分散型自律組織（DAO）は、イーサリアムのホワイトペーパーで初めて提案されたものですが、その定義は今でもはっきりしていません。
その結果、色々なタイプのDAOが登場しましたが、これらの間で共通のルールや、互いに連携するための基準がほとんどありません。

この問題を解決するために、**ERC721**で使われている`tokenURI`のような、標準化された`daoURI`が提案されています。
これは、DAOを簡単に見つけたり、その内容を理解しやすくしたり、異なるツールやシステム間でスムーズに連携できるようにするためのものです。

つまり、`daoURI`は、DAOをもっと使いやすく、互いに連携しやすくするための「**住所**」や「**名札**」のようなものです。
これによって、DAOの世界がもっと統一され、将来の発展に向けての土台が作られることになります。

# 仕様

**ERC4824**は、分散型自律組織（DAO）のための新しいイーサリアムのインターフェース規格です。
これは、DAOの情報を整理してアクセスしやすくするために設計されています。

この規格に準拠するコントラクトは以下の**ERC4824**インターフェースを実装する必要があります。

```javascript
pragma solidity ^0.8.1;

/// @title ERC-4824 DAOs
/// @dev See <https://eips.ethereum.org/EIPS/eip-4824>
interface IERC-4824 {
    event DAOURIUpdate(address daoAddress, string daoURI);

    /// @notice A distinct Uniform Resource Identifier (URI) pointing to a JSON object following the "ERC-4824 DAO JSON-LD Schema". This JSON file splits into four URIs: membersURI, proposalsURI, activityLogURI, and governanceURI. The membersURI should point to a JSON file that conforms to the "ERC-4824 Members JSON-LD Schema". The proposalsURI should point to a JSON file that conforms to the "ERC-4824 Proposals JSON-LD Schema". The activityLogURI should point to a JSON file that conforms to the "ERC-4824 Activity Log JSON-LD Schema". The governanceURI should point to a flatfile, normatively a .md file. Each of the JSON files named above can be statically-hosted or dynamically-generated.
    function daoURI() external view returns (string memory _daoURI);
}
```

前述している**DAO JSON-LD スキーマ**は以下になります。

```json
{
    "@context": "http://www.daostar.org/schemas",
    "type": "DAO",
    "name": "<name of the DAO>",
    "description": "<description>",
    "membersURI": "<URI>",
    "proposalsURI": "<URI>",
    "activityLogURI": "<URI>",
    "governanceURI": "<URI>",
    "contractsURI": "<URI>"
}
```

これは、DAOの基本的な情報（名前、説明など）を定義するためのフォーマットです。
これにより、DAOの情報が一元化され、わかりやすくなります。

DAOはこの**ERC4824**規格を直接実装することも、別の外部コントラクトを通じてこの規格に準拠することもできます。
外部コントラクトを使う場合は、DAOの主アドレスを記録する必要があります。
また、`daoURI`の更新機能を持つ方法を定義することが推奨されます。

:::note info
**ERC4824**はDAOの情報を整理し、誰でも簡単にアクセスできるようにするための新しいルールです。
これによって、DAOがもっと透明で効率的に運営されることを目指しています。
:::

```javascript
pragma solidity ^0.8.1;

/// @title ERC-4824 Common Interfaces for DAOs
/// @dev See <https://eips.ethereum.org/EIPS/eip-4824>
/// @title ERC-4824: DAO Registration
contract ERC-4824Registration is IERC-4824, AccessControl {
    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");

    string private _daoURI;

    address daoAddress;

    constructor() {
        daoAddress = address(0xdead);
    }

    /// @notice Set the initial DAO URI and offer manager role to an address
    /// @dev Throws if initialized already
    /// @param _daoAddress The primary address for a DAO
    /// @param _manager The address of the URI manager
    /// @param daoURI_ The URI which will resolve to the governance docs
    function initialize(
        address _daoAddress,
        address _manager,
        string memory daoURI_,
        address _ERC-4824Index
    ) external {
        initialize(_daoAddress, daoURI_, _ERC-4824Index);
        _grantRole(MANAGER_ROLE, _manager);
    }

    /// @notice Set the initial DAO URI
    /// @dev Throws if initialized already
    /// @param _daoAddress The primary address for a DAO
    /// @param daoURI_ The URI which will resolve to the governance docs
    function initialize(
        address _daoAddress,
        string memory daoURI_,
        address _ERC-4824Index
    ) public {
        if (daoAddress != address(0)) revert AlreadyInitialized();
        daoAddress = _daoAddress;
        _setURI(daoURI_);

        _grantRole(DEFAULT_ADMIN_ROLE, _daoAddress);
        _grantRole(MANAGER_ROLE, _daoAddress);

        ERC-4824Index(_ERC-4824Index).logRegistration(address(this));
    }

    /// @notice Update the URI for a DAO
    /// @dev Throws if not called by dao or manager
    /// @param daoURI_ The URI which will resolve to the governance docs
    function setURI(string memory daoURI_) public onlyRole(MANAGER_ROLE) {
        _setURI(daoURI_);
    }

    function _setURI(string memory daoURI_) internal {
        _daoURI = daoURI_;
        emit DAOURIUpdate(daoAddress, daoURI_);
    }

    function daoURI() external view returns (string memory daoURI_) {
        return _daoURI;
    }

    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override returns (bool) {
        return
            interfaceId == type(IERC-4824).interfaceId ||
            super.supportsInterface(interfaceId);
    }
}
```

--- 

### `MANAGER_ROLE`

```javascript
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
```

**概要**

**MANAGER_ROLE**という文字列をハッシュ化した定数。
**詳細**
特定のロールを識別するのに使用されます。
**MANAGER_ROLE**は特定のロールを表し、コントラクト内でのアクセス制御や権限管理に関連するロールを識別します。

---

### `_daoURI`

```javascript
string private _daoURI;
```

**概要**

DAOのURI（Uniform Resource Identifier）を格納する変数。

**詳細**

DAOのURIを格納するためのプライベート変数であり、コントラクト内でのみアクセス可能です。
DAOのURIは、外部から契約に関する情報を取得するために使用される場合があります。

---

### `daoAddress`

```javascript
address daoAddress;
```

**概要**

DAOのアドレスを格納する変数。

**詳細**

コントラクト内でDAOに関連する操作を実行する際に、対象のDAOのアドレスが指定できます。

---

### `initialize`

```javascript
function initialize(
    address _daoAddress,
    address _manager,
    string memory daoURI_,
    address _ERC-4824Index
) external
```

**概要**

初期のDAO URIを設定し、マネージャーのロールを指定のアドレスに付与する関数。

**詳細**

この関数は初期化用のもので、既に初期化されている場合にはエラーを発生させます。
指定されたDAOアドレス、マネージャーのアドレス、DAO URI、**ERC4824Index**アドレスを受け取ります。
初期化後にマネージャーロールが指定のアドレスに授与されます。

**引数**

- `_daoAddress`
  - 初期のDAOアドレス。
- `_manager`
  - URIマネージャーのアドレス。
- `daoURI_`
  - 解決されるDAOドキュメントへのURI。
- `_ERC-4824Index`
  - ERC-4824Indexのアドレス。

---

### `initialize`

```javascript
function initialize(
    address _daoAddress,
    string memory daoURI_,
    address _ERC-4824Index
) public
```

**概要**

初期のDAO URIを設定する関数。

**詳細**

この関数は初期化用のもので、既に初期化されている場合にはエラーを発生させます。
指定されたDAOアドレス、DAO URI、**ERC4824Index**アドレスを受け取ります。
初期化後、DAOアドレスにデフォルトの管理者役割が授与され、DAOアドレスにマネージャーロールが付与されます。
また、**ERC4824Index**に登録情報を記録します。

**引数**

- `_daoAddress`
  - 初期のDAOアドレス。
- `daoURI_`
  - 解決されるDAOドキュメントへのURI。
- `_ERC-4824Index`
  - ERC-4824Indexのアドレス。

---

### `setURI`

```javascript
function setURI(string memory daoURI_) public onlyRole(MANAGER_ROLE)
```

**概要**

DAOのURIを更新する関数。

**詳細**

この関数は、マネージャーロールを持つアカウントからのみ呼び出すことができます。
指定されたDAO URIを設定します。

**引数**

- `daoURI_`
  - 解決されるDAOドキュメントへのURI。

---

### `_setURI`

```javascript
function _setURI(string memory daoURI_) internal
```

**概要**

DAOのURIを設定する関数。

**詳細**

この関数は内部で使用され、指定されたDAO URIを設定します。
デフォルトでは外部からアクセスできないようになっています。

**引数**

- `daoURI_`
  - 解決されるDAOドキュメントへのURI。

---

### `daoURI`

```javascript
function daoURI() external view returns (string memory daoURI_)
```

**概要**

現在のDAO URIを取得する関数。

**詳細**

この関数は外部から呼び出すことができ、現在設定されているDAO URIを返します。

**戻り値**

- `daoURI_`
  - 現在のDAO URI。

---

## インデックス化

**ERC4824**はDAO（分散型自律組織）のための新しいルールで、これを使うとDAOがネットワーク上で見つけやすくなります。

:::note info
インデクサーコントラクトにDAOが登録されると、いくつかの重要な利点があります。

- **見つけやすさ**
    - インデクサーコントラクトに登録することで、DAOはネットワーク内で簡単に見つけられるようになります。
    - これは、人々が特定のDAOを検索し、その情報にアクセスする際に役立ちます。
- **データの整理とアクセス性の向上**
    - インデクサーはDAOに関連する情報（メンバー、提案、ガバナンスの文書など）を整理し、それらに簡単にアクセスできるようにします。
    - これにより、DAOの透明性と効率が向上します。
- **ネットワーク全体の効率**
    - インデクサーコントラクトを通じてDAOがシステム化されると、ネットワーク全体のデータ処理と管理の効率が向上します。
    - これにより、DAOエコシステム全体がスムーズに機能するようになります。
- **相互運用性**
    - インデクサーコントラクトを使用することで、異なるDAO間の相互運用性が向上します。
    - これにより、異なるDAOが協力しやすくなったり、互いのリソースを共有しやすくなります。
- **自動化と統合**
    - インデクサーコントラクトによって提供される標準化されたデータアクセスポイントを使用することで、DAOの運営に関連するさまざまなプロセスやツールを自動化し、統合することが容易になります。

インデクサーコントラクトへの登録は、DAOの発見性、アクセス性、効率性を高め、より広いエコシステム内での相互作用と統合を促進します。
:::

### DAOファクトリーとインデクサーコントラクト
DAOが**ERC4824**ルールに沿った「**DAOファクトリー**」というシステムから生まれる場合、そのスタート時に「**インデクサーコントラクト**」という別のシステムを使います。
これは、DAOをネットワーク上で効率的に見つけるために必要です。

### ERC165準拠のDAO
もしDAOが別のルールである**ERC165**にも従っている場合、DAOファクトリーは特別な許可なしでインデクサーコントラクトを使えます。

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

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

### ERC165非準拠のDAO
**ERC-165**に従っていないDAOの場合、DAOファクトリーはまずインデクサーコントラクトを使うための特別な権限を得て、その後にDAOの情報（`daoURI`というアドレス）をインデクサーコントラクトに登録します。

### `logRegistration`関数の使用
`logRegistration`は特別な関数で、DAO自身や他の人がこの関数を使って**ERC4824**に従うDAOをインデクサーコントラクトに登録できます。
これが**ERC165**にも従っていれば、もっと簡単です。

:::note info
**ERC4824**はDAOを簡単に見つけられるようにするための新しいシステムで、DAOがどのように作られ、どのルールに従っているかによって、登録の方法が少し変わります。
これにより、DAOの発見や管理がスムーズになります。
:::

```javascript
pragma solidity ^0.8.1;

error ERC-4824InterfaceNotSupported();

contract ERC-4824Index is AccessControl {
    using ERC165Checker for address;

    bytes32 public constant REGISTRATION_ROLE = keccak256("REGISTRATION_ROLE");

    event DAOURIRegistered(address daoAddress);

    constructor() {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(REGISTRATION_ROLE, msg.sender);
    }

    function logRegistrationPermissioned(
        address daoAddress
    ) external onlyRole(REGISTRATION_ROLE) {
        emit DAOURIRegistered(daoAddress);
    }

    function logRegistration(address daoAddress) external {
        if (!daoAddress.supportsInterface(type(IERC-4824).interfaceId))
            revert ERC-4824InterfaceNotSupported();
        emit DAOURIRegistered(daoAddress);
    }
}
```

---

### `REGISTRATION_ROLE`

```javascript
bytes32 public constant REGISTRATION_ROLE = keccak256("REGISTRATION_ROLE");
```

**概要**

DAO URIの登録に必要なロールを示す定数。

**詳細**

`REGISTRATION_ROLE`は、DAO URIを登録するために必要なロールを識別するために使用されます。
このロールを持つアカウントは、DAOのURIを登録する権限を持ちます。

---

### `DAOURIRegistered`

```javascript
event DAOURIRegistered(address daoAddress);
```

**概要**

DAOのURIが登録されたことを通知するイベント。

**詳細**

DAOのURIが正常に登録された場合に発行されます。
このイベントは、URIが登録されたことをトリガーとして他のアクションを実行するために使用されることがあります。

**パラメータ**

- `daoAddress`
  - URIが登録されたDAOのアドレス。

---

### `logRegistrationPermissioned`

```javascript
function logRegistrationPermissioned(address daoAddress) external onlyRole(REGISTRATION_ROLE) {
    emit DAOURIRegistered(daoAddress);
}
```

**概要**

特定のロールを持つアカウントによって呼び出された場合に、DAOのURIが登録されたことを通知する関数。

**詳細**

`REGISTRATION_ROLE`ロールを持つアカウントによってのみ呼び出すことができます。
この関数は、特別な権限を持つアカウントによって、DAOのURIが正常に登録されたことを通知するために使用されます。

**引数**

- `daoAddress`
  - 登録されたDAOのアドレス。

---

### `logRegistration`

```javascript
function logRegistration(address daoAddress) external {
    if (!daoAddress.supportsInterface(type(IERC-4824).interfaceId))
        revert ERC-4824InterfaceNotSupported();
    emit DAOURIRegistered(daoAddress);
}
```

**概要**

URIの登録をログに記録する関数。

**詳細**

指定されたDAOのアドレスを受け取り、そのDAOが**IERC4824**インターフェースをサポートしているかどうかを確認します。
サポートされていない場合、エラーが発生します。
サポートされている場合、DAOのURIが正常に登録されたことを通知するために使用されます。

**引数**

- `daoAddress`
  - 登録されたDAOのアドレス。

---

分散型自律組織（DAO）が、自分の情報を他の人やシステムが簡単に見つけられるようにするためには、外部の登録コントラクトを使います。
このとき、効果的にネットワークに自分の情報を登録するためには、共通の「**登録ファクトリーコントラクト**」というツールを使うことが良いとされています。
さらに、この登録ファクトリーコントラクトは、情報を整理して見つけやすくする「**インデクサー**」と呼ばれるシステムと連携します。

つまり、DAOはこれらのツールを使って、自分の存在や活動をネットワーク上で効率よく表示し、他の人たちが簡単にアクセスできるようにするわけです。
これにより、DAOの管理や追跡がスムーズになります。

```javascript
pragma solidity ^0.8.1;

/// @title ERC-4824 Common Interfaces for DAOs
/// @dev See <https://eips.ethereum.org/EIPS/eip-4824>

contract CloneFactory {
    // implementation of eip-1167 - see https://eips.ethereum.org/EIPS/eip-1167
    function createClone(address target) internal returns (address result) {
        bytes20 targetBytes = bytes20(target);
        assembly {
            let clone := mload(0x40)
            mstore(
                clone,
                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
            )
            mstore(add(clone, 0x14), targetBytes)
            mstore(
                add(clone, 0x28),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
            )
            result := create(0, clone, 0x37)
        }
    }
}

contract ERC-4824RegistrationSummoner {
    event NewRegistration(
        address indexed daoAddress,
        string daoURI,
        address registration
    );

    address public ERC-4824Index;
    address public template; /*Template contract to clone*/

    constructor(address _template, address _ERC-4824Index) {
        template = _template;
        ERC-4824Index = _ERC-4824Index;
    }

    function registrationAddress(
        address by,
        bytes32 salt
    ) external view returns (address addr, bool exists) {
        addr = Clones.predictDeterministicAddress(
            template,
            _saltedSalt(by, salt),
            address(this)
        );
        exists = addr.code.length > 0;
    }

    function summonRegistration(
        bytes32 salt,
        string calldata daoURI_,
        address manager,
        address[] calldata contracts,
        bytes[] calldata data
    ) external returns (address registration, bytes[] memory results) {
        registration = Clones.cloneDeterministic(
            template,
            _saltedSalt(msg.sender, salt)
        );

        if (manager == address(0)) {
            ERC-4824Registration(registration).initialize(
                msg.sender,
                daoURI_,
                ERC-4824Index
            );
        } else {
            ERC-4824Registration(registration).initialize(
                msg.sender,
                manager,
                daoURI_,
                ERC-4824Index
            );
        }

        results = _callContracts(contracts, data);

        emit NewRegistration(msg.sender, daoURI_, registration);
    }
}
```

---

### `NewRegistration`

```javascript
event NewRegistration(
    address indexed daoAddress,
    string daoURI,
    address registration
);
```

**概要**

新しい登録が行われた時に発行されるイベント。

**詳細**

DAOのURIの新規登録が行われたときに発行されます。
このイベントは、DAOのURIが正常に登録されたことを記録し、トランザクションのトレースや監視に使用されます。

**パラメータ**

- `daoAddress`
  - 登録されたDAOのアドレス。
- `daoURI`
  - 登録されたDAOのURI。
- `registration`
  - 登録を行ったアドレス。

### `ERC4824Index`

```javascript
address public ERC-4824Index;
```

**概要**

**ERC4824**インデックスのアドレスを保持する変数。

### `template`

```javascript
address public template; /*Template contract to clone*/
```

**概要**

クローンするためのテンプレートコントラクトのアドレスを保持する変数。

---

### `registrationAddress`

```javascript
function registrationAddress(
    address by,
    bytes32 salt
) external view returns (address addr, bool exists)
```

**概要**

登録アドレスとその存在を取得する関数。

**詳細**

指定された`by`アドレスと`salt 値から登録アドレスを予測し、そのアドレスの存在を確認します。
登録アドレスが予測され、コードが存在する場合、`exists`は`true`に設定されます。

**引数**

- `by`
  - 予測される登録アドレスを決定するためのアドレス。
- `salt`
  - アドレス予測に使用される`salt`値。

**戻り値**

- `addr`
  - 予測された登録アドレス。
- `exists`
  - 予測された登録アドレスが存在する場合は`true`、存在しない場合は`false`。

### `summonRegistration`

```javascript
function summonRegistration(
    bytes32 salt,
    string calldata daoURI_,
    address manager,
    address[] calldata contracts,
    bytes[] calldata data
) external returns (address registration, bytes[] memory results)
```

**概要**

登録を作成し初期化する関数。

**詳細**

指定された`salt`値を使用して新しい登録を予測し、その登録をクローン化して初期化します。
初期化には、DAOのURI、マネージャーアドレス、コントラクトアドレス、データが含まれます。
初期化が完了したら、新しい登録のアドレスと関数実行の結果を返します。
また、`NewRegistration`イベントを発行します。

**引数**

- `salt`
  - 登録アドレスを予測するための`salt`値。
- `daoURI_`
  - DAOのURI。
- `manager`
  - マネージャーアドレス。 `address(0)` の場合はマネージャーなし。
- `contracts`
  - コントラクトアドレスの配列。
- `data`
  - データの配列。

**戻り値**

- `registration`
  - 新しい登録のアドレス。
- `results`
  - 関数実行の結果を含むバイト配列の配列。

---

## メンバー

「**Members JSON-LD Schema**」は、分散型自律組織（DAO）のメンバー情報を整理するためのデータフォーマットです。
このEIP（改善提案）に従うコントラクトは、`membersURI`という特定の機能を持っているべきです。
この`membersURI`は、DAOのメンバーに関する情報を含むJSONファイルへのリンクを指します。
このJSONファイルは「**Members JSON-LD Schema**」という決められたフォーマットに従っている必要があります。

:::note info
DAOを管理するコントラクトは、DAOのメンバーについての情報を一定の形式で整理し、その情報に簡単にアクセスできるようにするリンク（`membersURI`）を提供する必要があります。
これにより、誰でもDAOのメンバーに関する情報を簡単に見つけて理解することができるようになります。
:::

```json
{
    "@context": "<http://www.daostar.org/schemas>",
    "type": "DAO",
    "name": "<name of the DAO>",
    "members": [
        {
            "type": "EthereumAddress",
            "id": "<address or other identifier>"
        },
        {
            "type": "EthereumAddress",
            "id": "<address or other identifier>"
        }
    ]
}
```

## 提案

「**Proposals JSON-LD Schema**」とは、分散型自律組織（DAO）の提案情報を整理するための特定のデータフォーマットです。
このEIP（改善提案）に従うコントラクトは、`proposalsURI`というリンクを持つ必要があります。
このリンクは、提案情報を含むJSONファイルを指し示します。

このスキーマには、次のような情報が含まれます。

- **提案IDの形式**
    - ブロックチェーン上の提案は、特定のアドレス（`CAIP10_ADDRESS`）と提案番号（`PROPOSAL_COUNTER`）を組み合わせたIDを持ちます。
    - ブロックチェーン外の提案は、似たような形式のIDを使用し、アドレスの部分を適切なURIやURLに置き換えます。

- **JSONファイルの内容**
    - このファイルには、DAOの名前、提案のリストが含まれます。
    - 各提案には、タイプ、ID、名前、内容へのリンク（`contentURI`）、状態、そしてコールデータ（操作の種類、送信元と送信先のアドレス、値、コールデータ）が含まれます。

:::note info
「**Proposals JSON-LD Schema**」は、DAOの提案をきちんと整理して、誰でも簡単にアクセスできるようにするためのフォーマットです。
そして、それを使うコントラクトは、このフォーマットに基づいた提案情報へのリンク（`proposalsURI`）を提供する必要があります。
これにより、DAOの提案がより透明で効率的に管理されます。
:::

```json
{
    "@context": "http://www.daostar.org/schemas",
    "type": "DAO",
    "name": "<name of the DAO>",
    "proposals": [
        {
            "type": "proposal",
            "id": "<proposal ID>",
            "name": "<name or title of proposal>",
            "contentURI": "<URI to content or discussion>",
            "status": "<status of proposal>",
            "calls": [
                {
                    "type": "CallDataEVM",
                    "operation": "<call or delegate call>",
                    "from": "<EthereumAddress>",
                    "to": "<EthereumAddress>",
                    "value": "<value>",
                    "data": "<call data>"
                }
            ]
        }
    ]
}
```

## アクティビティログ

「**Activity Log JSON-LD Schema**」とは、分散型自律組織（DAO）の活動を記録するためのデータ形式です。
このEIP（改善提案）に従うコントラクトは、`activityLogURI`というリンクを持ち、これは活動ログの情報が入ったJSONファイルを指します。

このスキーマの主な内容は以下の通りです。

- DAOの名前や活動ログのタイプ。
- 各活動の詳細情報。
    - これには、活動の一意のID、活動のタイプ、関連する提案のID、関連するメンバーのEthereumアドレスなどが含まれます。

このフォーマットを使用することで、DAOのさまざまな活動（例えば提案の作成や投票）を整理し、それらの活動に関連するメンバーの情報も記録します。
これにより、誰でも簡単にDAOの活動を見ることができ、DAOの透明性が高まります。

:::note info
「**Activity Log JSON-LD Schema」は、DAOの活動をわかりやすく記録するための方法であり、これを実装するコントラクトは、その情報へのリンク（`activityLogURI`）を提供する必要があります。
これによって、DAO内の活動がより透明で効率的に管理されるようになります。
:::

```json
{
    "@context": "<http://www.daostar.org/schemas>",
    "type": "DAO",
    "name": "<name of the DAO>",
    "activities": [
        {
            "id": "<activity ID>",
            "type": "activity",
            "proposal": {
                "type": "proposal"
                "id": "<proposal ID>",
            },
            "member": {
                "type": "EthereumAddress",
                "id": "<address or other identifier>"
            }
        }, 
    ],
    "activities": [
        {
            "id": "<activity ID>",
            "type": "activity",
            "proposal": {
                "type": "proposal"
                "id": "<proposal ID>",
            },
            "member": {
                "type": "EthereumAddress",
                "id": "<address or other identifier>"
            }
        }
    ]
}
```

## コントラクト

```json
{
    "@context": "<http://www.daostar.org/schemas>",
    "type": "DAO",
    "name": "<name of the DAO>",
    "contracts": [
        {
            "type": "EthereumAddress",
            "id": "<address or other identifier>",
            "name": "<name, e.g. Treasury>",
            "description": "<description, e.g. Primary operating treasury for the DAO>"
        },
        {
            "type": "EthereumAddress",
            "id": "<address or other identifier>",
            "name": "<name, e.g. Governance Token>",
            "description": "<description, e.g. ERC20 governance token contract>"
        }
        {
            "type": "EthereumAddress",
            "id": "<address or other identifier>",
            "name": "<name, e.g. Registraction Contract>",
            "description": "<description, e.g. ERC-4824 registration contract>"
        }
    ]
}
```

「**Contracts JSON-LD Schema**」とは、分散型自律組織（DAO）に関連するコントラクトの情報を整理するためのデータ形式です。
このEIP（改善提案）に従うコントラクトは、この形式に基づいた情報を含むJSONファイルへのリンクを指す`contractsURI`を持つ必要があります。

このJSONファイルには、以下のような情報が含まれます。

- DAOの名前やコントラクトの種類。
- 各コントラクトの詳細情報。
    - これには、Ethereumアドレスや他の識別子（`id`）、コントラクトの名前（例えば「**Treasury**」や「**Governance Token**」）、そしてそのコントラクトの説明（例えば「DAOの主要な運用トレジャリー」や「**ERC20**ガバナンストークンコントラクト」）が含まれます。

:::note info
「**Contracts JSON-LD Schema**」はDAOに関連するコントラクトの情報を一覧化し、それらについての詳細を提供するための方法です。
これにより、DAOに関連するコントラクトがどのようなものかが一目でわかり、その情報に簡単にアクセスできるようになります。
:::

# 補足

この標準では、分散型自律組織（DAO）は主に「**メンバーシップと行動**」という二つの要素から成り立っています。

- **メンバーシップ**
    - これはDAOのメンバーを表すアドレスの集合です。
    - つまり、誰がDAOのメンバーであるかを示すアドレスがメンバーシップになります。

- **行動**
    - これはDAOが行える様々な活動を意味します。
    - 例えば、他のコントラクトとのやり取りや、DAO自身の内部関数を実行することなどです。

DAOの提案は、メンバーシップと行動をつなげる役割を果たします。
メンバーはこれらの提案に対して意見を出したり投票することができ、提案が承認されるとそれはDAOの新しい行動として実行されます。

:::note info
この標準によれば、DAOはメンバーの集まりと、そのメンバーが行うことができる活動（コントラクトアクション）で構成されています。
提案はメンバーによって決定され、それが実行されるとDAOの行動となります。
:::

## API、URL、オフチェーンデータ

このテキストは、分散型自律組織（DAO）の機能と、なぜDAOがブロックチェーン外でデータを公開する必要があるかについて説明しています。

### DAOの機能
DAOは多様な目的で使用されています。
メンバーとのやり取り、新しいメンバーの募集、活動の計画、ユーザーインターフェースやガバナンスアプリケーション（例えばSnapshotやTally）の提供、DeepDAOやMessari、Etherscanなどのプラットフォームを通じた検索と発見などがその例です。

### 標準化されたデータ形式の重要性
これらの活動のためには、外部でデータを公開する必要があります。
様々なURIを通じて整理された標準化されたデータ形式（API仕様）があれば、DAOの活動を支え、エコシステム全体でのツールやフレームワークの発展を助け、さらなる相互運用性を可能にします。

### オンチェーン要素の標準化の取り扱い
この標準では、オンチェーンの提案やIDの標準化を検討しましたが、関連する用途がまだ成熟していないこと、提案システムとガバナンスの密接な関連性、そしてオフチェーンやレイヤー2の投票システムの普及を考慮して、現段階での標準化は控えることにしました。
しかし、標準URIインターフェースは比較的採用しやすく、コミュニティからの要望も強いです。

:::note info
このテキストはDAOが外部でデータを公開する必要性と、そのための標準化された方法の重要性を説明しており、同時にオンチェーンの要素については慎重な姿勢を示しています。
:::

## メンバーズURI

分散型自律組織（DAO）のメンバーシップに関する様々なアプローチと、メンバーシップ情報を整理するためのオフチェーンのJSONスキーマの重要性について述べています。

### メンバーシップの多様なアプローチ
一部のDAOやDAOフレームワーク（例えばGnosis SafeやTribute）では、明確に定義されたオンチェーンのメンバーリストを持っています。
一方で、MolochやCompoundのような他のDAOでは、メンバーシップはトークンの所有に基づいており、現在のメンバーを知るためにはオフチェーンのインデックス化が必要です。

### オフチェーンのJSONスキーマ
DAOは`membersURI`と呼ばれるJSONスキーマを使って、メンバーシップ情報を整理します。
これにより、オンチェーンのデータの静的コピーを提供したり、複数のコントラクトから成るDAOの一貫したメンバーシップを示したりすることができます。
さらに、このスキーマは外部サービスによって計算される場合もあります。

### スキーマの拡張の奨励
メンバーシップJSON-LDスキーマを拡張することが奨励されており、活動的／非活動的なステータスや異なるメンバーシップレベルを反映するために使用できます。

:::note info
DAOがメンバーシップ情報を効率的に整理し、さまざまな方法で活用できるようにするためのオフチェーンのJSONスキーマの重要性を強調しています。
:::

## 提案URI

DAOでの提案に関する情報と、それを整理するための方法について説明しています。

### 提案の重要性
DAOでは、メンバーがトークンを送るなどのオンチェーンアクションを起こすために提案を使います。
しかし、多くのDAOでは、DiscourseやDiscord、Snapshotのようなプラットフォーム上でオフチェーンの決定が行われ、提案は管理者へのシグナルや後のオンチェーン投票のための手段として使われます。

### 提案ID
オンチェーンの独自提案は、「**CAIP10_ADDRESS + “?proposalId=” + PROPOSAL_COUNTER**」の形式で一意のIDを持つ必要があります。
このIDは世界的にユニークであることが求められます。

### ContentURI
多くの提案には、フォーラム投稿や投票プラットフォーム上の説明のような、オフチェーンのコンテンツが伴います。

### ステータス
提案には通常、ステータスがありますが、そのステータスはガバナンスシステムに依存し、DAO間で共通の基準はありません。
そのため、一般的なテキスト説明フィールドを持つ「**ステータス**」プロパティを設定しています。

### 実行データ
オンチェーンの提案には、実行に必要なコールデータを公開するための配列フィールドが含まれることがあります。
これは提案の実行シミュレーションに役立ちます。

:::note info
DAOの提案に関する情報をオンチェーンとオフチェーンの両方でサポートするためのスキーマを提案し、それによって提案のID、内容、ステータス、実行データなどを整理する方法を説明しています。
DAOはこのスキーマを使って、オンチェーン、オフチェーン、またはその両方の提案情報を報告することができます。
:::

## アクティビティログURI

「**アクティビティログJSON**」とは、DAOのメンバーが提案に対してどのように行動するかを記録するためのフォーマットです。
これには、提案の作成や提出、提案への投票、提案に対する反対意見の提出など、メンバーのさまざまな活動が含まれます。

このフォーマットを選ぶ際には、「**履歴**」や「**やり取り**」といった他の方法も考慮されましたが、アクティビティログJSONが選ばれました。
これは、DAOのメンバーの活動と提案との関係をより詳細に記録し、DAOの透明性と活動の追跡を容易にするためです。

:::note info
アクティビティログJSONは、DAOのメンバーが提案とどのように関わっているかを示す記録であり、DAOの活動をより明確に理解するための重要なツールとなります。
:::

## ガバナンスURI

「**governanceURI**」とは、DAOのメンバーシップに関連する権利や提案の仕組みについての情報を提供するためのリンクです。

### メンバーシップの意味
DAOのメンバーは、提案に投票する権利やDAOから脱退する権利（**ragequit**）、提案に拒否権を行使する権利など、さまざまな権利を持っています。
しかし、これらの権利の多くは、Snapshotのようなオフチェーンのプラットフォームで実現されます。

### フラットファイルの利用
DAOのメンバーシップに関する権利や提案の仕組みを説明するために、フラットファイル（簡単なテキストファイル）を使用することが推奨されています。
これは、これらの情報をオンチェーンで標準化するよりも簡単で広く受け入れられる方法です。
Etherscanなどのサービスがこれらのファイルを活用して、DAOをより発見しやすく、理解しやすくします。

### 「ガバナンス」の用語選択
「**ガバナンス**」という言葉は、DAOエコシステムで広く使用されていることと、オープンソースプロジェクトで「`governance.md`」というファイルが一般的に使用されることを反映して選ばれました。

:::note info
「**governanceURI**」はDAOのメンバーシップと提案の仕組みに関する情報を提供するリンクであり、DAOの活動をより透明でアクセスしやすくするためのツールとなります。
:::

## コントラクトURI

「**contractsURI**」とは、分散型自律組織（DAO）が使用する様々なコントラクトに関する情報をまとめて提供するためのリンクです。
これは、DAOのコントラクトを監査やインデックス化するためにコミュニティで話し合われた結果生まれた概念です。

### DAOコントラクトの種類
いくつかのDAOでは、Open Zeppelin / Compound Governorのようなフレームワークを使用して、コアコントラクトや投票コントラクト、タイムロックコントラクトなどをデプロイしています。
また、別のDAOでは、複数のマルチシグをトレジャリーとして使ったり、いくつかのサブDAOを設立して管理したりしています。

### contractsURIの目的
このリンクは、DAOに関連する多様なコントラクトの情報を一元化して提供する役割を持ちます。
これにより、DAOのコントラクト構造や機能が外部から見てわかりやすくなります。

### 名称の選定
「**contractsURI**」という名前は、「**contractsRegistry**」（コントラクトレジストリ）や「**contractsList**」（コントラクトリスト）といった他の候補を検討した結果、選ばれました。

:::note info
「**contractsURI**」は、DAOが使用しているさまざまなコントラクトの情報をまとめてアクセス可能にするリンクであり、DAOの透明性を高め、外部の監査や理解を容易にするための重要なツールです。
:::

## Why JSON-LD

なぜ分散型自律組織（DAO）のデータフォーマットとしてJSON-LD（JSON for Linked Data）を選んだかを説明しています。

### 多様な識別方法のサポート
DAOでは、メンバーをEthereumアドレスだけでなく、他のブロックチェーンのアドレスや異なる識別方法で表すことがあります。
JSON-LDは、このような多様な識別方法をサポートするために選ばれました。

### マルチチェーン互換性
このフォーマットは、将来的にマルチチェーン環境で使用される可能性を考慮しています。
JSON-LDは、アドレスのコンテキストやタイプを定義する機能を備えているため、この目的に適しています。

### 複数のDAOからのデータ統合
大規模な組織では、複数のDAOを同じURIにリンクして、それを複数のコントラクトやサービスからのデータアクセスポイントとして使用することがあります。
JSON-LDは、これらのデータを拡張しやすく管理しやすいため、このような用途に適しています。

:::note info
JSON-LDは、Ethereumアドレス以外の識別方法やマルチチェーン環境への対応、さらには複数のDAOのデータを一元化するための柔軟性と拡張性を提供する選択肢として選ばれました。
これにより、DAOのデータ管理がより効率的かつ柔軟になります。
:::

## コミュニティコンセンサス

DAOの初期標準案がどのようにして作られたかについての話です。

### 開発プロセス
この標準案は、多くのEVMベースのDAOフレームワーク（例えばAragon、Compound、DAOstackなど）の代表者やDAOツールの開発者、そしていくつかの主要なDAOが参加するDAOstar One ラウンドテーブルで開発されました。

### 貢献者への感謝
このプロジェクトに貢献した多くの人々、特にAuryn Macmillan、SnapshotのFabien、Selim Imoberdorfなどに対する感謝が述べられています。

### 今後の予定
2022年のSchelling PointとETHDenverでの対面イベントと、2022年初めに予定されている一連のコミュニティコールで、さらに多くのフィードバックを得ることを期待しています。

:::note info
DAOの標準案が多くの専門家の意見を集めて形成され、今後もコミュニティからの意見を取り入れながら進化していくことを示しています。
:::

# 後方互換性

### 既存コントラクトへの影響
この新しい標準を採用しない既存のコントラクトには影響がありません。
つまり、現在動いているDAOがこの新しい標準を使わなくても、問題はないということです。

### 新標準の採用方法
新しい標準を採用したいDAOで、既存のコントラクトを更新したり移行したりするのを避けたい場合、外部の登録コントラクトを利用することができます。
これにより、既存のコントラクトをそのまま使いつつ、新しい標準に合わせることが可能になります。

:::note info
新しいDAO標準の採用は任意であり、既存のコントラクトを変更せずに、外部の登録コントラクトを通じて新しい標準に適合させることができると説明しています。
:::

# セキュリティ考慮事項

このテキストは、DAOのURI（Uniform Resource Identifier）に関するインターフェースを定義していますが、URIの設定ルールやデータの準備方法については具体的に指定していません。
つまり、どのようにURIを設定するかやデータを用意するかは、この標準自体では規定されていないということです。代わりに、標準を実装する開発者は以下の点に注意する必要があります。

### ガバナンスモデルに合致したデータ更新
開発者は、DAOのガバナンスモデルに合致した方法でデータを更新する方法を考える必要があります。
つまり、DAOの意思決定プロセスやルールに従ってURIのデータを適切に更新することが求められます。

### 中央集権的サービスプロバイダーへの依存の最小化
データを新鮮な状態に保つ際に、中央集権的なサービスプロバイダーへの依存を最小限に抑えることが重要です。
つまり、データの更新や取得において、中央集権的なサービスに頼りすぎないようにする必要があります。

また、URIから返されるデータを利用するデータ索引化サービス（インデクサー）は、注意が必要です。
なぜなら、URIから返されるコードが実行可能である場合、それが最新のメンバーシップ情報や提案、活動ログを取得するために使用される一方で、無関係なタスクを実行する可能性もあるからです。

:::note info
提案されている標準はURIのインターフェースを提供するものであり、URIの設定やデータの更新方法については開発者が自身で考える必要があることを強調しています。
同時に、データを利用する際にはセキュリティと中央集権性に対する懸念にも留意すべきであると述べています。
:::

# 引用

Joshua Tan (@thelastjosh), Isaac Patka (@ipatka), Ido Gershtein <ido@daostack.io>, Eyal Eithcowich <eyal@deepdao.io>, Michael Zargham (@mzargham), Sam Furter (@nivida), "ERC-4824: Common Interfaces for DAOs [DRAFT]," Ethereum Improvement Proposals, no. 4824, February 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4824.

# 最後に

今回は「オンチェーンとオフチェーンを繋ぐ、分散型自律組織（DAO）のためのAPIの仕組みを提案している規格である**ERC4824**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58


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