はじめに
初めまして。
CryptoGamesというブロックチェーンゲーム企業でエンジニアをしている cardene(かるでね) です!
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。
代表的なゲームはクリプトスペルズというブロックチェーンゲームです。
今回は、NFTのさまざまなロールを管理するインターフェースを提案しているERC7432についてまとめていきます!
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
7432は現在(2023年9月7日)では「Review」段階です。
概要
この規格は、NFTに特定のロールを与える仕組みを提案しています。
NFTごとにロールが紐づけられており、あらかじめ設定された時間が経過すると紐づけられたロールは自動的に無効になります。
ここでの「ロール」とは、特定の機能や権限を指すもので、たとえば「管理者」や「所有者」といったものです。
これらのロールは、情報をバイト(bytes32
)の形式で保持し、さらにカスタムの「_data
」フィールドを持っています。
この「_data
」フィールドは、ロールに関連付けられた情報を自由に格納でき、カスタマイズすることが可能です。
動機
このインターフェースは、NFT(非代替トークン)におけるロール管理のための標準の提供を目指しています。
この標準に従うことで、分散型アプリケーション(dApps)は、特権的な操作を実行するためのアクセス制御を実現できます。
たとえば、トークンの発行(エアドロップの権利など)を特定のユーザーに制限することができます。
NFTのロール管理は、dAppsとシームレスに統合され、ユーティリティ(機能や権限)を共有するメカニズムを提供します。
具体的な例として、デジタル不動産を考えてみましょう。
ユーザーはデジタルの不動産NFTを作成し、他のユーザーに「PROPERTY_MANAGER
」というロールを与えることができます。
これにより、所有権を譲渡することなく、特定の機能や権限を委任できます。
同じユーザーは「PROPERTY_TENANT
」というロールを複数のユーザーに与えることもでき、これによりロールを付与されたアドレスはデジタル不動産にアクセスし、対話することができます。
また、分散型金融(DeFi)においても興味深い活用事例があります。
保険ポリシーをNFTとして発行し、受益者、被保険者、保険会社などをブロックチェーン上で追跡することができます。
これにより、契約者や関係者のロールを透明かつ信頼性の高い方法で管理できます。
仕様
この規格に準拠するコントラクトは、以下のインターフェイスを実装する必要があります。
/// @title ERC-7432 Non-Fungible Token Roles
/// @dev See https://eips.ethereum.org/EIPS/eip-7432
/// Note: the ERC-165 identifier for this interface is 0xd7e151ef.
interface IERC7432 /* is ERC165 */ {
/** Events **/
/// @notice Emitted when a role is granted.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user assigning the role.
/// @param _grantee The user receiving the role.
/// @param _expirationDate The expiration date of the role.
/// @param _data Any additional data about the role.
event RoleGranted(
bytes32 indexed _role,
address indexed _tokenAddress,
uint256 indexed _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bytes _data
);
/// @notice Emitted when a role is revoked.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _revoker The user revoking the role.
/// @param _grantee The user that receives the role revocation.
event RoleRevoked(
bytes32 indexed _role,
address indexed _tokenAddress,
uint256 indexed _tokenId,
address _revoker,
address _grantee
);
/// @notice Emitted when a user is approved to manage any role on behalf of another user.
/// @param _tokenAddress The token address.
/// @param _operator The user approved to grant and revoke roles.
/// @param _isApproved The approval status.
event RoleApprovalForAll(
address indexed _tokenAddress,
address indexed _operator,
bool _isApproved
);
/// @notice Emitted when a user is approved to manage the roles of an NFT on behalf of another user.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _operator The user approved to grant and revoke roles.
/// @param _isApproved The approval status.
event RoleApproval(
address indexed _tokenAddress,
uint256 indexed _tokenId,
address _operator,
bool _isApproved
);
/** External Functions **/
/// @notice Grants a role to a user.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantee The user receiving the role.
/// @param _expirationDate The expiration date of the role.
/// @param _data Any additional data about the role.
function grantRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantee,
uint64 _expirationDate,
bytes calldata _data
) external;
/// @notice Revokes a role from a user.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantee The user that receives the role revocation.
function revokeRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantee
) external;
/// @notice Grants a role on behalf of a user.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user assigning the role.
/// @param _grantee The user that receives the role.
/// @param _expirationDate The expiration date of the role.
/// @param _data Any additional data about the role.
function grantRoleFrom(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bytes calldata _data
) external;
/// @notice Revokes a role on behalf of a user.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _revoker The user revoking the role.
/// @param _grantee The user that receives the role revocation.
function revokeRoleFrom(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _revoker,
address _grantee
) external;
/// @notice Approves operator to grant and revoke any roles on behalf of another user.
/// @param _tokenAddress The token address.
/// @param _operator The user approved to grant and revoke roles.
/// @param _approved The approval status.
function setRoleApprovalForAll(
address _tokenAddress,
address _operator,
bool _approved
) external;
/// @notice Approves operator to grant and revoke roles of an NFT on behalf of another user.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _operator The user approved to grant and revoke roles.
/// @param _approved The approval status.
function approveRole(
address _tokenAddress,
uint256 _tokenId,
address _operator,
bool _approved
) external;
/** View Functions **/
/// @notice Checks if a user has a role.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user that assigned the role.
/// @param _grantee The user that received the role.
function hasRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bool);
/// @notice Checks if a user has a unique role.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user that assigned the role.
/// @param _grantee The user that received the role.
function hasUniqueRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bool);
/// @notice Returns the custom data of a role assignment.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user that assigned the role.
/// @param _grantee The user that received the role.
function roleData(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bytes memory data_);
/// @notice Returns the expiration date of a role assignment.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user that assigned the role.
/// @param _grantee The user that received the role.
function roleExpirationDate(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (uint64 expirationDate_);
/// @notice Checks if the grantor approved the operator for all NFTs.
/// @param _tokenAddress The token address.
/// @param _grantor The user that approved the operator.
/// @param _operator The user that can grant and revoke roles.
function isRoleApprovedForAll(
address _tokenAddress,
address _grantor,
address _operator
) external view returns (bool);
/// @notice Checks if the grantor approved the operator for a specific NFT.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user that approved the operator.
/// @param _operator The user approved to grant and revoke roles.
function getApprovedRole(
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _operator
) external view returns (bool);
}
メタデータ拡張
NFT(非代替トークン)の従来のJSONベースのメタデータスキーマを拡張します。
そのため、この機能をサポートするDApps(分散型アプリケーション)は、必ずERC721またはERC1155のメタデータ拡張を実装する必要があります。
この拡張機能はオプションであり、開発者がロールに関する追加情報を提供できるようにします。
-
Roles Metadata拡張
NFTに関連付けられたロールに関する追加情報を提供するための機能です。
例えば、特定のNFTが「PROPERTY_MANAGER
」の役割を持っている場合、その「PROPERTY_MANAGER
」の詳細情報を提供することができます。 -
JSONベースのメタデータスキーマ
通常、NFTにはJSON形式のメタデータが含まれており、それにはトークンの名前、説明、画像URLなどが含まれています。
Roles Metadata拡張は、この既存のメタデータスキーマを拡張して、ロールに関する情報を追加できるようにします。 -
DAppsのサポート
Roles Metadata拡張をサポートするDAppsは、NFTのメタデータにロール情報を正しく表示し、操作できる必要があります。
ただし、この機能を実装する際には、ERC721またはERC1155のメタデータ拡張も同時に実装しなければなりません。
アップデートされたメタデータスキーマ。
{
/** Existing NFT Metadata **/
"title": "Asset Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset to which this NFT represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this NFT represents"
},
"image": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive"
}
},
/** Additional fields for Roles **/
"roles": [
{
"id": {
"type": "bytes32",
"description": "Identifies the role"
},
"name": {
"type": "string",
"description": "Human-readable name of the role"
},
"description": {
"type": "string",
"description": "Describes the role"
},
"isUniqueRole": {
"type": "boolean",
"description": "Whether the role supports simultaneous assignments or not"
},
"inputs": [
{
"name": {
"type": "string",
"description": "Human-readable name of the argument"
},
"type": {
"type": "string",
"description": "Solidity type, e.g., uint256 or address"
}
}
]
}
]
}
以下のJSONはERC7432メタデータの例です。
{
// ... Existing NFT Metadata
"roles": [
{
// keccak256("PROPERTY_MANAGER")
"id": "0x5cefc88e2d50f91b66109b6bb76803f11168ca3d1cee10cbafe864e4749970c7",
"name": "Property Manager",
"description": "The manager of the property is responsible for furnishing it and ensuring its good condition.",
"isUniqueRole": false,
"inputs": []
},
{
// keccak256("PROPERTY_TENANT")
"id": "0x06a3b33b0a800805559ee9c64f55afd8a43a05f8472feb6f6b77484ff5ac9c26",
"name": "Property Tenant",
"description": "The tenant of the property is responsible for paying the rent and keeping the property in good condition.",
"isUniqueRole": true,
"inputs": [
{
"name": "rent",
"type": "uint256"
}
]
}
]
}
-
ロールの配列プロパティ
これらのプロパティは、NFTの役割に関する情報を含むものです。
開発者は必要に応じて、ロールについての追加情報(たとえば、ロールの画像や詳細な説明)を追加できます。
しかし、「isUniqueRole
」というプロパティを含めることが非常に重要です。
この「isUniqueRole
」フィールドは、あるロールが一意であるかどうかを示し、それに応じて「hasRole
」または「hasUniqueRole
」という関数を呼び出すかどうかを判断するのに役立ちます。 -
inputsプロパティの重要性
このプロパティは、特定の操作(たとえば、ロールの付与)に必要な情報を記述する場所です。
具体的には、どのパラメーターをエンコードし、grantRole
関数に渡すかを示します。
このとき、「inputs
」プロパティには、パラメーターの型を示す「type
」と、複雑なデータ構造(たとえば、タプル型)の場合に使用される「components
」が含まれます。
これにより、操作が正確に実行されるための情報が提供されます。
注意事項
-
IERC7432インターフェースの実装
この規格に準拠したコントラクトは、IERC7432インターフェースを実装する必要があります。
これにより、ロール管理の標準化が促進されます。 -
ロールの表現
ロールはbytes32
型で表されます。
通常、ロール名はkeccak256
ハッシュ関数を使用してハッシュ化され、このハッシュがロールを表します。
例えば、ROLE_NAME
ロールのハッシュはkeccak256("ROLE_NAME")
です。 -
grantRole関数
ロールを付与する関数で、_expirationDate
(有効期限)が過去の場合、エラーを発生させる必要があります。 -
grantRoleFrom関数
_expirationDate
が過去の場合、またはmsg.sender
が_grantor
の代わりにロールを付与する権限を持っていない場合、エラーを発生させる必要があります。 -
revokeRole関数
ロールを取り消す関数です。 -
revokeRoleFrom関数
msg.sender
が_revoker
の代わりにロールを取り消す権限を持っていない場合、エラーを発生させる必要があります。 -
setRoleApprovalForAll関数
ロールの付与権限を設定する関数です。 -
approveRole関数
ロールの承認権限を設定する関数です。 -
hasRole関数
ロールの割り当てが存在し、有効期限が切れていないかどうかを確認する関数です。 -
hasUniqueRole関数
ロールの割り当てが存在し、有効期限が切れておらず、最後に付与されたロールであるかどうかを確認する関数で、pureまたはviewで実装さ、同時にロールの割り当てがサポートされません。 -
roleData関数
ロールの割り当てが存在しない場合、空のバイト配列を返します。 -
roleExpirationDate関数
ロールの割り当てが存在しない場合、0
ゼロを返します。 -
isRoleApprovedForAll関数
指定した_operator
が_grantor
の代わりにすべてのNFTに対してロールを付与および取り消す権限を持っている場合、true
を返します。 -
getApprovedRole関数
指定した_operator
が_grantor
の指定したNFTに対してロールを付与および取り消す権限を持っている場合、true
を返します。 -
ERC165のサポート
この規格に準拠したコントラクトはERC165をサポートします。
補足
ERC7432はERC721やERC1155の拡張ではありません。
ERC7432は、特定のNFT実装に依存せず、どのNFTプラットフォームでも使えるように設計されています。
これにより、標準を外部で実装するか、NFTのコントラクト内で実装し、dAppsが不変のNFTとロールを組み合わせて使えます。
自動有効期限
自動有効期限は、ロールの付与とロールの有効性のチェックに関わります。
ロールの付与において、有効期限を設定するのがgrantRole
関数の役割で、ロールの有効性を確認するのがhasRole
関数の役割です。
日付はuint256
ではなく、uint64
で表されます。
最大のUNIX
タイムスタンプは約584,942,417,355
年で、これは「永久」と考えられるため、期限切れを設定しないケースにはtype(uint64).max
を使用することが推奨されています。
ユニークとユニークでないロール
この標準は、ユニークなロール(一度に1つのアカウントに割り当てられる)とノンユニークなロール(複数のアカウントに同時に付与可能)の両方をサポートしています。
ロールがユニークかノンユニークかはメタデータで指定できます。
コントラクトがメタデータを実装していない場合、すべてのロールはノンユニークとみなされます。
カスタムデータ
dAppsは、ロールの割り当て時にロール固有の情報をエンコードするためにgrantRole
関数の_data
パラメーターを使用できます。
このカスタムデータはroleData
関数を介して取得でき、RoleGranted
イベントと共に送信されます。
開発者はこれをオンチェーンとオフチェーンのアプリケーションに統合できます。
ロール承認
ERC7432は、ユーザーが他のアカウントにロールの付与と取り消しを承認する機能を提供します。
ユーザーは単一のNFTまたはコレクション内のすべてのNFTを管理できるアカウントを認可できます。
これにより、所有権を持たないコントラクトがERC7432を操作できるようになります。
後方互換性
ERC7432は、トークンのアドレス(tokenAddress
)とトークンのID(tokenId
)をすべての関数とイベントで提供することを要求します。
これにより、NFTのロールに関する情報を一元的に管理できる独立したERC7432コントラクトを使用できます。
これは、他のNFT関連の関数(例:ownerOf
やbalanceOf
)が不要であることを意味し、さまざまなNFT実装との統合がスムーズに行えるようになります。
参考実装
以下のGithubに格納しています。
roleAssignments
mapping(address => mapping(address => mapping(address => mapping(uint256 => mapping(bytes32 => RoleData))))) public roleAssignments;
概要
ロールの割り当て情報を格納するマッピング配列。
各キーに対応するロールの情報が保持されます。
詳細
-
grantor
- ロールを付与するアカウントのアドレス。
-
grantee
- ロールを受け取るアカウントのアドレス。
-
tokenAddress
- トークンのアドレス。
-
tokenId
- トークンのID。
-
role
- ロールを表すハッシュ。
-
RoleData
- ロールの有効期限とカスタムデータを格納する構造体。
latestGrantees
mapping(address => mapping(address => mapping(uint256 => mapping(bytes32 => address)))) public latestGrantees;
概要
最新の受益者(grantee
)を追跡するマッピング配列。
各トークンとロールに対して最新の受益者が保持されます。
詳細
-
grantor
- ロールを付与するアカウントのアドレス。
-
tokenAddress
- トークンのアドレス。
-
tokenId
- トークンのID。
-
role
- ロールを表すハッシュ。
-
grantee
- 最新の受益者(
grantee
)のアドレス。
- 最新の受益者(
tokenIdApprovals
mapping(address => mapping(address => mapping(uint256 => mapping(address => bool)))) public tokenIdApprovals;
概要
トークンIDごとのオペレーターの承認情報を追跡するマッピング配列。
詳細
-
grantor
- ロールを付与するアカウントのアドレス。
-
operator
- オペレーターのアドレス。
-
tokenAddress
- トークンのアドレス。
-
isApproved
- オペレーターが承認されているかどうかの状態。
tokenApprovals
mapping(address => mapping(address => mapping(address => bool))) public tokenApprovals;
概要
トークンごとのオペレーターの承認情報を追跡するマッピング配列。
詳細
-
grantor
- ロールを付与するアカウントのアドレス。
-
operator
- オペレーターのアドレス。
-
tokenAddress
- トークンのアドレス。
-
isApproved
- オペレーターが承認されているかどうかの状態。
validExpirationDate
modifier validExpirationDate(uint64 _expirationDate) {
require(_expirationDate > block.timestamp, "ERC7432: expiration date must be in the future");
_;
}
概要
有効期限の日付が未来であることを確認する修飾子。
詳細
-
_expirationDate
- 確認される有効期限の日付。
onlyApproved
modifier onlyApproved(address _tokenAddress, uint256 _tokenId, address _grantor) {
require(
isRoleApprovedForAll(_tokenAddress, _grantor, msg.sender) ||
getApprovedRole(_tokenAddress, _tokenId, _grantor, msg.sender),
"ERC7432: sender must be approved"
);
_;
}
概要
指定された条件を満たす場合にのみ関数を実行できる修飾子。
送信者が承認されているかどうかを確認します。
詳細
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンのID。
-
_grantor
- ロールを付与するアカウントのアドレス。
grantRole
function grantRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantee,
uint64 _expirationDate,
bytes calldata _data
) external {
_grantRole(_role, _tokenAddress, _tokenId, msg.sender, _grantee, _expirationDate, _data);
}
概要
指定したロール(_role
)を特定のトークン(_tokenAddress
、_tokenId
)の受託者(_grantee
)に付与する関数。
詳細
権限の有効期限(_expirationDate
)およびデータ(_data
)も指定できます。
引数
-
_role
- 付与するロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantee
- ロールを受け取るアドレス。
-
_expirationDate
- ロールの有効期限(Unixタイムスタンプ形式)。
-
_data
- 任意のデータ。
grantRoleFrom
function grantRoleFrom(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bytes calldata _data
) external override onlyApproved(_tokenAddress, _tokenId, _grantor) {
_grantRole(_role, _tokenAddress, _tokenId, _grantor, _grantee, _expirationDate, _data);
}
概要
特定のトークン(_tokenAddress
、_tokenId
)の所有者(_grantor
)が指定したロール(_role
)を受託者(_grantee
)に付与する関数。
詳細
所有者の承認が必要です。
引数
-
_role
- 付与するロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantor
- ロールを付与する所有者のアドレス。
-
_grantee
- ロールを受け取るアドレス。
-
_expirationDate
- ロールの有効期限(Unixタイムスタンプ形式)。
-
_data
- 任意のデータ。
_grantRole
function _grantRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bytes calldata _data
) internal validExpirationDate(_expirationDate) {
roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role] = RoleData(_expirationDate, _data);
latestGrantees[_grantor][_tokenAddress][_tokenId][_role] = _grantee;
emit RoleGranted( _role, _tokenAddress, _tokenId, _grantor, _grantee, _expirationDate, _data);
}
概要
ロールの付与と内部処理を行う関数。
引数
-
_role
- 付与するロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantor
- ロールを付与する所有者のアドレス。
-
_grantee
- ロールを受け取るアドレス。
-
_expirationDate
- ロールの有効期限(Unixタイムスタンプ形式)。
-
_data
- 任意のデータ。
revokeRole
function revokeRole(bytes32 _role, address _tokenAddress, uint256 _tokenId, address _grantee) external {
_revokeRole(_role, _tokenAddress, _tokenId, msg.sender, _grantee);
}
概要
指定したロール(_role
)を特定のトークン(_tokenAddress
、_tokenId
)の受託者(_grantee
)から取り消す関数。
詳細
-
_role
- 取り消すロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantee
- ロールを持っている受託者のアドレス。
revokeRoleFrom
function revokeRoleFrom(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _revoker,
address _grantee
) external override onlyApproved(_tokenAddress, _tokenId, _revoker) {
_revokeRole(_role, _tokenAddress, _tokenId, _revoker, _grantee);
}
概要
特定のトークン(_tokenAddress
、_tokenId
)の所有者(_revoker
)が指定したロール(_role
)を受託者(_grantee
)から取り消す関数。
詳細
所有者の承認が必要です。
引数
-
_role
- 取り消すロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_revoker
- ロールを取り消す所有者のアドレス。
-
_grantee
- ロールを持っている受託者のアドレス。
_revokeRole
function _revokeRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _revoker,
address _grantee
) internal {
delete roleAssignments[_revoker][_grantee][_tokenAddress][_tokenId][_role];
delete latestGrantees[_revoker][_tokenAddress][_tokenId][_role];
emit RoleRevoked(_role, _tokenAddress, _tokenId, _revoker, _grantee);
}
概要
ロールの実際の取り消しと内部処理を行う関数。
詳細
-
_role
- 取り消すロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_revoker
- ロールを取り消す所有者のアドレス。
-
_grantee
- ロールを持っている受託者のアドレス。
hasRole
function hasRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bool) {
return roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role].expirationDate > block.timestamp;
}
概要
指定したトークン(_tokenAddress
、_tokenId
)の所有者(_grantor
)が特定の受託者(_grantee
)に対して役割(_role
)を持っているか確認する関数。
詳細
-
_role
- 確認するロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantor
- ロールを持つ所有者のアドレス。
-
_grantee
- ロールを持っているか確認する受託者のアドレス。
戻り値
-
true
- 受託者がロールを持っており、有効期限内であることを示す
bool
値。
- 受託者がロールを持っており、有効期限内であることを示す
-
false
- 受託者が役割を持っていないか、有効期限が切れていることを示す
bool
値。
- 受託者が役割を持っていないか、有効期限が切れていることを示す
hasUniqueRole
function hasUniqueRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bool) {
return latestGrantees[_grantor][_tokenAddress][_tokenId][_role] == _grantee && roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role].expirationDate > block.timestamp;
}
概要
指定したトークン(_tokenAddress
、_tokenId
)の所有者(_grantor
)が特定の受託者(_grantee
)に対してロール(_role
)を持っていて、そのロールがユニークか確認する関数。
詳細
-
_role
- 確認するロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantor
- ロールを持つ所有者のアドレス。
-
_grantee
- ロールを持っているか確認する受託者のアドレス。
引数
なし。
戻り値
-
true
- 受託者が唯一のロールを持っており、有効期限内であることを示す
bool
値。
- 受託者が唯一のロールを持っており、有効期限内であることを示す
-
false
- 受託者が唯一の役割を持っていないか、有効期限が切れていることを示す
bool
値。
- 受託者が唯一の役割を持っていないか、有効期限が切れていることを示す
roleData
function roleData(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bytes memory data_) {
RoleData memory _roleData = roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role];
return (_roleData.data);
}
概要
指定したトークン(_tokenAddress
、_tokenId
)の所有者(_grantor
)が特定の受託者(_grantee
)に対してロール(_role
)に関連付けられたデータを取得する関数。
詳細
-
_role
- データを取得するロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantor
- ロールを持つ所有者のアドレス。
-
_grantee
- データを取得する受託者のアドレス。
戻り値
-
data_
- ロールに関連付けられたデータ。
roleExpirationDate
function roleExpirationDate(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (uint64 expirationDate_){
RoleData memory _roleData = roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role];
return (_roleData.expirationDate);
}
概要
指定したトークン(_tokenAddress
、_tokenId
)の所有者(_grantor
)が特定の受託者(_grantee
)に対してロール(_role
)の有効期限を取得する関数。
詳細
-
_role
- 有効期限を取得するロールの識別子。
-
_tokenAddress
- トークンのアドレス。
-
_tokenId
- トークンの識別子。
-
_grantor
- ロールを持つ所有者のアドレス。
-
_grantee
- 有効期限を取得する受託者のアドレス。
戻り値
-
expirationDate_
- ロールの有効期限(Unixタイムスタンプ形式)。
supportsInterface
function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
return interfaceId == type(IERC7432).interfaceId;
}
概要
指定したインターフェースがサポートされているかどうかを確認する関数。
特定のインターフェース(IERC7432)のサポートを確認するために使用されます。
詳細
特定のインターフェース(IERC7432)のサポートを確認するために使用されます。
引数
-
interfaceId
- 確認するインターフェースの識別子。
戻り値
-
true
- 指定したインターフェースがサポートされています。
-
false
- 指定したインターフェースがサポートされていません。
setRoleApprovalForAll
function setRoleApprovalForAll(
address _tokenAddress,
address _operator,
bool _isApproved
) external override {
tokenApprovals[msg.sender][_tokenAddress][_operator] = _isApproved;
emit RoleApprovalForAll(_tokenAddress, _operator, _isApproved);
}
概要
所有者が指定したトークン(_tokenAddress
)の特定のオペレーター(_operator
)に対するロール承認を設定または解除する関数。
引数
-
_tokenAddress
- ロール承認を設定または解除するトークンのアドレス。
-
_operator
- ロール承認を設定または解除するオペレーターのアドレス。
-
_isApproved
- ロール承認を設定する場合は
true
、解除する場合はfalse
。
- ロール承認を設定する場合は
approveRole
function approveRole(
address _tokenAddress,
uint256 _tokenId,
address _operator,
bool _approved
) external override {
tokenIdApprovals[msg.sender][_tokenAddress][_tokenId][_operator] = _approved;
emit RoleApproval(_tokenAddress, _tokenId, _operator, _approved);
}
概要
所有者が指定したトークン(_tokenAddress
、_tokenId
)に対して特定のオペレーター(_operator
)に対するロール承認を設定または解除する関数。
引数
-
_tokenAddress
- ロール承認を設定または解除するトークンのアドレス。
-
_tokenId
- ロール承認を設定または解除するトークンの識別子。
-
_operator
- ロール承認を設定または解除するオペレーターのアドレス。
-
_approved
- ロール承認を設定する場合は
true
、解除する場合はfalse
。
- ロール承認を設定する場合は
isRoleApprovedForAll
function isRoleApprovedForAll(
address _tokenAddress,
address _grantor,
address _operator
) public view override returns (bool) {
return tokenApprovals[_grantor][_tokenAddress][_operator];
}
概要
所有者が指定したトークン(_tokenAddress
)の特定のオペレーター(_operator
)に対するロール承認が設定されているか確認する関数。
引数
-
_tokenAddress
- ロール承認を確認するトークンのアドレス。
-
_grantor
- ロール承認を設定した所有者のアドレス。
-
_operator
- ロール承認を確認するオペレーターのアドレス。
戻り値
-
true
- ロール承認が設定されています。
-
false
- ロール承認が設定されていません。
getApprovedRole
function getApprovedRole(
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _operator
) public view override returns (bool) {
return tokenIdApprovals[_grantor][_tokenAddress][_tokenId][_operator];
}
概要
所有者が指定したトークン(_tokenAddress
、_tokenId
)に対して特定のオペレーター(_operator
)に対するロール承認が設定されているか確認する関数。
引数
-
_tokenAddress
- ロール承認を確認するトークンのアドレス。
-
_tokenId
- ロール承認を確認するトークンの識別子。
-
_grantor
- ロール承認を設定した所有者のアドレス。
-
_operator
- ロール承認を確認するオペレーターのアドレス。
戻り値
-
true
- ロール承認が設定されています。
-
false
- ロール承認が設定されていません。
セキュリティ考慮事項
NFTロールインターフェースを統合する開発者にとっての重要事項は以下になります。
-
適切なアクセス制御の確保
- 不正なロールの割り当てや取り消しを防ぐために、適切なアクセス制御メカニズムを実装しましょう。
- これにより、権限のない操作を防ぎ、セキュリティを向上させます。
-
セキュリティ対策の検討
- スマートコントラクトの実装中に潜在的な攻撃(例:再入攻撃)を考慮し、適切なセキュリティ対策を実施しましょう。
- セキュリティの確保は非常に重要です。
-
NFTの所有権の確認
-
ERC7432はNFTの所有権を自動的に確認しないため、dAppはNFTの所有者を明示的にクエリし、正確な所有者(
_grantor
)をhasRole
関数に渡す責任があります。 - これにより、ロールの割り当てが正確であることを保証できます。
-
ERC7432はNFTの所有権を自動的に確認しないため、dAppはNFTの所有者を明示的にクエリし、正確な所有者(
-
ユニークまたはノンユニークなロールの確認
- ロールがユニーク(一度に1つのアカウントにしか割り当てられない)かノンユニーク(複数のアカウントに同時に割り当てられる)かを確認する責任はdAppにあります。
- ユニークなロールの場合、他のアカウントに割り当てられていないことを確認するために、
hasUniqueRole
関数を使用する必要があります。
引用
Ernani São Thiago (@ernanirst), Daniel Lima (@karacurt), "ERC-7432: Non-Fungible Token Roles [DRAFT]," Ethereum Improvement Proposals, no. 7432, July 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7432.
最後に
今回は「NFTのさまざまなロールを管理するインターフェースを提案しているERC7432」についてまとめてきました!
いかがだったでしょうか?
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!
他の媒体でも情報発信しているのでぜひ他も見ていってください!