NFTを他の人に使わせる！　Ethereumの改善提案による ERC4907について

# はじめに

こんにちは〜！
ぐるーんです。最近はNFTが普通の人にも認知されてきましたね。今は様々なNFTプロジェクトが誕生しています。NFTを愛する者としては嬉しい限りです。

さて、最近、NFTを他の人に利用させる規格の作成を目指したEIP-4907が承認されましたね。
https://eips.ethereum.org/EIPS/eip-4907

普通はNFTを他の人に貸したりしないので、他の人に利用させるNFTというのは面白いです。
また、これはNFTの貸し出しプラットフォームの話ではなく、NFTそれ自体に、NFTの利用機能をビルトインさせようとしているのが面白いです。

これらの機能は、NFTの技術を考える上でも、NFTの性質を考える上でも非常に興味深いです。

今回はこれについての記事を書こうと思います。

まずは、純粋にERC4907がどういう仕組みなのか簡単に説明します。
その後、どういう使い方や影響があり得るのかについて考えていきます。


# ERC4907について
EIP4907は、ERC4907を作成するためのものです。ERC721のように共通規格を作ろうということですね。
ERC4907は、基本的にはERC721をベースにしたNFTの規格になっています。基本部分について、ERC721の機能が備わっているNFTということになります。

ERC4907では、ERC721をベースに、主として以下2つの機能を追加しています。
・NFTごとに「**user**」を設定し、参照する機能
・NFTごとに「**expires**」を設定し、参照する機能

「**user**」とは、NFTの利用者となるアドレスを想定しています。また、「**expires**」はNFTの利用期限を想定しています。

これらのパラメータを設定し、参照するのがERC4907ということです。ERC4907の最大公約数的な機能はこれだけです。

逆に言えば、これら以外の機能は自由にアレンジ可能であり、安易にERC4907＝利用機能が追加されただけのNFTと考えてはいけません。他のNFTと同様にwallet内の仮想通貨を盗むNFTをERC4907ベースに作ることは可能なので注意しましょう。

公式では、ベースとなるERC4907が紹介されているので、以下、公式ERC4907の細かい内容について見ていきましょう。

## 「**user**」と「**expires**」を設定する
```solidity
struct UserInfo 
    {
        address user;   // address of user role
        uint64 expires; // unix timestamp, user expires
    }

function setUser(uint256 tokenId, address user, uint64 expires) public virtual{
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC4907: transfer caller is not owner nor approved");
        UserInfo storage info =  _users[tokenId];
        info.user = user;
        info.expires = expires;
        emit UpdateUser(tokenId, user, expires);
    }
```
上記のsetUserのfunctionによって、「**user**」と「**expires**」をNFTごとに設定することができます。
「**user**」はNFTの利用者あるいはコントラクトのアドレスを想定しています。
「**expires**」は、利用期限を想定しています。UNIX標準時から数えた秒数で表します。
これは、基本的にはNFTを持っている人（「**owner**」）が「**user**」と「**expires**」を設定する権限を持っています。公式のERC4907では、approveによって「**user**」と「**expires**」の設定権限を第三者に付与できる仕組みになっているので、やや注意が必要です。
また、「**owner**」及びapproveされた者は、いつでも一方的に「**user**」と「**expires**」を変更できることに注意が必要です。

## 「**user**」を参照する

```solidity
function userOf(uint256 tokenId) public view virtual returns(address){
        if( uint256(_users[tokenId].expires) >=  block.timestamp){
            return  _users[tokenId].user;
        }
        else{
            return address(0);
        }
    }
```
userOfのfunctionによって、「**user**」のアドレスを誰でも参照できます。ただし、公式のERC4907では、利用期限としての「**expires**」が経過してしまうと、このfunctionによって、「**user**」のアドレスを参照することはできません。UserInfoのStructの中には、「**user**」が変更されていなければ、期限の経過後も従前の「**user**」のアドレスが残っているので、その点は各々の設計において何か使い道があるかもしれません。


## 「**expires**」を参照する
```solidity
function userExpires(uint256 tokenId) public view virtual returns(uint256){
        return _users[tokenId].expires;
    }
```
userExpiresのfunctionによって、「**expires**」の数値を誰でも参照できます。


