[ERC5334] ERC721形式のNFTにアドレス・有効期限・レベルという情報を付与できる仕組みを理解しよう！

# はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、アドレスと有効期限、レベルを指定することで、様々な用途に使用できる設定をNFTに付与することができる仕組みを提案している**ERC5334**についてまとめていきます！

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

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

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

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

# 概要

**ERC5334**は、**ERC721**に、新しく「`user`」というロールを追加する提案です。
このユーザーはNFTの所有者とは別のアドレスに設定でき、NFTを使用することはできますが、`transfer`したり他のアドレスを`user`に設定したりする権限は持ちません。

また、このユーザー権限には「有効期限（`expires`）」と「レベル（`level`）」が設定できます。
有効期限が切れたら自動的に権限が無効になる仕組みです。
これにより、NFTの一時的なレンタルなどに対応しやすくなります。

# 動機

## NFTの使い道は所有だけじゃない

NFTは単に持っているだけのものではなく、ゲームアイテムやメタバース上の土地など、「使う」ことに意味があるケースが増えています。
しかし、こういったユースケースでは、所有者がNFTを他人に使わせる場面も出てきます。

例えば、土地NFTの所有者が誰かに土地を貸して建物を建てさせたい場合、所有権は移したくないが使用する権限は与えたい、という状況です。
このようなとき、所有者と利用者のロールを分けられる仕組みがあると便利です。

## 無駄なトランザクションを減らせる

従来のやり方では、NFTを誰かに一時的に使わせるには以下の2つのトランザクションが必要でした。

- 利用を開始するとき → 利用者を登録
- 利用期間が終わったとき → 利用者を解除

この手順では手間もガス代も無駄に発生します。
**ERC5334**では、あらかじめ有効期限を指定しておけるため、期間が終われば自動的にそのアドレスは使えなくなります。
また、解除のための追加トランザクションは不要です。

## 他のプロジェクトとも連携しやすくなる

`user`ロールと「**有効期限**」と「**レベル**」の仕様が標準化されることで、他のプロジェクトでも共通のインターフェースとして扱えるようになります。
つまり、NFT発行元に特別な対応をしてもらわずに、レンタルプラットフォームや分割購入サービスなどがNFTを取り扱えるようになります。

例えば、あるPFP（プロフィール画像）NFTを30日間レンタルできるサービスと、NFTを分割で購入しながら使えるモーゲージサービスの両方に同時に対応させることも可能です。

# 仕様

**ERC5334**は、NFTに対して「`user`」「利用期限（`expires`）」「利用レベル（`level`）」の3つの情報を管理できるようにするインターフェースです。

## インターフェース

```js
interface IERC5334 {

    // Logged when the user of a NFT, expires, or level is changed
    /// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed or the user `level` is changed
    /// The zero address for user indicates that there is no user address
    event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires, uint8 level);

    /// @notice set the user and expires and level of a NFT
    /// @dev The zero address indicates there is no user
    /// Throws if `tokenId` is not valid NFT
    /// @param user  The new user of the NFT
    /// @param expires  UNIX timestamp, The new user could use the NFT before expires
    /// @param level user level
    function setUser(uint256 tokenId, address user, uint64 expires, uint8 level) external;

    /// @notice Get the user address of an NFT
    /// @dev The zero address indicates that there is no user or the user is expired
    /// @param tokenId The NFT to get the user address for
    /// @return The user address for this NFT
    function userOf(uint256 tokenId) external view returns(address);

    /// @notice Get the user expires of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user expires for
    /// @return The user expires for this NFT
    function userExpires(uint256 tokenId) external view returns(uint256);

    /// @notice Get the user level of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user level for
    /// @return The user level for this NFT
    function userLevel(uint256 tokenId) external view returns(uint256);
}
```


## イベント

### `UpdateUser`

```js
event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires, uint8 level);
```

NFTに設定されている`user`、利用期限、またはレベルが変更されたときに発行されるイベント。  
ユーザーが設定されていない場合は `address(0)` が使われます。

このイベントは、`setUser()`が実行されたときに必ず発行する必要があります。

## 関数

### `setUser`

```js
function setUser(uint256 tokenId, address user, uint64 expires, uint8 level) external;
```

NFTに対して、新しいユーザーを設定する関数。  

- `user`
    - NFTの使用者アドレス。
    - 空アドレス（`address(0)`）を渡すと設定されているユーザーは無しになります。  
- `expires`
    - UNIXタイムスタンプ。
    - 指定時刻までユーザーとして利用できます。  
- `level`
    - ユーザーレベル。
    - アプリによって意味づけが異なる可能性があります。

### `userOf`

```js
function userOf(uint256 tokenId) external view returns(address);
```

対象のNFTに現在設定されているユーザーを返す関数。  
ユーザーがいない、もしくは有効期限切れの場合は `address(0)` が返ってきます。  

### `userExpires`

```js
function userExpires(uint256 tokenId) external view returns(uint256);
```

対象NFTのユーザーがいつまで使用できるか（UNIXタイム）を返す関数。  
値が `0` の場合は、ユーザーがいないことを意味します。  

### `userLevel`

```js
function userLevel(uint256 tokenId) external view returns(uint256);
```

対象NFTに設定された「ユーザーレベル」を返す関数。  
このレベルの使い方はアプリケーション次第ですが、レアリティや機能制限などに応用できます。  

## 準拠するべきこと

- `setUser()` でユーザー情報が変更された場合、必ず `UpdateUser` イベントを発行させる。

# 互換性

**ERC5334**は、**ERC721**の機能を拡張するだけなので、**ERC721**と完全に互換性があります。

# セキュリティ

**ERC5334**は、NFTの所有者の権利を完全に保護することができ、所有者はいつでもレンタルする`user`と有効期限、レベルを変更することができます。

# 引用

Yan (@yan253319066), "ERC-5334: EIP-721 User And Expires And Level Extension [DRAFT]," Ethereum Improvement Proposals, no. 5334, July 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5334.

# 最後に

今回は「アドレスと有効期限、レベルを指定することで、様々な用途に使用できる設定をNFTに付与することができる仕組みを提案している**ERC5334**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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