# [ERC7508] NFTにさまざまな属性情報を持たせて管理する仕組みを理解しよう！

> この提案は、ERC721とERC1155という2つの異なるトークン規格を使っているトークン（通常、デジタルアセットやゲームアイテムなど）に関連しています。

- URL: https://cardene.dev/articles/83b2bfcc0499556cb8a0
- 公開日: 2023-09-28
- 更新日: 2023-09-28
- トピック: Blockchain
- タグ: ethereum, solidity, ブロックチェーン, nft

## はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、NFTにさまざまな属性情報を持たせて管理する仕組みを提案している**ERC7508**についてまとめていきます！

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

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

:::message alert
**7508**は現在（2023年9月22日）では「**Draft**」段階です。
:::

## 概要

この提案は、**ERC721**と**ERC1155**という2つの異なるトークン規格を使っているトークン（通常、デジタルアセットやゲームアイテムなど）に関連しています。
これらのトークンは、個々のトークンごとに異なる属性情報（たとえば、アーティスト名、製造日、レア度など）を持つことがあります。

この提案は、これらの属性情報をブロックチェーン上に保存し、他のスマートコントラクトなど外部のプログラムからアクセス可能にする方法を提供します。
この属性情報を格納するための特別な場所（**The Public On-Chain Non-Fungible Token Attributes Repository**）があり、これはすべてのネットワークで同じアドレスでアクセス可能です。
これにより、どのネットワークでも同じ情報にアクセスできます。

このリポジトリスマートコントラクトは、共通のリソースとして提供され、**ERC721**や**ERC1155**に準拠したトークンを持つプロジェクトや開発者に利用されることが期待されています。

:::message
異なるプロジェクトやトークンを持つ人々が同じリポジトリを使用して属性情報を管理できるようになります。
これにより、トークンの属性情報をブロックチェーン上で効率的に管理し、他のスマートコントラクトと連携するための共通のプラットフォームが提供されることになります。
:::

## 動機

NFT（非代替可能トークン）は、Ethereumエコシステム内で広く使用され、デジタルアセットやゲームアイテムなどのさまざまな用途に利用されています。
しかし、これらのNFTにはさらに多くのユーティリティ（実用性）を提供する必要があります。
このERC（Ethereumの提案規格）は、NFTに対して新たな機能を標準化し、以下の機能を実現します。

### コレクション間のインタラクティブ性
異なるNFTコレクション間でトークンを簡単にやり取りできるようにする機能です。
あるNFTを別のNFTコレクションに移したり、相互に統合したりできるようになります。
これにより、NFTの交換や利用がより柔軟になります。

### 属性情報の永続的な保管
トークンの属性情報を永続的にブロックチェーン上に保存します。
これにより、属性情報が失われることなく、トークンの歴史と価値を確保できます。
属性情報はいつでもアクセス可能です。

### トークンの進化
NFTは時間とともに進化することができ、新しい機能や属性を獲得できるようになります。
これにより、NFTがより魅力的になり、コミュニティやプロジェクトに新たな可能性をもたらします。

### 動的な状態の追跡
NFTの状態をリアルタイムで追跡および更新できる機能です。
これにより、トークンの現在の状態を効果的に監視し、スマートコントラクトとの連携を強化できます。
これは特にゲーム内アイテムなどで有用です。

:::message
このERCは、NFTのユーティリティを向上させ、異なるNFTコレクション間での相互作用を強化し、属性情報を確実に保管し、トークンの進化と動的な状態追跡を可能にするものです。
これにより、NFTはより多くの業界やプロジェクトで利用され、より価値のあるデジタルアセットとなります。
:::

### コレクション間のインタラクティブ性（Cross-Collection Interactivity）
ブロックチェーン上で属性情報を一貫性のある形式で格納することで、トークンの属性情報は外部のスマートコントラクトがそれを利用する際に、トークンがその外部スマートコントラクトの存在を意識する必要がありません。
例えば、あるトークンがゲームのキャラクターを表す場合、その属性情報は別のゲームで同じステータスとして再利用でき、オフチェーンの情報源から属性情報を再度取得する必要がありません。
これにより、異なるゲーム間で属性情報を共有し、不正な変更を防ぎ、信頼性を確保できます。

### 属性情報の永続的な保管（Perpetual Store of Attributes）
ブロックチェーン上で属性情報を標準化して格納することで、属性情報は永遠に保持されます。
オフチェーンの属性情報ストレージでは、その情報はオフチェーンストレージが利用可能な期間限定でのみ利用可能です。
しかし、ブロックチェーン上の属性情報ストレージでは、属性情報はブロックチェーンが存在する限り利用可能です。
これにより、トークンの価値が持続的に保たれ、属性情報がトークンの存在と共に存続することが確約されます。

### トークンの進化（Token Evolution）
ブロックチェーン上でトークンの属性情報を格納することで、トークンは時間とともに進化できます。
所有者のアクションによって属性情報が変更される可能性があります。
属性情報がチェーン上に保存されているため、スマートコントラクトは特定の条件が満たされた場合に属性を変更することができます。
これにより、トークンはよりインタラクティブになり、所有者の取り組みや努力を反映することができます。

### 動的な状態の追跡（Dynamic State Tracking）
ブロックチェーン上でトークンの属性情報を格納することで、トークンとその所有者の状態をリアルタイムで追跡できます。
これにより、トークンはさまざまな用途で使用できます。
例えば、サプライチェーンにおいて、トークンは製品を表し、その属性情報は製品の「**保留中**」「**発送済み**」「**配達済み**」などの状態を追跡するために使用できます。
これは、物流管理などの分野で非常に有用です。

:::message
これらの機能は、NFTの価値を向上させ、異なる業界やプロジェクトで新たな可能性を開くのに役立ちます。
属性情報をブロックチェーン上に格納することで、データの信頼性と透明性が確保され、NFTのユーティリティが大幅に向上します。
:::


## 仕様

