はじめに

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

今回は、NFTに保証人というロールを導入し、一定の価格でいつでも換金できる仕組みを提案しているERC7652についてまとめていきます!

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

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

概要

ERC7652は、ERC721(NFT)に「保証人(Guarantor)」という役割を追加する提案です。 保証人とは、特定のNFT(token ID)に対して価格保証を提供する主体を指します。

ERC7652では、NFTごとに以下のような情報と振る舞いを定義します。

NFTに対して、ユーザーが設定した評価額を扱います。 これは、保証人がそのNFTに対して「最低限この価値がある」と認める金額です。 加えて、その評価額のうち、どの範囲までを保証するかを示す保証割合も管理します。

保証人は価格保証という義務を負う一方で、保証に対する利息や報酬を受け取る権利を持ちます。 ERC7652は、これらの保証に関する権利と義務をNFTの取引フローの中に組み込みます。

この仕様を実装したコントラクトでは、NFTのtoken IDを指定することで、現在の保証価格を取得したり、新たに設定したりできます。 また、NFTが売買や送付された時には、保証利息の分配や保証義務の履行が自動的に行われます。

保証の状態が変更された場合には、標準化されたイベントが発行されます。 これにより、ウォレットやマーケットプレイス、インデクサーなどの外部システムが、NFTの保証状況を正確に追跡できます。

ERC7652は、既存のERC721を前提として設計されており、NFTの基本仕様を変更することなく保証機能を拡張する規格です。

動機

NFT市場における流動性の課題

NFT(token ID)は、一般的に市場流動性が低いという問題を抱えています。 主な原因は、NFTの価格が不透明であることです。

多くのNFTは、明確な評価基準が存在せず、「いくらで売れるのか」が事前に分かりません。 そのため、購入後に売却しようとしても買い手が見つからない、あるいは大幅に値下げしなければ売れないケースが多くあります。

この不確実性が、NFT市場全体の参加ハードルを高くしています。

保証人による価格評価の導入

ERC7652では、この問題に対して保証人という新しい役割を導入します。

複数の保証人グループが、それぞれの判断基準に基づいてNFTに価格保証を提供できます。 これにより、NFTの価値は単一の主観ではなく、複数の保証に基づく評価の集合として表現されるようになります。

結果として、NFTの価格に一定の透明性が生まれ、ユーザーは取引時の判断材料を得やすくなります。

ユーザー保護としての買い戻し保証

NFTを購入したユーザーは、いつでも保証人にNFTを返却し、保証された最高価格で買い戻してもらうことが可能です。

これにより、価格下落のリスクが明確に限定されます。 ユーザーは「最低でもこの価格では売れる」という下限を把握したうえでNFTを保有できるため、心理的・経済的な負担が大きく軽減されます。

保証の引き継ぎと継続性

保証人は、自身が保証義務を果たした後、次の保証人に対して保証を引き継ぐことを求めることができます。

この仕組みにより、NFTの流通過程において保証が断絶せず、継続的に提供される構造が生まれます。 NFTは一度きりの保証で終わるのではなく、状況や所有者の変化に応じて、保証主体が移り変わっていきます。

DAOによるNFTの保有と運用

保証人は個人だけでなく、DAO(分散型自律組織)であることも想定されています。

NFTが保証人であるDAOの所有下にある場合でも、そのNFTはDAOの意思決定プロセスの中で運用され続けます。 これによりNFTは、単なる資産ではなく、コミュニティや社会的文脈を伴った存在として価値を蓄積していくことが可能になります。

仕様

インターフェース

IERC721Guarantee.sol
pragma solidity ^0.8.20;

// import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";

/// @title EIP-721 Guarantor Role extension
///  Note: the EIP-165 identifier for this interface is


interface IERC721Guarantee /*is IERC721*/{
    /// @notice           Emitted when `guarantee contract` is established for an NFT
    /// @param user       address of  guarantor
    /// @param value      The guarantee value provided by dao
    /// @param DAO        DAO organization providing guarantee
    /// @param tokenId    Guaranteed NFT (token ID),
    event GuaranteeIsEstablshed(
        address user,
        uint256 value,
        address DAO,
        uint256 indexed tokenId
    );

    /// @notice           Emitted when `guarantee contract` is canceled
    /// @dev              Some users in the closed DAO request a reduction in their guarantee share
    /// @param user       address of  guarantor
    /// @param value      The guarantee value provided by dao
    /// @param DAO        DAO organization providing guarantee
    /// @param tokenId    Guaranteed NFT (token ID),
    event GuaranteeIsCancel(
        address user,
        uint256 value,
        address DAO,
        uint256 indexed tokenId
    );

    /// @notice           Emitted when `Guarantee sequence` is established for an NFT
    /// @param userGuaranteed      address of guaranteed
    /// @param number  block.number of transaction,
    ///                and all DAOs established before this point will enter the guarantee sequence
    /// @param DAOs   DAO sequence providing guarantee
    /// @param tokenId Guaranteed NFT (token ID),
    event GuaranteeSequenceIsEstablshed(
        address userGuaranteed,
        uint256 number,
        address DAOs,
        uint256 indexed tokenId
    );

