[ERC6617] ビットベースの権限管理の仕組みを理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、ビットベースの権限管理システムの仕組みを提案している規格である**ERC6617**についてまとめていきます！

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

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

:::note warn
**6617**は現在（2024年1月10日）では「**Review**」段階です。
:::

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

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

# 概要

このEIPはイーサリアムのスマートコントラクトにおいて、非常に高度で柔軟な権限とロール管理システムを実現するためのフレームワークを提案しています。
ビットベースのアプローチは、各ビットが独立した権限を表すため、`256`ビット（`uint256`）を使用することで、非常に多くの異なる権限の組み合わせを作ることが可能です。

さらに、$2^{256}$ の異なるロールを定義できるという点は、このシステムの非常に強力な側面です。
これは、実質的に無限に近い数のユニークなロールを作成できることを意味し、それぞれのロールに異なる権限の組み合わせを割り当てることが可能になります。
これにより、非常に複雑で多様な権限のシナリオを管理することができ、大規模なプロジェクトや複雑なビジネスロジックを持つアプリケーションに適しています。

例えば、あるロールには`transfer`機能の権限を与え、別のロールには`mint`機能の権限を与えることができます。
これにより、特定のユーザーグループに対して厳密なアクセスコントロールを実施することが可能となり、コントラクトのセキュリティを強化することができます。

このEIPは、イーサリアムのスマートコントラクトの権限管理を、より細かく、柔軟に、かつ効率的に行うことを可能にする新しい方法を提案しています。
これは、開発者にとって強力なツールであり、より安全で機能的なデジタルアプリケーションの開発を促進するでしょう。

# 仕様

以下のは、インターフェースはSolidity 0.8.7（またはそれ以上）の構文を使用しています。

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

```javascript
pragma solidity ^0.8.7;

/**
    @title EIP-6617 Bit Based Permission
    @dev See https://eips.ethereum.org/EIPS/eip-6617
*/
interface IEIP6617 {

    /**
        MUST trigger when a permission is granted.
        @param _grantor        Grantor of the permission
        @param _permission     Permission that is granted
        @param _user           User who received the permission
    */
    event PermissionGranted(address indexed _grantor, uint256 indexed _permission, address indexed _user);

    /**
        MUST trigger when a permission is revoked.
        @param _revoker        Revoker of the permission
        @param _permission     Permission that is revoked
        @param _user           User who lost the permission
    */
    event PermissionRevoked(address indexed _revoker, uint256 indexed _permission, address indexed _user);

    /**
        @notice Check if user has permission
        @param _user                Address of the user whose permission we need to check
        @param _requiredPermission  The required permission
        @return                     True if the _permission is a superset of the _requiredPermission else False
    */
    function hasPermission(address _user, uint256 _requiredPermission)
        external
        view
        returns (bool);

    /**
        @notice Add permission to user
        @param _user                Address of the user to whom we are going to add a permission
        @param _permissionToAdd     The permission that will be added
        @return                     The new permission with the _permissionToAdd
    */
    function grantPermission(address _user, uint256 _permissionToAdd)
        external
        returns (bool);

    /**
        @notice Revoke permission from user
        @param _user                Address of the user to whom we are going to revoke a permission
        @param _permissionToRevoke  The permission that will be revoked
        @return                     The new permission without the _permissionToRevoke
    */
    function revokePermission(address _user, uint256 _permissionToRevoke)
        external
        returns (bool);
}
```

**EIP6617**に準拠しているコントラクトは、**IEIP6617**インターフェースを実装する必要があります。
この規格における権限は、`uint256`として表されます。
権限は`uint256`の中で`1`ビットだけを使用し、そのため2の累乗でなければなりません。
それぞれの権限はユニークでなければならず、`0`は「**無権限**」を意味するために使用されます。

## メタデータインターフェース

```javascript
/**
 * @dev Defined the interface of the metadata of EIP6617, MAY NOT be implemented
 */
interface IEIP6617Meta {
    
    /**
        Structure of permission description
        @param _permission     Permission
        @param _name           Name of the permission
        @param _description    Description of the permission
    */
    struct PermissionDescription {
        uint256 permission;
        string name;
        string description;
    }

    /**
        MUST trigger when the description is updated.
        @param _permission     Permission
        @param _name           Name of the permission
        @param _description    Description of the permission
    */
    event UpdatePermissionDescription(uint256 indexed _permission, string indexed _name, string indexed _description);

    /**
        Returns the description of a given `_permission`.
        @param _permission     Permission
    */
    function getPermissionDescription(uint256 _permission) external view returns (PermissionDescription memory description);

    /**
        Return `true` if the description was set otherwise return `false`. It MUST emit `UpdatePermissionDescription` event.
        @param _permission     Permission
        @param _name           Name of the permission
        @param _description    Description of the permission
    */
    function setPermissionDescription(uint256 _permission, string memory _name, string memory _description)
        external
        returns (bool success);
}
```