## 「**user**」と「**expires**」が設定されているときに、NFTの保有者（owner）が変更される場合について
```solidity
function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override{
        super._beforeTokenTransfer(from, to, tokenId);

        if (from != to && _users[tokenId].user != address(0)) {
            delete _users[tokenId];
            emit UpdateUser(tokenId, address(0), 0);
        }
    }
```
公式のERC4907では、NFTの保有者である「**owner**」が変更される場合、すなわちNFTがtransferされる場合、当該NFTの「**user**」は強制的に「**user**」の地位を剥奪され、「**expires**」の期限は強制的に0になります（なんかNFTの賃貸借（民法601条）よりは使用貸借（民法594条）っぽいですね笑）。


# 使い方について
### GameFiなどのプラットフォーム内でのみ使用されることが想定されるNFTとしての使い道
このNFTはGameFiで今後活用される可能性はあるかもしれません！
Axieなどのplay to earnゲームではスカラシップ制度により、NFTのキャラクターを他の人に使ってもらい、報酬を分配するということが行われています。AxieのNFTには貸し出し機能がビルトインされていなかったので、ERC4907により、シームレスなNFTの貸し出しが可能になるかもしれません。

ただ、Openseaなどのプラットフォームがこれに対応して「**user**」を表示させるのは現実的ではないかもしれません。ERC4907を必要とするNFTはとても少ないと思いますし、パラメーターのうちの一つに過ぎない「**user**」について、プラットフォームがこれに対応するリソースを割くことはやや難しいかもしれません。プラットフォームをまたぐ局面で、ERC4907の効果は限定的かもしれませんね。

### ERC4907のアレンジ
前述の通り、ERC4907はNFTの「**owner**」の権限が強いですが、上記のfunctionの内容を変更して、「**user**」と「**expires**」の強制変更の仕組みを制限したり、NFTのtransferによる「**user**」の地位喪失の仕組みを削除したりして、「**user**」の地位を高めるようなNFTが作れると思います。このようなアレンジは、当該NFTを認証のために使用する場合など、様々な局面で有用かもしれませんね。

公式のERC4907によれば、「**user**」の地位は、「**owner**」によっていつでも一方的に剥奪される状態にあるため、法的には極めて弱い権利利益であるという点は非常に面白いです。これは、「**user**」になることに非常に大きなメリットがあることが大前提になることを意味しています。「**user**」の地位を検討するときは、この大前提と「**user**」に関するコードとを合わせて検討する必要があるという点が興味深いです。「**user**」に関連するコードの仕組みを変更するときは、前提となるプロダクトデザインを十分考慮すべきであるということですね。

# ERC4907を契機にして
個人的には、権限の弱い「**user**」のパラメーターを新設するよりは、「**owner**」よりも権限の強い貸主として「**lessor**」を新設すべきであったと思います。この「**lessor**」には、一定期間経過後、誰が「**owner**」であっても「**owner**」を「**lessor**」に戻す権限を与えておきます。これにより、貸し出す目的でNFTをtransferして「**owner**」を移転させても、仮に「**owner**」となった借主が当該NFTを無断で転売したとしても、一定期間経過後に「**lessor**」にNFTの「**lessor**」が戻るのであり、NFTそれ自体に安全な貸出機能をビルトインすることができます。
また、これを採用すれば、既に存在するOpenseaやmetamaskで借主がNFTを表示させることが可能になり、プラットフォームをまたいでNFTの貸出しを実現することが可能です。プラットフォームをまたいで機能を追加することはweb3冥利に尽きますね。
この仕組みでは、NFTを借りる者も、「**owner**」になっているわけなので、借り手もNFTを借りている感や、持ってる感を実感することができます。

この新しい仕組みは、近いうちにサンプルを作り、次回の記事で紹介していきたいですね笑
EIPを精査して、似たものがないかどうかについても調査していきたいです。

与信のないNFTの貸し出しは、新たな経済圏のトリガーになるかもしれませんね。
何か良い案や参照すべき資料があれば是非教えてもらえると嬉しいです。

それではまた〜！