    /// @notice   A user's evaluation for an NFT (token ID)
    /// @dev      Set the guarantee information for one guarantor,
    /// Throws if `_tokenId` is not a valid NFT
    /// @param value  user's evaluation for  an NFT, the oledr value is canceled,
    /// @param user   address of guarantor
    /// @param weight guarantee weight for guarantor
    /// @param tokenId The NFT
    /// @return the error status of function execution
    function setNFTGuarantedInfo(
        uint256 value,
        address user,
        uint256 weight,
        uint256 tokenId
    ) external returns (uint256);

    /// @notice   Establish guarantee sequence for an NFT (token ID) and split the commission
    /// @dev      Each NFT(token ID) retains a current guarantee sequence,
    ///           and expired guarantee sequences are no longer valid,
    ///           Throws if `_tokenId` is not a valid NFT
    /// @param valueCommission Commission for a transactions
    /// @param userGuaranteed   address of guaranteed
    /// @param number  block.number of transaction,
    ///              and all DAOs established before this point will enter the guarantee sequence
    /// @param tokenId The NFT
    /// @return the error status of function execution
    function establishNFTGuarantee(
        uint256 valueCommission,
        address userGuaranteed,
        uint256 number,
        uint256 tokenId
    ) external returns (uint256);

    /// @notice   Transactions that fulfill the guarantee responsibility
    /// @dev      The new accountability transaction also requires
    ///           the construction of a new guarantee sequence
    ///           Throws if `_tokenId` is not a valid NFT or userGuaranteed is not right

    /// @param  userGuaranteed   address of guaranteed
    /// @param  tokenId The NFT
    /// @return the error status of function execution
    function FulfillGuaranteeTransfer(address userGuaranteed, uint256 tokenId)
        external
        returns (uint256);
}

イベント

GuaranteeIsEstablshed
javascript
event GuaranteeIsEstablshed(
    address user,
    uint256 value,
    address DAO,
    uint256 indexed tokenId
);

NFTに対する保証コントラクトが新たに確立された時に発行されるイベント。 このイベントは、特定のNFTに対して保証人およびDAOによる保証が正式に設定された時に発行されます。 保証価格や保証主体がオンチェーンで明示されるため、外部システムが保証開始を検知できます。

パラメータ

  • user
    • 保証人のアドレス。
  • value
    • DAOが提供する保証評価額。
  • DAO
    • 保証を提供するDAOのアドレス。
  • tokenId
    • 保証対象となるNFTのトークンID。
GuaranteeIsCancel
javascript
event GuaranteeIsCancel(
    address user,
    uint256 value,
    address DAO,
    uint256 indexed tokenId
);

NFTに対する保証コントラクトがキャンセルされた時に発行されるイベント。 このイベントは、DAO内部の意思決定などにより、既存の保証が無効化された場合に発行されます。 保証割合の縮小やDAOの解散など、保証が継続できなくなった状況を表します。

パラメータ

  • user
    • 保証人のアドレス。
  • value
    • キャンセル時点の保証評価額。
  • DAO
    • 保証を提供していたDAOのアドレス。
  • tokenId
    • 保証がキャンセルされたNFTのトークンID。
GuaranteeSequenceIsEstablshed
javascript
event GuaranteeSequenceIsEstablshed(
    address userGuaranteed,
    uint256 number,
    address DAOs,
    uint256 indexed tokenId
);

NFTに対する保証シーケンスが確立された時に発行されるイベント。 このイベントは、NFTの取引や保証履行に伴い、保証の順序(シーケンス)が確定した時に発行されます。 指定されたブロック番号以前に保証を行っていたDAOが、保証シーケンスに参加することを示します。

パラメータ

  • userGuaranteed
    • 保証を受けるユーザーのアドレス。
  • number
    • 基準となるブロック番号。
  • DAOs
    • 保証シーケンスに参加するDAOのアドレス。
  • tokenId
    • 対象となるNFTのトークンID。

関数

setNFTGuarantedInfo
javascript
function setNFTGuarantedInfo(
    uint256 value,
    address user,
    uint256 weight,
    uint256 tokenId
) external returns (uint256);

NFTに対する保証人の評価額と保証比率を設定する関数。 この関数は、特定のNFTに対して、保証人が提示する評価額と保証の重みを登録します。 すでに同一保証人による設定が存在する場合、以前の値は無効化されます。 無効なトークンIDが指定された場合は、処理が失敗します。

引数

  • value
    • 保証人が提示するNFTの評価額。
  • user
    • 保証人のアドレス。
  • weight
    • 保証人が負担する保証割合や重み。
  • tokenId
    • 対象となるNFTのトークンID。

戻り値

  • uint256
    • 関数実行結果を表すステータスコード。
establishNFTGuarantee
javascript
function establishNFTGuarantee(
    uint256 valueCommission,
    address userGuaranteed,
    uint256 number,
    uint256 tokenId
) external returns (uint256);

NFTに対する保証シーケンスを確立し、手数料を分配する関数。 この関数は、NFTごとに現在有効な保証シーケンスを構築します。 過去の保証シーケンスは無効となり、新しい保証責任の順序が定義されます。 同時に、取引に伴う手数料を保証人間で分配する処理も想定されています。