**IEIP6617Meta**インターフェースは、**EIP6617**に準拠したコントラクトに追加情報を提供するためのオプショナルな拡張機能です。
この拡張機能によって、コントラクトは基本権限とその主要な組み合わせについての名前と説明を定義することができます。
これは、権限が何を意味するのか、どのように機能するのかを理解しやすくするために役立ちます。

ただし、すべての可能な権限の組み合わせ（サブコンビネーション）に対して個別に説明を提供することは推奨されていません。
これは、権限の数が非常に多いため、すべての組み合わせに対して詳細な説明を用意することが非現実的であるからです。
代わりに、主要な権限とそれらの基本的な組み合わせに焦点を当てることで、開発者やユーザーが権限システムの全体像を理解しやすくなります。

**IEIP6617Meta**インターフェースの実装により、コントラクトはより透明性を持ち、ユーザーに対して権限の意味と用途を明確に伝えることができます。
これにより、コントラクトの使用や管理がより容易になり、ユーザーエクスペリエンスが向上します。

# 補足

イーサリアムのスマートコントラクトにおける現行の権限管理方法は、主に**ERC173**の単一オーナーモデルか、**ERC5982**のように`bytes32`を使用したロールベースのモデルを採用しています。
**ERC173**のモデルでは、コントラクトの全ての管理権限は1つのアカウント（`owner`）に集中しており、**ERC5982**では、`bytes32`データ型を使用して異なるロールを表現しています。

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

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

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

https://qiita.com/cardene/items/6457bb501aa5ac1677af

しかしながら、ビットワイズ演算（ビットごとの論理演算）やビットマスク（特定のビットだけを操作する手法）を使用することには、いくつかの利点があります。
まず、ビットワイズ演算はガス効率が良いため、コントラクトの実行コストを削減できます。
特に、大規模なアプリケーションや多くのユーザーが関与する場合、ガス効率の向上は大きなメリットとなります。

また、ビットマスクを用いることで、権限の管理がより柔軟になります。
ビットマスクを使用すると、特定のビットのみを切り替えることで、権限を細かく調整できます。
これにより、開発者は必要に応じて精密なアクセスコントロールを設計することが可能になり、コントラクトのセキュリティと機能性が向上します。

このように、ビットワイズ演算とビットマスクの使用は、スマートコントラクトの権限管理において、従来の単一オーナーモデルやロールベースのモデルに比べて、効率性と柔軟性の両方を提供します。
これにより、より高度で実用的なアプリケーションの開発が促進されるでしょう。

## ガスコスト効率
ビットワイズ演算は非常に安価で高速です。
例えば、権限ビットマスクに対して`AND`ビットワイズ演算を行うことは、いくつかの`LOAD`オペコードを呼び出すよりもかなり安価です。

## 柔軟性
`uint256`の`256`ビットを使用して、最大で`256`の異なる権限を作成でき、これによりユニークな組み合わせ（別名ロール）が生成されます。
ロールは複数の権限の組み合わせです。
すべてのロールを事前に定義する必要はありません。

権限が符号なし整数として定義されているため、バイナリ`OR`演算子を使用して、複数の権限に基づいた新しいロールを作成できます。

## 重要度による権限の順序付け
最も重要な権限を表すために最上位ビットを使用できます。
それらはすべて`uint256`であるため、権限間の比較が簡単に行えます。

## 意味の関連付け
**ERC5982**によるアクセスコントロールと比較して、このEIPは権限やロールの意味を直接かつ簡単に理解することはありません。

# 実装

以下に格納されています。

https://eips.ethereum.org/assets/eip-6617/contracts/EIP6617.sol

# 引用

Chiro (@chiro-hiro), Victor Dusart (@vdusart), "ERC-6617: Bit Based Permission [DRAFT]," Ethereum Improvement Proposals, no. 6617, February 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6617.

# 最後に

今回は「ビットベースの権限管理システムの仕組みを提案している規格である**ERC6617**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下の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