```javascript
/// @title ERC-7508 Public On-Chain NFT Attributes Repository
/// @dev See https://eips.ethereum.org/EIPS/eip-7508
/// @dev Note: the ERC-165 identifier for this interface is 0x07cd44c7.

pragma solidity ^0.8.21;

interface IRMRKTokenAttributesRepository /*is IERC165*/ {
    /**
     * @notice A list of supported access types.
     * @return The `Issuer` type, where only the issuer can manage the parameter.
     * @return The `Collaborator` type, where only the collaborators can manage the parameter.
     * @return The `IssuerOrCollaborator` type, where only the issuer or collaborators can manage the parameter.
     * @return The `TokenOwner` type, where only the token owner can manage the parameters of their tokens.
     * @return The `SpecificAddress` type, where only specific addresses can manage the parameter.
     */
    enum AccessType {
        Issuer,
        Collaborator,
        IssuerOrCollaborator,
        TokenOwner,
        SpecificAddress
    }

    /**
     * @notice Structure used to represent a string attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct StringAttribute {
        string key;
        string value;
    }

    /**
     * @notice Structure used to represent an uint attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct UintAttribute {
        string key;
        uint256 value;
    }

    /**
     * @notice Structure used to represent a boolean attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct BoolAttribute {
        string key;
        bool value;
    }

    /**
     * @notice Structure used to represent an address attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct AddressAttribute {
        string key;
        address value;
    }

    /**
     * @notice Structure used to represent a bytes attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct BytesAttribute {
        string key;
        bytes value;
    }

    /**
     * @notice Used to notify listeners that a new collection has been registered to use the repository.
     * @param collection Address of the collection
     * @param issuer Address of the issuer of the collection; the addess authorized to manage the access control
     * @param registeringAddress Address that registered the collection
     * @param useOwnable A boolean value indicating whether the collection uses the Ownable extension to verify the
     *  issuer (`true`) or not (`false`)
     */
    event AccessControlRegistration(
        address indexed collection,
        address indexed issuer,
        address indexed registeringAddress,
        bool useOwnable
    );

    /**
     * @notice Used to notify listeners that the access control settings for a specific parameter have been updated.
     * @param collection Address of the collection
     * @param key The name of the parameter for which the access control settings have been updated
     * @param accessType The AccessType of the parameter for which the access control settings have been updated
     * @param specificAddress The specific addresses that has been updated
     */
    event AccessControlUpdate(
        address indexed collection,
        string key,
        AccessType accessType,
        address specificAddress
    );

    /**
     * @notice Used to notify listeners that a new collaborator has been added or removed.
     * @param collection Address of the collection
     * @param collaborator Address of the collaborator
     * @param isCollaborator A boolean value indicating whether the collaborator has been added (`true`) or removed
     *  (`false`)
     */
    event CollaboratorUpdate(
        address indexed collection,
        address indexed collaborator,
        bool isCollaborator
    );

    /**
     * @notice Used to notify listeners that a string attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event StringAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        string value
    );

    /**
     * @notice Used to notify listeners that an uint attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event UintAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        uint256 value
    );

    /**
     * @notice Used to notify listeners that a boolean attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event BoolAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        bool value
    );

    /**
     * @notice Used to notify listeners that an address attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event AddressAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        address value
    );

    /**
     * @notice Used to notify listeners that a bytes attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event BytesAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        bytes value
    );

    /**
     * @notice Used to register a collection to use the RMRK token attributes repository.
     * @dev  If the collection does not implement the Ownable interface, the `useOwnable` value must be set to `false`.
     * @dev Emits an {AccessControlRegistration} event.
     * @param collection The address of the collection that will use the RMRK token attributes repository.
     * @param issuer The address of the issuer of the collection.
     * @param useOwnable The boolean value to indicate if the collection implements the Ownable interface and whether it
     *  should be used to validate that the caller is the issuer (`true`) or to use the manually set issuer address
     *  (`false`).
     */
    function registerAccessControl(
        address collection,
        address issuer,
        bool useOwnable
    ) external;

    /**
     * @notice Used to manage the access control settings for a specific parameter.
     * @dev Only the `issuer` of the collection can call this function.
     * @dev The possible `accessType` values are:
     *  [
     *      Issuer,
     *      Collaborator,
     *      IssuerOrCollaborator,
     *      TokenOwner,
     *      SpecificAddress,
     *  ]
     * @dev Emits an {AccessControlUpdated} event.
     * @param collection The address of the collection being managed.
     * @param key The key of the attribute
     * @param accessType The type of access control to be applied to the parameter.
     * @param specificAddress The address to be added as a specific addresses allowed to manage the given
     *  parameter.
     */
    function manageAccessControl(
        address collection,
        string memory key,
        AccessType accessType,
        address specificAddress
    ) external;

    /**
     * @notice Used to manage the collaborators of a collection.
     * @dev The `collaboratorAddresses` and `collaboratorAddressAccess` arrays must be of the same length.
     * @dev Emits a {CollaboratorUpdate} event.
     * @param collection The address of the collection
     * @param collaboratorAddresses The array of collaborator addresses being managed
     * @param collaboratorAddressAccess The array of boolean values indicating if the collaborator address should
     *  receive the permission (`true`) or not (`false`).
     */
    function manageCollaborators(
        address collection,
        address[] memory collaboratorAddresses,
        bool[] memory collaboratorAddressAccess
    ) external;

    /**
     * @notice Used to set a number attribute.
     * @dev Emits a {UintAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setUintAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        uint256 value
    ) external;

    /**
     * @notice Used to set a string attribute.
     * @dev Emits a {StringAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setStringAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        string memory value
    ) external;

    /**
     * @notice Used to set a boolean attribute.
     * @dev Emits a {BoolAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setBoolAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bool value
    ) external;

    /**
     * @notice Used to set an bytes attribute.
     * @dev Emits a {BytesAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setBytesAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bytes memory value
    ) external;

    /**
     * @notice Used to set an address attribute.
     * @dev Emits a {AddressAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setAddressAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        address value
    ) external;

    /**
     * @notice Sets multiple string attributes for a token at once.
     * @dev The `StringAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      string value
     *  ]
     * @param collection Address of the collection
     * @param tokenId ID of the token
     * @param attributes An array of `StringAttribute` structs to be assigned to the given token
     */
    function setStringAttributes(
        address collection,
        uint256 tokenId,
        StringAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple uint attributes for a token at once.
     * @dev The `UintAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      uint value
     *  ]
     * @param collection Address of the collection
     * @param tokenId ID of the token
     * @param attributes An array of `UintAttribute` structs to be assigned to the given token
     */
    function setUintAttributes(
        address collection,
        uint256 tokenId,
        UintAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple bool attributes for a token at once.
     * @dev The `BoolAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      bool value
     *  ]
     * @param collection Address of the collection
     * @param tokenId ID of the token
     * @param attributes An array of `BoolAttribute` structs to be assigned to the given token
     */
    function setBoolAttributes(
        address collection,
        uint256 tokenId,
        BoolAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple address attributes for a token at once.
     * @dev The `AddressAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      address value
     *  ]
     * @param collection Address of the collection
     * @param tokenId ID of the token
     * @param attributes An array of `AddressAttribute` structs to be assigned to the given token
     */
    function setAddressAttributes(
        address collection,
        uint256 tokenId,
        AddressAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple bytes attributes for a token at once.
     * @dev The `BytesAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      bytes value
     *  ]
     * @param collection Address of the collection
     * @param tokenId ID of the token
     * @param attributes An array of `BytesAttribute` structs to be assigned to the given token
     */
    function setBytesAttributes(
        address collection,
        uint256 tokenId,
        BytesAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple attributes of multiple types for a token at the same time.
     * @dev Emits a separate event for each attribute set.
     * @dev The `StringAttribute`, `UintAttribute`, `BoolAttribute`, `AddressAttribute` and `BytesAttribute` structs consists
     *  to the following fields (where `value` is of the appropriate type):
     *  [
     *      key,
     *      value,
     *  ]
     * @param collection The address of the collection
     * @param tokenId The token ID
     * @param stringAttributes An array of `StringAttribute` structs containing string attributes to set
     * @param uintAttributes An array of `UintAttribute` structs containing uint attributes to set
     * @param boolAttributes An array of `BoolAttribute` structs containing bool attributes to set
     * @param addressAttributes An array of `AddressAttribute` structs containing address attributes to set
     * @param bytesAttributes An array of `BytesAttribute` structs containing bytes attributes to set
     */
    function setTokenAttributes(
        address collection,
        uint256 tokenId,
        StringAttribute[] memory stringAttributes,
        UintAttribute[] memory uintAttributes,
        BoolAttribute[] memory boolAttributes,
        AddressAttribute[] memory addressAttributes,
        BytesAttribute[] memory bytesAttributes
    ) external;

    /**
     * @notice Used to set the uint attribute on behalf of an authorized account.
     * @dev Emits a {UintAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetUintAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the string attribute on behalf of an authorized account.
     * @dev Emits a {StringAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetStringAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        string memory value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the bool attribute on behalf of an authorized account.
     * @dev Emits a {BoolAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetBoolAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        bool value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the bytes attribute on behalf of an authorized account.
     * @dev Emits a {BytesAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetBytesAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        bytes memory value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the address attribute on behalf of an authorized account.
     * @dev Emits a {AddressAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetAddressAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        address value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to check if the specified address is listed as a collaborator of the given collection's parameter.
     * @param collaborator Address to be checked.
     * @param collection Address of the collection.
     * @return Boolean value indicating if the address is a collaborator of the given collection's (`true`) or not
     *  (`false`).
     */
    function isCollaborator(
        address collaborator,
        address collection
    ) external view returns (bool);

    /**
     * @notice Used to check if the specified address is listed as a specific address of the given collection's
     *  parameter.
     * @param specificAddress Address to be checked.
     * @param collection Address of the collection.
     * @param key The key of the attribute
     * @return Boolean value indicating if the address is a specific address of the given collection's parameter
     *  (`true`) or not (`false`).
     */
    function isSpecificAddress(
        address specificAddress,
        address collection,
        string memory key
    ) external view returns (bool);

    /**
     * @notice Used to retrieve the string type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return The value of the string attribute
     */
    function getStringTokenAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (string memory);

    /**
     * @notice Used to retrieve the uint type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return The value of the uint attribute
     */
    function getUintTokenAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (uint256);

    /**
     * @notice Used to retrieve the bool type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return The value of the bool attribute
     */
    function getBoolTokenAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (bool);

    /**
     * @notice Used to retrieve the address type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return The value of the address attribute
     */
    function getAddressTokenAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (address);

    /**
     * @notice Used to retrieve the bytes type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return The value of the bytes attribute
     */
    function getBytesTokenAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (bytes memory);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned uint attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignUintAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        uint256 value,
        uint256 deadline
    ) external view returns (bytes32);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned string attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignStringAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        string memory value,
        uint256 deadline
    ) external view returns (bytes32);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned bool attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignBoolAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bool value,
        uint256 deadline
    ) external view returns (bytes32);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned bytes attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignBytesAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bytes memory value,
        uint256 deadline
    ) external view returns (bytes32);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned address attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignAddressAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        address value,
        uint256 deadline
    ) external view returns (bytes32);

    /**
     * @notice Used to retrieve multiple token attributes of any type at once.
     * @dev The `StringAttribute`, `UintAttribute`, `BoolAttribute`, `AddressAttribute` and `BytesAttribute` structs consists
     *  to the following fields (where `value` is of the appropriate type):
     *  [
     *      key,
     *      value,
     *  ]
     * @param collection The collection address
     * @param tokenId The token ID
     * @param stringKeys An array of string type attribute keys to retrieve
     * @param uintKeys An array of uint type attribute keys to retrieve
     * @param boolKeys An array of bool type attribute keys to retrieve
     * @param addressKeys An array of address type attribute keys to retrieve
     * @param bytesKeys An array of bytes type attribute keys to retrieve
     * @return stringAttributes An array of `StringAttribute` structs containing the string type attributes
     * @return uintAttributes An array of `UintAttribute` structs containing the uint type attributes
     * @return boolAttributes An array of `BoolAttribute` structs containing the bool type attributes
     * @return addressAttributes An array of `AddressAttribute` structs containing the address type attributes
     * @return bytesAttributes An array of `BytesAttribute` structs containing the bytes type attributes
     */
    function getTokenAttributes(
        address collection,
        uint256 tokenId,
        string[] memory stringKeys,
        string[] memory uintKeys,
        string[] memory boolKeys,
        string[] memory addressKeys,
        string[] memory bytesKeys
    )
        external
        view
        returns (
            StringAttribute[] memory stringAttributes,
            UintAttribute[] memory uintAttributes,
            BoolAttribute[] memory boolAttributes,
            AddressAttribute[] memory addressAttributes,
            BytesAttribute[] memory bytesAttributes
        );

    /**
     * @notice Used to get multiple sting parameter values for a token.
     * @dev The `StringAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     string value
     *  ]
     * @param collection Address of the collection the token belongs to
     * @param tokenId ID of the token for which the attributes are being retrieved
     * @param stringKeys An array of string keys to retrieve
     * @return An array of `StringAttribute` structs
     */
    function getStringTokenAttributes(
        address collection,
        uint256 tokenId,
        string[] memory stringKeys
    ) external view returns (StringAttribute[] memory);

    /**
     * @notice Used to get multiple uint parameter values for a token.
     * @dev The `UintAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     uint value
     *  ]
     * @param collection Address of the collection the token belongs to
     * @param tokenId ID of the token for which the attributes are being retrieved
     * @param uintKeys An array of uint keys to retrieve
     * @return An array of `UintAttribute` structs
     */
    function getUintTokenAttributes(
        address collection,
        uint256 tokenId,
        string[] memory uintKeys
    ) external view returns (UintAttribute[] memory);

    /**
     * @notice Used to get multiple bool parameter values for a token.
     * @dev The `BoolAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     bool value
     *  ]
     * @param collection Address of the collection the token belongs to
     * @param tokenId ID of the token for which the attributes are being retrieved
     * @param boolKeys An array of bool keys to retrieve
     * @return An array of `BoolAttribute` structs
     */
    function getBoolTokenAttributes(
        address collection,
        uint256 tokenId,
        string[] memory boolKeys
    ) external view returns (BoolAttribute[] memory);

    /**
     * @notice Used to get multiple address parameter values for a token.
     * @dev The `AddressAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     address value
     *  ]
     * @param collection Address of the collection the token belongs to
     * @param tokenId ID of the token for which the attributes are being retrieved
     * @param addressKeys An array of address keys to retrieve
     * @return An array of `AddressAttribute` structs
     */
    function getAddressTokenAttributes(
        address collection,
        uint256 tokenId,
        string[] memory addressKeys
    ) external view returns (AddressAttribute[] memory);

    /**
     * @notice Used to get multiple bytes parameter values for a token.
     * @dev The `BytesAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     bytes value
     *  ]
     * @param collection Address of the collection the token belongs to
     * @param tokenId ID of the token for which the attributes are being retrieved
     * @param bytesKeys An array of bytes keys to retrieve
     * @return An array of `BytesAttribute` structs
     */
    function getBytesTokenAttributes(
        address collection,
        uint256 tokenId,
        string[] memory bytesKeys
    ) external view returns (BytesAttribute[] memory);
}
```

#### AccessType

```javascript
enum AccessType {
    Issuer,
    Collaborator,
    IssuerOrCollaborator,
    TokenOwner,
    SpecificAddress
}
```

**概要**
サポートされているアクセスタイプの列挙型。

**パラメータ**
- `Issuer`
    - 発行者だけがパラメータを管理できるタイプ。
- `Collaborator`
    - 協力者だけがパラメータを管理できるタイプ。
- `IssuerOrCollaborator`
    - 発行者または協力者だけがパラメータを管理できるタイプ。
- `TokenOwner`
    - トークン所有者だけが自身のトークンのパラメータを管理できるタイプ。
- `SpecificAddress`
    - 特定のアドレスだけがパラメータを管理できるタイプ。

---

#### StringAttribute

```javascript
struct StringAttribute {
    string key;
    string value;
}
```

**概要**
文字列属性を表す構造体。

**パラメータ**
- `key`: 属性のキー。
- `value`: 属性の値。

---

#### UintAttribute

```javascript
struct UintAttribute {
    string key;
    uint256 value;
}
```

**概要**
整数属性を表す構造体。

**パラメータ**
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### BoolAttribute

```javascript
struct BoolAttribute {
    string key;
    bool value;
}
```

**概要**
ブール属性を表す構造体。

**パラメータ**
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### AddressAttribute

```javascript
struct AddressAttribute {
    string key;
    address value;
}
```

**概要**
アドレス属性を表す構造体。

**パラメータ**
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### BytesAttribute

```javascript
struct BytesAttribute {
    string key;
    bytes value;
}
```

**概要**
バイト属性を表す構造体。

**パラメータ**
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### AccessControlRegistration

```javascript
event AccessControlRegistration(
    address indexed collection,
    address indexed issuer,
    address indexed registeringAddress,
    bool useOwnable
);
```

**概要**
新しいコレクションがリポジトリを使用するために登録された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `issuer`
    - コレクションの発行者のアドレス。
- `registeringAddress`
    - コレクションを登録したアドレス。
- `useOwnable`
    - コレクションがOwnable拡張を使用するかどうかを示すブール値。

---

#### AccessControlUpdate

```javascript
event AccessControlUpdate(
    address indexed collection,
    string key,
    AccessType accessType,
    address specificAddress
);
```

**概要**
特定のパラメータのアクセス制御設定が更新された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `key`
    - アクセス制御設定が更新されたパラメータの名前。
- `accessType`
    - アクセス制御設定が更新されたパラメータのAccessType。
- `specificAddress`
    - 更新された特定のアドレス。

---

#### CollaboratorUpdate

```javascript
event CollaboratorUpdate(
    address indexed collection,
    address indexed collaborator,
    bool isCollaborator
);
```

**概要**
協力者が追加または削除された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `collaborator`
    - 協力者のアドレス。
- `isCollaborator`
    - 協力者が追加されたか削除されたかを示すブール値。

---

#### StringAttributeUpdated

```javascript
event StringAttributeUpdated(
    address indexed collection,
    uint256 indexed tokenId,
    string key,
    string value
);
```

**概要**
文字列属性が更新された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 新しい属性の値。

---

#### UintAttributeUpdated

```javascript
event UintAttributeUpdated(
    address indexed collection,
    uint256 indexed tokenId,
    string key,
    uint256 value
);
```

**概要**
整数属性が更新された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 新しい属性の値。

---

#### BoolAttributeUpdated

```javascript
event BoolAttributeUpdated(
    address indexed collection,
    uint256 indexed tokenId,
    string key,
    bool value
);
```

**

概要**
ブール属性が更新された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 新しい属性の値。

---

#### AddressAttributeUpdated

```javascript
event AddressAttributeUpdated(
    address indexed collection,
    uint256 indexed tokenId,
    string key,
    address value
);
```

**概要**
アドレス属性が更新された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 新しい属性の値。

---

#### BytesAttributeUpdated

```javascript
event BytesAttributeUpdated(
    address indexed collection,
    uint256 indexed tokenId,
    string key,
    bytes value
);
```

**概要**
バイト属性が更新された時に発行されるイベント。

**パラメータ**
- `collection`
    - コレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 新しい属性の値。

---

#### registerAccessControl

```javascript
function registerAccessControl(
    address collection,
    address issuer,
    bool useOwnable
) external;
```

**概要**

RMRKトークン属性リポジトリを使用するコレクションを登録する関数。

**詳細**

コレクションが`Ownable`インターフェースを実装していない場合、`useOwnable`の値は`false`に設定する必要があります。
この関数は、`AccessControlRegistration`イベントを発行します。

**引数**

- `collection`
    - RMRKトークン属性リポジトリを使用するコレクションのアドレス。
- `issuer`
    - コレクションの発行者のアドレス。
- `useOwnable`
    - コレクションが`Ownable`インターフェースを実装しているかどうかを示すブール値。
    - 発行者を検証するために`Ownable`を使用する場合は`true`、手動で設定された発行者アドレスを使用する場合は`false`。

---

#### manageAccessControl

```javascript
function manageAccessControl(
    address collection,
    string memory key,
    AccessType accessType,
    address specificAddress
) external;
```

**概要**

特定のパラメータのアクセス制御設定を管理する関数。

**詳細**

この関数は、指定されたコレクションの発行者だけが呼び出せます。
可能な`accessType`の値は以下の値です。
`[Issuer, Collaborator, IssuerOrCollaborator, TokenOwner, SpecificAddress]`。
この関数は、`AccessControlUpdated`イベントを発行します。

**引数**

- `collection`
    - 管理されているコレクションのアドレス。
- `key`
    - 属性のキー。
- `accessType`
    - パラメータに適用されるアクセス制御のタイプ。
- `specificAddress`
    - 指定されたアドレスを特定のアドレスとして許可するためのアドレス。

---

#### manageCollaborators

```javascript
function manageCollaborators(
    address collection,
    address[] memory collaboratorAddresses,
    bool[] memory collaboratorAddressAccess
) external;
```

**概要**

コレクションの協力者を管理する関数。

**詳細**

`collaboratorAddresses`と`collaboratorAddressAccess`の配列は同じ長さである必要があります。
この関数は、`CollaboratorUpdate`イベントを発行します。

**引数**

- `collection`
    - コレクションのアドレス。
- `collaboratorAddresses`
    - 管理されている協力者のアドレスの配列。
- `collaboratorAddressAccess`
    - 協力者アドレスが許可を受け取る場合は`true`、それ以外の場合は`false`を示すブール値の配列。

---

#### setUintAttribute

```javascript
function setUintAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    uint256 value
) external;
```

**概要**

整数属性を設定する関数。

**詳細**

指定されたコレクションに整数属性を設定します。
`UintAttributeUpdated`イベントを発行します。

**引数**

- `collection`
    - 属性を受け取るコレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### setStringAttribute

```javascript
function setStringAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    string memory value
) external;
```

**概要**

文字列属性を設定する関数。

**詳細**

指定されたコレクションに文字列属性を設定します。
`StringAttributeUpdated`イベントを発行します。

**引数**

- `collection`
    - 属性を受け取るコレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### setBoolAttribute

```javascript
function setBoolAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    bool value
) external;
```

**概要**

ブール属性を設定する関数。

**詳細**

指定されたコレクションにブール属性を設定します。
`BoolAttributeUpdated`イベントを発行します。

**引数**

- `collection`
    - 属性を受け取るコレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### setBytesAttribute

```javascript
function setBytesAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    bytes memory value
) external;
```

**概要**

バイト属性を設定する関数。

**詳細**

指定されたコレクションにバイト属性を設定します。
`BytesAttributeUpdated`イベントを発行します。

**引数**

- `collection`
    - 属性を受け取るコレクションのアドレス。
- `tokenId`
    - トークンのID。
- `key`
    - 属性のキー。
- `value`
    - 属性の値。

---

#### setAddressAttribute

```javascript
function setAddressAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    address value
) external;
```

**概要**

指定されたコレクションとトークンに対してアドレス属性を設定する関数。

**詳細**

指定されたコレクションとトークンに対して、指定されたキーでアドレス属性を設定します。
属性の値として、アドレス（`address`型）が提供されます。
属性が設定されると、`AddressAttributeUpdated`イベントが発行されます。

**引数**

- `collection`
  - アドレス属性を設定するコレクションのアドレス。
- `tokenId`
  - アドレス属性を設定するトークンのID。
- `key`
  - 属性のキー。属性を一意に識別するための文字列です。
- `value`
  - 属性の値として設定するアドレス。

---

#### setStringAttributes

```javascript
function setStringAttributes(
    address collection,
    uint256 tokenId,
    StringAttribute[] memory attributes
) external;
```

**概要**

指定されたコレクションとトークンに対して複数の文字列属性を一度に設定する関数。

**詳細**

指定されたコレクションとトークンに対して、一度に複数の文字列属性を設定します。
`attributes`パラメータには、`StringAttribute`構造体の配列が提供されます。
各構造体は属性のキーと値を持っており、これらは指定されたトークンに割り当てられます。

**引数**

- `collection`
  - 文字列属性を設定するコレクションのアドレス。
- `tokenId`
  - 文字列属性を設定するトークンのID。
- `attributes`
  - `StringAttribute`構造体の配列。
  - 各構造体は文字列属性の情報を保持しています。

---

#### setUintAttributes

```javascript
function setUintAttributes(
    address collection,
    uint256 tokenId,
    UintAttribute[] memory attributes
) external;
```

**概要**
指定されたコレクションとトークンに対して複数の整数属性を一度に設定する関数。

**詳細**
指定されたコレクションとトークンに対して、一度に複数の整数属性を設定します。
`attributes`パラメータには、`UintAttribute`構造体の配列が提供されます。
各構造体は属性のキーと値を持っており、これらは指定されたトークンに割り当てられます。

**引数**

- `collection`
  - 整数属性を設定するコレクションのアドレス。
- `tokenId`
  - 整数属性を設定するトークンのID。
- `attributes`
  - `UintAttribute` 構造体の配列。
  - 各構造体は整数属性の情報を保持しています。

---

#### setBoolAttributes

```javascript
function setBoolAttributes(
    address collection,
    uint256 tokenId

,
    BoolAttribute[] memory attributes
) external;
```

**概要**

指定されたコレクションとトークンに対して複数の真偽値属性を一度に設定する関数。

**詳細**

指定されたコレクションとトークンに対して、一度に複数の真偽値属性を設定します。
`attributes`パラメータには、`BoolAttribute`構造体の配列が提供されます。
各構造体は属性のキーと真偽値を持っており、これらは指定されたトークンに割り当てられます。


**引数**

- `collection`
  - 真偽値属性を設定するコレクションのアドレス。
- `tokenId`
  - 真偽値属性を設定するトークンのID。
- `attributes`
  - `BoolAttribute` 構造体の配列。
  - 各構造体は真偽値属性の情報を保持しています。

---

#### setAddressAttributes

```javascript
function setAddressAttributes(
    address collection,
    uint256 tokenId,
    AddressAttribute[] memory attributes
) external;
```

**概要**

指定されたコレクションとトークンに対して複数のアドレス属性を一度に設定する関数。

**詳細**

この関数は、指定されたコレクションとトークンに対して、一度に複数のアドレス属性を設定します。
`attributes`パラメータには、`AddressAttribute`構造体の配列が提供されます。
各構造体は属性のキーとアドレスを持っており、これらは指定されたトークンに割り当てられます。

**引数**

- `collection`
  - アドレス属性を設定するコレクションのアドレス。
- `tokenId`
  - アドレス属性を設定するトークンのID。
- `attributes`
  - `AddressAttribute` 構造体の配列。
  - 各構造体はアドレス属性の情報を保持しています。

---

#### setBytesAttributes

```javascript
function setBytesAttributes(
    address collection,
    uint256 tokenId,
    BytesAttribute[] memory attributes
) external;
```

**概要**

指定されたコレクションとトークンに対して複数のバイト属性を一度に設定する関数。

**詳細**

指定されたコレクションとトークンに対して、一度に複数のバイト属性を設定します。
`attributes`パラメータには、`BytesAttribute`構造体の配列が提供されます。
各構造体は属性のキーとバイトデータを持っており、これらは指定されたトークンに割り当てられます。

**引数**

- `collection`
  - バイト属性を設定するコレクションのアドレス。
- `tokenId`
  - バイト属性を設定するトークンのID。
- `attributes`
  - `BytesAttribute`構造体の配列。
  - 各構造体はバイト属性の情報を保持しています。

---

#### setTokenAttributes

```javascript
function setTokenAttributes(
    address collection,
    uint256 tokenId,
    StringAttribute[] memory stringAttributes,
    UintAttribute[] memory uintAttributes,
    BoolAttribute[] memory boolAttributes,
    AddressAttribute[] memory addressAttributes,
    BytesAttribute[] memory bytesAttributes
) external;
```

**概要**

指定されたコレクションとトークンに対して、複数の異なる属性を一度に設定する関数。

**詳細**

指定されたコレクションとトークンに対して、文字列属性、整数属性、真偽値属性、アドレス属性、およびバイト属性を一度に設定します。
それぞれの属性タイプは、対応する構造体の配列で指定されます。
各構造体は属性のキーと値を持っており、これらは指定されたトークンに割り当てられます。
各属性の設定ごとに個別のイベントが発行されます。

**引数**

- `collection`
  - 属性を設定するコレクションのアドレス。
- `tokenId`
  - 属性を設定するトークンのID。
- `stringAttributes`
  - 文字列属性を設定するための`StringAttribute`構造体の配列。
- `uintAttributes`
  - 整数属性を設定するための`UintAttribute`構造体の配列。
- `boolAttributes`
  - 真偽値属性を設定するための`BoolAttribute`構造体の配列。
- `addressAttributes`
  - アドレス属性を設定するための`AddressAttribute`構造体の配列。
- `bytesAttributes`
  - バイト属性を設定するための`BytesAttribute`構造体の配列。

---

#### presignedSetUintAttribute

```javascript
function presignedSetUintAttribute(
    address setter,
    address collection,
    uint256 tokenId,
    string memory key,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```

**概要**

承認されたアカウントを代表して整数属性を設定する関数。

**詳細**

特定のアカウントが事前に署名したメッセージを使用して整数属性を設定します。
これにより、他のアカウントが設定する前に属性の変更を承認することができます。
属性が設定されると、`UintAttributeUpdated`イベントが発行されます。

**引数**

- `setter`
  - 属性変更を事前に署名したアカウントのアドレス。
- `collection`
  - 属性を設定するコレクションのアドレス。
- `tokenId`
  - 属性を設定するトークンのID。
- `key`
  - 属性のキー。属性を一意に識別するための文字列です。
- `value`
  - 属性の値として設定する整数。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。
  - このタイムスタンプまでにトランザクションを実行する必要があります。
- `v`
  - ECDSA署名の`v`値。
- `r`
  - ECDSA署名の`r`値。
- `s`
  - ECDSA署名の`s`値。

---


#### presignedSetStringAttribute

```javascript
function presignedSetStringAttribute(
    address setter,
    address collection,
    uint256 tokenId,
    string memory key,
    string memory value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```

**概要**

承認されたアカウントを代表して文字列属性を設定する関数。

**詳細**

特定のアカウントが事前に署名したメッセージを使用して文字列属性を設定します。
これにより、他のアカウントが設定する前に属性の変更を承認することができます。
属性が設定されると、`StringAttributeUpdated`イベントが発行されます。

**引数**

- `setter`
  - 属性変更を事前に署名したアカウントのアドレス。
- `collection`
  - 属性を設定するコレクションのアドレス。
- `tokenId`
  - 属性を設定するトークンのID。
- `key`
  - 属性のキー。属性を一意に識別するための文字列です。
- `value`
  - 属性の値として設定する文字列。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。
  - このタイムスタンプまでにトランザクションを実行する必要があります。
- `v`
  - ECDSA署名の`v`値。
- `r`
  - ECDSA署名の`r`値。
- `s`
  - ECDSA署名の`s`値。

---

#### presignedSetBoolAttribute

```javascript
function presignedSetBoolAttribute(
    address setter,
    address collection,
    uint256 tokenId,
    string memory key,
    bool value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```

**概要**

承認されたアカウントを代表して真偽値属性を設定する関数。

**詳細**

この関数は、特定のアカウントが事前に署名したメッセージを使用して真偽値属性を設定します。
これにより、他のアカウントが設定する前に属性の変更を承認することができます。
属性が設定されると、`BoolAttributeUpdated`イベントが発行されます。

**引数**

- `setter`
  - 属性変更を事前に署名したアカウントのアドレス。
- `collection`
  - 属性を設定するコレクションのアドレス。
- `tokenId`
  - 属性を設定するトークンのID。
- `key`
  - 属性のキー。
  - 属性を一意に識別するための文字列です。
- `value`
  - 属性の値として設定する真偽値。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。
  - このタイムスタンプまでにトランザクションを実行する必要があります。
- `v`
  - ECDSA署名の`v`値。
- `r`
  - ECDSA署名の`r`値。
- `s`
  - ECDSA署名の`s`値。

---

#### presignedSetBytesAttribute

```javascript
function presignedSetBytesAttribute(
    address setter,
    address collection,
    uint256 tokenId,
    string memory key,
    bytes memory value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```

**概要**

承認されたアカウントを代表してバイト属性を設定する関数。

**詳細**

この関数は、特定のアカウントが事前に署名したメッセージを使用してバイト属性を設定します。
これにより、他のアカウントが設定する前に属性の変更を承認することができます。
属性が設定されると、`BytesAttributeUpdated`イベントが発行されます。


**引数**

- `setter`
  - 属性変更を事前に署名したアカウントのアドレス。
- `collection`
  - 属性を設定するコレクションのアドレス。
- `tokenId`
  - 属性を設定するトークンのID。
- `key`
  - 属性のキー。
  - 属性を一意に識別するための文字列です。
- `value`
  - 属性の値として設定するバイト列。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。
  - このタイムスタンプまでにトランザクションを実行する必要があります。
- `v`
  - ECDSA署名の`v`値。
- `r`
  - ECDSA署名の`r`値。
- `s`
  - ECDSA署名の`s`値。

---

#### presignedSetAddressAttribute

```javascript
function presignedSetAddressAttribute(
    address setter,
    address collection,
    uint256 tokenId,
    string memory key,
    address value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```

**概要**

承認されたアカウントを代表してアドレス属性を設定する関数。

**詳細**

特定のアカウントが事前に署名したメッセージを使用してアドレス属性を設定します。
これにより、他のアカウントが設定する前に属性の変更を承認することができます。
属性が設定されると、`AddressAttributeUpdated`イベントが発行されます。

**引数**

- `setter`
  - 属性変更を事前に署名したアカウントのアドレス。
- `collection`
  - 属性を設定するコレクションのアドレス。
- `tokenId`
  - 属性を設定するトークンのID。
- `key`
  - 属性のキー。
  - 属性を一意に識別するための文字列です。
- `value`
  - 属性の値として設定するアドレス。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。
  - このタイムスタンプまでにトランザクションを実行する必要があります。
- `v`
  - ECDSA署名の`v`値。
- `r`
  - ECDSA署名の`r`値。
- `s`
  - ECDSA署名の`s`値。

---

#### isCollaborator

```javascript
function isCollaborator(
    address collaborator,
    address collection
) external view returns (bool);
```

**概要**
指定されたアドレスが指定されたコレクションの共同作業者としてリストされているか確認する関数。

**詳細**

指定されたアドレスが特定のコレクションの共同作業者であるかどうかを確認するために使用されます。
共同作業者としてリストされたアドレスは、特定のアクションや権限を持つ場合があります。
共同作業者である場合は`true`を、それ以外の場合は`false`を返します。


**引数**

- `collaborator`
  - 確認するアドレス。
- `collection`
  - コレクションのアドレス。

**戻り値**

- `true`
    - 指定されたアドレスがコレクションの共同作業者である場合。
- `false`
    - 指定されたアドレスがコレクションの共同作業者でない場合。

---

#### isSpecificAddress

```javascript
function isSpecificAddress(
    address specificAddress,
    address collection,
    string memory key
) external view returns (bool);
```

**概要**

指定されたアドレスが指定されたコレクションの特定のアドレスとしてリストされているか確認する関数。

**詳細**

指定されたアドレスが特定のコレクションの特定のアドレスであるかどうかを確認するために使用されます。
特定のアドレスとしてリストされたアドレスは、特別な権限や属性を持つ場合があります。
特定のアドレスである場合は`true`を、それ以外の場合は`false`を返します。

**引数**

- `specificAddress`
  - 確認するアドレス。
- `collection`
  - コレクションのアドレス。
- `key`
  - 属性のキー。
  - 特定のアドレスを一意に識別するための文字列です。

**戻り値**

- `true`
    - 指定されたアドレスがコレクションの特定のアドレスである場合。
- `false`
    - 指定されたアドレスがコレクションの特定のアドレスでない場合。

---

#### getStringTokenAttribute

```javascript
function getStringTokenAttribute(
    address collection,
    uint256 tokenId,
    string memory key
) external view returns (string memory);
```

**概要**

指定されたコレクションとトークンのIDに関連付けられた文字列型のトークン属性を取得する関数。

**詳細**

指定されたコレクションとトークンのID、および属性のキーを使用して、トークンの文字列属性の値を取得します。
これにより、トークンに関する追加情報を取得できます。

**引数**

- `collection`
  - コレクションのアドレス。
- `tokenId`
  - トークンのID。
- `key`
  - 属性のキー。
  - 取得したい属性を一意に識別するための文字列です。

**戻り値**

- 文字列属性の値。

---

#### getUintTokenAttribute

```javascript
function getUintTokenAttribute(
    address collection,
    uint256 tokenId,
    string memory key
) external view returns (uint256);
```

**概要**

指定されたコレクションとトークンのIDに関連付けられた整数型のトークン属性を取得する関数。

**詳細**

指定されたコレクションとトークンのID、および属性のキーを使用して、トークンの整数属性の値を取得します。
これにより、トークンに関する追加情報を取得できます。

**引数**

- `collection`
  - コレクションのアドレス。
- `tokenId`
  - トークンのID。
- `key`
  - 属性のキー。
  - 取得したい属性を一意に識別するための文字列です。

**戻り値**

- 整数属性の値。

---

Sure, I'll provide explanations for the remaining functions in the requested format.

#### `getBoolTokenAttribute`

```javascript
/**
 * @notice ブール型のトークン属性を取得します。
 * @param collection コレクションのアドレス
 * @param tokenId トークンのID
 * @param key 属性のキー
 * @return ブール属性の値
 */
function getBoolTokenAttribute(
    address collection,
    uint256 tokenId,
    string memory key
) external view returns (bool);
```

**概要**

この関数は、指定されたコレクションとトークンのIDに関連付けられたブール型のトークン属性を取得します。

**詳細**

この関数は、指定されたコレクションとトークンのID、および属性のキーを使用して、トークンのブール属性の値を取得します。ブール属性は `true` または `false` の値を持ち、トークンの特定の状態やフラグを示すのに使用されます。

**引数**

- `collection`
  - コレクションのアドレス。
- `tokenId`
  - トークンのID。
- `key`
  - 属性のキー。取得したい属性を一意に識別するための文字列です。

**戻り値**

- ブール属性の値 (`true` または `false`)。

---

#### `getAddressTokenAttribute`

```javascript
/**
 * @notice アドレス型のトークン属性を取得します。
 * @param collection コレクションのアドレス
 * @param tokenId トークンのID
 * @param key 属性のキー
 * @return アドレス属性の値
 */
function getAddressTokenAttribute(
    address collection,
    uint256 tokenId,
    string memory key
) external view returns (address);
```

**概要**

この関数は、指定されたコレクションとトークンのIDに関連付けられたアドレス型のトークン属性を取得します。

**詳細**

この関数は、指定されたコレクションとトークンのID、および属性のキーを使用して、トークンのアドレス属性の値を取得します。アドレス属性は Ethereum アドレスを格納するのに使用され、トークンが他のコントラクトやユーザーアカウントとの関連付けを持つ場合に有用です。

**引数**

- `collection`
  - コレクションのアドレス。
- `tokenId`
  - トークンのID。
- `key`
  - 属性のキー。取得したい属性を一意に識別するための文字列です。

**戻り値**

- アドレス属性の値 (Ethereum アドレス)。

---

#### getBytesTokenAttribute

```javascript
function getBytesTokenAttribute(
    address collection,
    uint256 tokenId,
    string memory key
) external view returns (bytes memory);
```

**概要**

指定されたコレクションとトークンのIDに関連付けられたバイト型のトークン属性を取得する関数。

**詳細**

指定されたコレクションとトークンのID、および属性のキーを使用して、トークンのバイト属性の値を取得します。
バイト属性はバイナリデータを格納するのに使用され、トークンが複雑なデータ構造を持つ場合に有用です。

**引数**

- `collection`
  - コレクションのアドレス。
- `tokenId`
  - トークンのID。
- `key`
  - 属性のキー。
  - 取得したい属性を一意に識別するための文字列です。

**戻り値**

- バイト属性の値。

---

#### prepareMessageToPresignUintAttribute

```javascript
function prepareMessageToPresignUintAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    uint256 value,
    uint256 deadline
) external view returns (bytes32);
```

**概要**

承認されたアカウントによる事前署名された`uint`属性の変更を提出するために使用されるメッセージを取得する関数。

**詳細**

承認されたアカウントによって提出される`uint`属性変更の署名メッセージを生成します。
メッセージは、変更内容やトランザクションの有効期限などの情報を含み、署名されたメッセージは属性変更トランザクションの提出に使用されます。

**引数**

- `collection`
  - 属性を受け取るトークンのコレクションスマートコントラクトのアドレス。
- `tokenId`
  - 属性を受け取るトークンのID。
- `key`
  - 属性のキー。
  - 変更したい属性を一意に識別するための文字列です。
- `value`
  - 属性の新しい値 (`uint`型)。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。
  - このタイムスタンプを過ぎるとメッセージは無効になります。

**戻り値**

- 承認されたアカウントによって署名される生のメッセージ (`bytes32`)。

---

#### prepareMessageToPresignStringAttribute

```javascript
function prepareMessageToPresignStringAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    string memory value,
    uint256 deadline
) external view returns (bytes32);
```

**概要**

承認されたアカウントによる事前署名された文字列属性の変更を提出するために使用されるメッセージを取得する関数。

**詳細**

承認されたアカウントによって提出される文字列属性変更の署名メッセージを生成します。
メッセージは、変更内容やトランザクションの有効期限などの情報を含み、署名されたメッセージは属性変更トランザクションの提出に使用されます。

**引数**

- `collection`
  - 属性を受け取るトークンのコレクションスマートコントラクトのアドレス。
- `tokenId`
  - 属性を受け取るトークンのID。
- `key`
  - 属性のキー。
  - 変更したい属性を一意に識別するための文字列です。
- `value`
  - 属性の新しい値 (文字列)。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。このタイムスタンプを過ぎるとメッセージは無効になります。

**戻り値**

- 承認されたアカウントによって署名される生のメッセージ (`bytes32`)。

---

#### prepareMessageToPresignBoolAttribute

```javascript
function prepareMessageToPresignBoolAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    bool value,
    uint256 deadline
) external view returns (bytes32);
```

**概要**

承認されたアカウントによる事前署名されたブール属性の変更を提出するために使用されるメッセージを取得する関数。

**詳細**

承認されたアカウントによって提出されるブール属性変更の署名メッセージを生成します。
メッセージは、変更内容やトランザクションの有効期限などの情報を含み、署名されたメッセージは属性変更トランザクションの提出に使用されます。

**引数**

- `collection`
  - 属性を受け取るトークンのコレクションスマートコントラクトのアドレス。
- `tokenId`
  - 属性を受け取るトークンのID。
- `key`
  - 属性のキー。変更したい属性を一意に識別するための文字列です。
- `value`
  - 属性の新しい値 (ブール型)。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。このタイムスタンプを過ぎるとメッセージは無効になります。

**戻り値**

- 承認されたアカウントによって署名される生のメッセージ (`bytes32`)。

---

#### prepareMessageToPresignBytesAttribute

```javascript
function prepareMessageToPresignBytesAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    bytes memory value,
    uint256 deadline
) external view returns (bytes32);
```

**概要**

承認されたアカウントによる事前署名されたバイト属性の変更を提出するために使用されるメッセージを取得する関数。

**詳細**

承認されたアカウントによって提出されるバイト属性変更の署名メッセージを生成します。
メッセージは、変更内容やトランザクションの有効期限などの情報を含み、署名されたメッセージは属性変更トランザクションの提出に使用されます。

**引数**

- `collection`
  - 属性を受け取るトークンのコレクションスマートコントラクトのアドレス。
- `tokenId`
  - 属性を受け取るトークンのID。
- `key`
  - 属性のキー。変更したい属性を一意に識別するための文字列です。
- `value`
  - 属性の新しい値 (バイト配列)。
- `deadline`
  - 承認トランザクションの締め切りタイムスタンプ。このタイムスタンプを過ぎるとメッセージは無効になります。

**戻り値**

- 承認されたアカウントによって署名される生のメッセージ (`bytes32`)。

---


#### prepareMessageToPresignAddressAttribute

```javascript
function prepareMessageToPresignAddressAttribute(
    address collection,
    uint256 tokenId,
    string memory key,
    address value,
    uint256 deadline
) external view returns (bytes32);
```

**概要**
事前に署名されたアドレス属性変更のメッセージを取得する関数。

**詳細**
指定されたコレクションのトークンに対してアドレス属性を変更するための事前署名メッセージを生成します。
メッセージは指定されたコレクション、トークンID、属性キー、属性値、および期限の情報を含みます。
これは、属性変更トランザクションが安全に署名され、送信されるのに役立ちます。

**引数**
- `collection`
  - アトリビュートを受け取るトークンのコレクションスマートコントラクトのアドレス。
- `tokenId`
  - アトリビュートを受け取るトークンのID。
- `key`
  - アトリビュートのキー。
- `value`
  - アトリビュートの値。
- `deadline`
  - 事前署名されたトランザクションの期限タイムスタンプ。
  - 期限後にメッセージは無効になります。

**戻り値**
- `bytes32`
  - 承認されたアカウントによって署名される生のメッセージ。
  - このメッセージは事前署名されたトランザクションに使用されます。

---

#### getTokenAttributes

```javascript
function getTokenAttributes(
    address collection,
    uint256 tokenId,
    string[] memory stringKeys,
    string[] memory uintKeys,
    string[] memory boolKeys,
    string[] memory addressKeys,
    string[] memory bytesKeys
) external view returns (
        StringAttribute[] memory stringAttributes,
        UintAttribute[] memory uintAttributes,
        BoolAttribute[] memory boolAttributes,
        AddressAttribute[] memory addressAttributes,
        BytesAttribute[] memory bytesAttributes
    );
```

**概要**
任意の種類の複数のトークン属性を一度に取得する関数。

**詳細**
指定されたコレクションとトークンIDに関連付けられた、異なる種類の属性（`string`、`uint`、`bool`、`address`、`bytes`）を一括して取得します。
指定された属性キーのリストに基づいて、それぞれの属性の値を返します。
これは、トークンに関連する複数の属性情報を効率的に取得するために使用されます。

**引数**
- `collection`
  - コレクションのアドレス。
- `tokenId`
  - トークンID。
- `stringKeys`
  - 取得する文字列型属性キーの配列。
- `uintKeys`
  - 取得するuint型属性キーの配列。
- `boolKeys`
  - 取得するbool型属性キーの配列。
- `addressKeys`
  - 取得するaddress型属性キーの配列。
- `bytesKeys`
  - 取得するbytes型属性キーの配列。

**戻り値**
- `stringAttributes`
  - 文字列型属性を含む`StringAttribute`構造体の配列。
- `uintAttributes`
  - uint型属性を含む`UintAttribute`構造体の配列。
- `boolAttributes`
  - bool型属性を含む`BoolAttribute`構造体の配列。
- `addressAttributes`
  - address型属性を含む`AddressAttribute`構造体の配列。
- `bytesAttributes`
  - bytes型属性を含む`BytesAttribute`構造体の配列。

---

#### getStringTokenAttributes

```javascript
function getStringTokenAttributes(
    address collection,
    uint256 tokenId,
    string[] memory stringKeys
) external view returns (StringAttribute[] memory);
```

**概要**
トークンの複数の文字列型パラメータ値を取得する関数。

**詳細**
指定されたコレクションとトークンIDに関連付けられた、指定された文字列型キーのパラメータ値を取得します。
各文字列型パラメータはキーと値のペアで表され、それらのペアは`StringAttribute`構造体の要素として返されます。
これにより、トークンの文字列型属性情報を簡単に取得できます。

**引数**
- `collection`
  - トークンが所属するコレクションのアドレス。
- `tokenId`
  - 属性を取得するトークンのID。
- `stringKeys`
  - 取得する文字列型キーの配列。

**戻り値**
- `StringAttribute[]`
  - `StringAttribute`構造体の配列。
  - 各構造体は文字列型パラメータのキーと値を含んでいます。

---

#### getUintTokenAttributes

```javascript
function getUintTokenAttributes(
    address collection,
    uint256 tokenId,
    string[] memory uintKeys
) external view returns (UintAttribute[] memory);
```

**概要**
トークンの複数の`uint`型パラメータ値を取得する関数。

**詳細**
指定されたコレクションとトークンIDに関連付けられた、指定された`uint`型キーのパラメータ値を取得します。
各`uint`型パラメータはキーと値のペアで表され、それらのペアは`UintAttribute`構造体の要素として返されます。
これにより、トークンの`uint`型属性情報を簡単に取得できます。

**引数**
- `collection`
  - トークンが所属するコレクションのアドレス。
- `tokenId`
  - 属性を取得するトークンのID。
- `uintKeys`
  - 取得する`uint`型キーの配列。

**戻り値**
- `UintAttribute[]`
  - `UintAttribute`構造体の配列。
  - 各構造体は`uint`型パラメータのキーと値を含んでいます。

---

#### getBoolTokenAttributes

```javascript
function getBoolTokenAttributes(
    address collection,
    uint256 tokenId,
    string[] memory boolKeys
) external view returns (BoolAttribute[] memory);
```

**概要**
トークンの複数の`bool`型パラメータ値を取得する関数。

**詳細**
指定されたコレクションとトークンIDに関連付けられた、指定された`bool`型キーのパラメータ値を取得します。
各`bool`型パラメータはキーと値のペアで表され、それらのペアは`BoolAttribute`構造体の要素として返されます。
これにより、トークンの`bool`型属性情報を簡単に取得できます。

**引数**
- `collection`
  - トークンが所属するコレクションのアドレス。
- `tokenId`
  - 属性を取得するトークンのID。
- `boolKeys`
  - 取得する`bool`型キーの配列。

**戻り値**
- `BoolAttribute[]`
  - `BoolAttribute`構造体の配列。
  - 各構造体は`bool`型パラメータのキーと値を含んでいます。

---

#### getAddressTokenAttributes

```javascript
function getAddressTokenAttributes(
    address collection,
    uint256 tokenId,
    string[] memory addressKeys
) external view returns (AddressAttribute[] memory);
```

**概要**
トークンの複数の`address`型パラメータ値を取得するために使用されます。

**詳細**
指定されたコレクションとトークンIDに関連付けられた、指定された`address`型キーのパラメータ値を取得します。
各`address`型パラメータはキーと値のペアで表され、それらのペアは`AddressAttribute`構造体の要素として返されます。
これにより、トークンの`address`型属性情報を簡単に取得できます。

**引数**
- `collection`
  - トークンが所属するコレクションのアドレス。
- `tokenId`
  - 属性を取得するトークンのID。
- `addressKeys`
  - 取得する`address`型キーの配列。

**戻り値**
- `AddressAttribute[]`
  - `AddressAttribute`構造体の配列。
  - 各構造体は`address`型パラメータのキーと値を含んでいます。

---

#### getBytesTokenAttributes

```javascript
function getBytesTokenAttributes(
    address collection,
    uint256 tokenId,
    string[] memory bytesKeys
) external view returns (BytesAttribute[] memory);
```

**概要**
トークンの複数のbytes型パラメータ値を取得する関数。

**詳細**
指定されたコレクションとトークンIDに関連付けられた、指定された`bytes`型キーのパラメータ値を取得します。
各`bytes`型パラメータはキーと値のペアで表され、それらのペアは`BytesAttribute`構造体の要素として返されます。
これにより、トークンの`bytes`型属性情報を簡単に取得できます。

**引数**
- `collection`
  - トークンが所属するコレクションのアドレス。
- `tokenId`
  - 属性を取得するトークンのID。
- `bytesKeys`
  - 取得する`bytes`型キーの配列。

**戻り値**
- `BytesAttribute[]`
  - `BytesAttribute`構造体の配列。
  - 各構造体は`bytes`型パラメータのキーと値を含んでいます。

---

### 署名付き属性のメッセージフォーマット

以下のメッセージは、属性を設定する権限を持つ「**setter**」（設定者）が使用する署名のフォーマットです。
このメッセージはセキュリティを確保するために使用され、以下の要素から構成されています。

```javascript
keccak256(
    abi.encode(
        DOMAIN_SEPARATOR,
        METHOD_TYPEHASH,
        collection,
        tokenId,
        key,
        value,
        deadline
    )
);
```

- `keccak256`
    - ハッシュ関数で、メッセージを固定長のハッシュ値に変換します。
    - これはセキュリティ目的で使用され、メッセージが改ざんされていないことを確認します。
- `abi.encode`
    - データをエンコード（変換）するための関数。
    - 指定したデータをバイト列に変換します。
- `DOMAIN_SEPARATOR`
    - 属性リポジトリスマートコントラクトのドメインセパレータ。
    - 属性設定トランザクションの発信元を識別するための一意の値です。
    - この値はスマートコントラクトごとに異なります。
- `METHOD_TYPEHASH`
    - メソッドのタイプハッシュと呼ばれる値で、特定のメソッド（属性の設定など）を一意に識別します。
    - この値もメソッドごとに異なります。
    - - `SET_UINT_ATTRIBUTE_TYPEHASH`
        - uint属性を設定する場合に使用されるタイプハッシュ。
    - `SET_STRING_ATTRIBUTE_TYPEHASH`
        - 文字列属性を設定する場合に使用されるタイプハッシュ。
    - `SET_BOOL_ATTRIBUTE_TYPEHASH`
        - ブール属性を設定する場合に使用されるタイプハッシュ。
    - `SET_BYTES_ATTRIBUTE_TYPEHASH`
        - バイト属性を設定する場合に使用されるタイプハッシュ。
    - `SET_ADDRESS_ATTRIBUTE_TYPEHASH`
        - アドレス属性を設定する場合に使用されるタイプハッシュ。
- `collection`
    - 属性を設定するトークンが所属するコレクションのアドレス。
- `tokenId`
    - 属性を設定するトークンの一意の識別子（ID）。
- `key`
    - 属性のキー。
    - 属性を一意に識別するための名前またはラベルです。
- `value`
    - 属性の値。
    - 属性の種類に応じて、uint、文字列、ブール、バイト、アドレスのいずれかの適切なデータ型である必要があります。
- `deadline`
    - 署名が提出される期限のUNIXタイムスタンプ。
    - この期限を過ぎた署名は無効になります。

:::message
この情報を`abi.encode`を使用してバイト列にエンコードし、`keccak256`を適用してハッシュ値を生成します。
このハッシュ値は、署名付きトランザクションと共に提出され、属性の設定を確認および認証するために使用されます。
このプロセスは、セキュアな属性変更を確保するために重要です。
:::

`DOMAIN_SEPARATOR`は以下のように生成されます。

```javascript
keccak256(
    abi.encode(
        "ERC-7508: Public Non-Fungible Token Attributes Repository",
        "1",
        block.chainid,
        address(this)
    )
);
```

`SET_UINT_ATTRIBUTE_TYPEHASH`は以下のように生成されます。

```javascript
keccak256(
    "setUintAttribute(address collection,uint256 tokenId,string memory key,uint256 value)"
);
```

`SET_STRING_ATTRIBUTE_TYPEHASH`は以下のように生成されます。

```javascript
keccak256(
    "setStringAttribute(address collection,uint256 tokenId,string memory key,string memory value)"
);
```

`SET_BOOL_ATTRIBUTE_TYPEHASH`は以下のように生成されます。

```javascript
keccak256(
    "setBoolAttribute(address collection,uint256 tokenId,string memory key,bool value)"
);
```

`SET_BYTES_ATTRIBUTE_TYPEHASH`は以下のように生成されます。

```javascript
keccak256(
    "setBytesAttribute(address collection,uint256 tokenId,string memory key,bytes memory value)"
);
```

`SET_ADDRESS_ATTRIBUTE_TYPEHASH`は以下のように生成されます。

```javascript
keccak256(
    "setAddressAttribute(address collection,uint256 tokenId,string memory key,address value)"
);
```

Attributesリポジトリ・スマートコントラクトがデプロイされる各チェーンは、チェーンIDが異なるため、異なる`DOMAIN_SEPARATOR`値を持つことになります。

### Attributes repository（属性リポジトリ）の事前設定されたアドレス

このアドレスは、`0xA77B75`で始まり、この「`0xA77B75`」は「**ATTBTS**」の抽象的な表現です。
具体的なアドレスは「`0xA77b75D5fDEC6E6e8E00e05c707a7CA81a3F9f4a`」です。

このアドレスの設計には意味があります。
アドレスの最初の文字列「`0xA77B75`」は、「**ATTBTS**」という概念や名前を表現しています。
このようなアドレス設計は、スマートコントラクトが何に関連しているのかを簡単に理解できるようにするために役立ちます。
特に、ブロックチェーン上で複数のスマートコントラクトが活動している場合、スマートコントラクトがどの機能や目的に関連しているかを識別するのに役立ちます。

このアドレス設計により、Emotableリポジトリスマートコントラクトが属性に関する情報を格納し、提供する役割を視覚的に理解しやすくなります。
ブロックチェーン上でのスマートコントラクトの使途や目的を説明するための効果的な手段となっています。

## 補足

### プロパティと属性の用語の使用
トークンに関連する特性や特徴をどのように表現するべきか検討しました。
歴史的には「**プロパティ**」という用語が一般的でしたが、より一般的な「**属性**」という用語を採用することにしました。
これは、属性が何か/誰かの品質や特徴を指す用語であり、より広範な文脈で適切であると判断したためです。

### アクセス制御の有無
提案にアクセス制御のルールを明示するべきかどうかを検討しました。
アクセス制御を含めることで、実装者が属性リポジトリを使用する前に設定する必要があります。
一方、アクセス制御を実装者に任せることで、柔軟性が高まりますが、実装者が独自にアクセス制御を設計する必要があります。
提案にアクセス制御を含めることで、既存のコレクションとの後方互換性が確保される利点もあります。

### 属性拡張か共通リポジトリか
最初には**ERC721**トークン向けの属性拡張を検討しましたが、より広範な利用を可能にするために共通の属性リポジトリとすることにしました。
これにより、提案以前から存在するトークンも新しいトークンもリポジトリを利用できるようになり、**ERC1155**トークンとの互換性も確保できます。

### 単一アクションと複数アクション
属性の割り当て操作について、単一のトークンに単一の属性を割り当てる単一アクションと、複数のトークンに同時に属性を割り当てる複数アクションのどちらを含めるべきかを検討しました。
最終的には両方を含めることにし、ユーザーに選択肢を提供しました。

### 他のユーザーの代理で属性を割り当てる機能
提案初期では考慮されていなかったが、後に有用性が認識されました。
この機能により、ユーザーは他のユーザーの代わりに属性を割り当てることができます。
また、属性の代理割り当てが不正でないことを確認するためにECDSA署名を導入することが提案されました。

### 属性のチェーンIDパラメータ
トークンに属性を割り当てる時に、チェーンIDをパラメータとして含めるべきかどうかを検討しました。
最終的には採用しないことにしました。
理由として、チェーンIDパラメータはほとんど使用されず、属性の割り当てトランザクションのコストを増加させるだけであり、コレクションスマートコントラクトや市場プレイスが同じチェーン上に属性を期待しているためです。

### 文字列の使用コスト削減
文字列の使用コストが高いことが問題となりました。
この問題を解決するため、文字列の代わりに文字列のインデックスを使用するアプローチが採用されました。
これにより、新しい文字列を設定する時のコストは最初のユーザーだけが支払い、他のユーザーは文字列のインデックスの設定コストのみを支払います。
また、このアプローチはリポジトリ全体に適用され、同じ文字列を使用する他のコレクションは文字列を再設定する必要がありません。

## 後方互換性

Attributes repository（属性リポジトリ）の標準仕様は、**ERC721**および**ERC1155**と完全に互換性があります。
これは、Attributes repositoryがこれらのトークン規格とシームレスに連携でき、既存の**ERC721**トークンインフラストラクチャとも問題なく動作することを意味しています。

:::message
Attributes repositoryは**ERC721**と**ERC1155**で使用されるトークンと属性に関する情報を効率的に管理できます。
これにより、トークンの属性を追加、変更、クエリするためのツールやプロセスがスムーズに統合できます。
また、既存の**ERC721**インフラストラクチャやツールとも互換性があるため、既存のトークンシステムにAttributes repositoryを導入しやすく、既存のトークンにも新しい属性を追加できます。
:::

## テスト

以下のGithubに格納しています。

https://github.com/cardene777/base-code/blob/develop/contract/test/ERC7508/attributesRepository.ts

引用: https://eips.ethereum.org/EIPS/eip-7508

## 参考実装

以下のGithubに格納しています。

https://github.com/cardene777/base-code/tree/develop/contract/contracts/ERC7508

引用: https://eips.ethereum.org/EIPS/eip-7508

## セキュリティ考慮事項

この提案は、ユーザーからの任意の形式のアセットを管理または処理することを意図しておらず、Attributes repository（属性リポジトリ）とやり取りする時にユーザーのアセットが危険にさらされることはありません。

提案に含まれるECDSA署名を使用して、他のユーザーの代わりに属性を設定する機能は、リプレイ攻撃というセキュリティリスクを持ち込む可能性があります。
ただし、この提案ではメッセージの署名対象となるフォーマットが設計されており、それによってリプレイ攻撃を防ぎます。具体的には、署名するメッセージ内で使用される`DOMAIN_SEPARATOR`（ドメインセパレータ）は、それが展開されているブロックチェーン上のリポジトリスマートコントラクトに固有です。
これは、署名が別のブロックチェーン上では無効であり、他のチェーンに展開された属性リポジトリは、リプレイ攻撃が試みられた場合に操作を拒否するべきです。

さらに、事前署名されたメッセージの再利用についても考慮すべきです。
メッセージには署名の有効期限が含まれており、その有効期限が切れるまで、何度でも同じメッセージを再利用できます。
ただし、この提案では特定のキーに対して単一の値しか設定できない制限があるため、事前署名されたメッセージを使用して属性値をさらに変更することはできません。
ただし、このリポジトリを使用するサービスが、特定のアクションの後で属性を取り消したり変更したりする機能に依存している場合、有効な事前署名されたメッセージを使用してトークンの属性を再設定できます。
この時、提案では事前署名されたメッセージの有効期限を比較的短い期間で無効にすることを提案しています。

非監査のスマートコントラクトを扱う場合には注意が必要です。
セキュリティが確保されていないスマートコントラクトは潜在的なリスクを伴う可能性があり、慎重に対処する必要があります。

## 引用

Steven Pineda (@steven2308), Jan Turk (@ThunderDeliverer), "ERC-7508: Dynamic On-Chain Token Attributes Repository [DRAFT]," Ethereum Improvement Proposals, no. 7508, August 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7508.

## 最後に

今回は「NFTにさまざまな属性情報を持たせて管理する仕組みを提案している**ERC7508**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58