引数

  • valueCommission
    • 取引に対して発生する手数料の金額。
  • userGuaranteed
    • 保証を受けるユーザーのアドレス。
  • number
    • 基準となるブロック番号。
  • tokenId
    • 対象となるNFTのトークンID。

戻り値

  • uint256
    • 関数実行結果を表すステータスコード。
FulfillGuaranteeTransfer
javascript
function FulfillGuaranteeTransfer(
    address userGuaranteed,
    uint256 tokenId
) external returns (uint256);

保証責任を履行するためのNFT移転を実行する関数。 この関数は、保証条件が満たされた場合に、NFTの移転を通じて保証責任を果たします。 この処理が実行されると、新たな保証シーケンスを構築する必要があります。 保証を受けるユーザーが正しくない場合や、無効なNFTが指定された場合は失敗します。

引数

  • userGuaranteed
    • 保証を受けるユーザーのアドレス。
  • tokenId
    • 対象となるNFTのトークンID。

戻り値

  • uint256
    • 関数実行結果を表すステータスコード。

補足

手数料分配における公平性

ERC7652÷では、NFTの取引や保証履行に伴って手数料(コミッション)が発生します。 この手数料は、複数の保証グループ(DAO)が関与する可能性があるため、グループ間およびグループ内部の双方で公平性を保つことが重要な設計要件になっています。

具体的には、以下のような状況を想定しています。

  • あるNFTに対して複数のDAOが異なる条件で保証を提供している
  • 保証の重みや順序に応じて、受け取るべき報酬が変わる

ERC7652は、こうした状況でも特定のDAOや保証人だけが不当に有利・不利にならないよう、保証シーケンスや保証ウェイトといった概念を導入しています。 これにより、保証にどれだけ関与したかに応じた合理的な分配が可能になります。

保証グループ数の制限とコントラクト肥大化の回避

ERC7652では、インターフェース上で扱う保証グループ(DAO)の数に注意を払っています。

保証を柔軟に設計しようとすると、DAOの一覧や履歴を無制限に保持したくなりますが、それをそのままコントラクトに持たせると、コントラクトが肥大化してガスコストや可読性が悪化します。

そのためERC7652では、以下の方針をとっています。

  • 常に「現在有効な保証シーケンス」を明確にする
  • 過去の保証はイベントとして追跡可能にし、状態としては最小限に保つ

これにより、必要な情報だけをオンチェーンに残し、不要な状態の増加を防ぐ設計になっています。

保証グループはDAOであること

ERC7652における保証グループは、単なるアドレスではなくDAOコントラクトであることを前提としています。

そのため、保証グループとなるDAOは、必ず ERC721TokenReceiver インターフェースを実装する必要があります。

これは、保証履行時にNFTを安全に受け取れることを保証するためです。 もしこのインターフェースを実装していない場合、NFTが送信できず、保証そのものが成立しなくなります。

この制約により、ERC7652は以下の点を保証しています。

  • 保証履行時にNFTが失われない
  • DAOがNFTを受け取り、管理・運用できることが明確になる

シンプルさの重視

ERC7652は、新しい概念を導入している一方で、仕様自体はできる限りシンプルに保つことを重視しています。

保証ロール、保証評価額、保証シーケンスといった要素はありますが、役割や責務が曖昧にならないよう、以下の点が意識されています。

  • インターフェースは必要最小限の関数とイベントに留める
  • 保証の状態遷移はイベントで追跡できるようにする
  • 実装の自由度は確保しつつ、共通部分は標準化する

これにより、実装者が過度に複雑なロジックを強いられることなく、ERC7652を採用できます。

ガス効率への配慮

Ethereum上で動作する以上、ガスコストは無視できない要素です。

ERC7652では、以下の方針を採用しています。

  • 不要なストレージ書き込みを避ける
  • 履歴情報はイベントで表現する
  • 保証シーケンスを単純な構造で扱う

これにより、NFTの保証という追加機能を提供しつつも、通常のNFT取引に対するガス増加を最小限に抑える設計になっています。

互換性

ERC7652は、既存のERC721と完全に互換性があります。

ERC721の基本的な仕様や挙動を変更することはなく、あくまで拡張として保証ロールを追加します。 そのため、以下の特徴があります。

  • 既存のNFTコントラクトは、そのまま動作する
  • ERC7652を実装していないNFTも市場から排除されない

また、NFTに対して保証ロールを定義する標準は、これまで存在していませんでした。 「Guarantor(保証人)」という名称も、他のERC721関連標準では使われていないため、役割の衝突や混乱が起きにくい点も考慮されています。

引用

Liu.C.Dao (@CDao) iunknow@163.com, Sam 1047180870@qq.com, "ERC-7652: ERC-721 Guarantee Extension [DRAFT]," Ethereum Improvement Proposals, no. 7652, March 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7652.

最後に

今回は「NFTに保証人というロールを導入し、一定の価格でいつでも換金できる仕組みを提案しているERC7652」についてまとめてきました! いかがだったでしょうか?

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

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