Alert Source Discuss
Standards Track: ERC

ERC-7578: 物理资产赎回

为实体资产支持的 NFT 持有者提供关于底层实物资产的现成可用的真实世界信息。

Authors Lee Vidor (@V1d0r), David Tan <david@emergentx.org>, Lee Smith <lee@emergentx.org>, Gabriel Stoica (@gabrielstoica)
Created 2023-08-01
Requires EIP-165, EIP-721

摘要

本提案是 ERC-721 的扩展,通过捕获信息来增强 NFT 底层实物资产的相关功能和信息,使实物资产支持的 NFT 持有者能够验证真实性并促进底层实物资产的赎回。本提案的主要目的是通过披露相关方的详细信息来提高透明度,并提供定义和提供 NFT 持有者与相应底层实物资产的所有者/持有者之间相关法律关系的机会。本提案使代币发行者有责任嵌入关于底层实物资产和相关关键方的一组标准化信息的准确信息。

动机

NFT 用例的第一波主要包括数字资产所有权的表示。鉴于预期将任何现实世界资产代币化的趋势,预计 NFT 的用例将围绕实物资产迅速增长和扩展。缺乏关于底层实物资产的嵌入式标准化信息集,以及缺乏对相关关键方的透明度,为 NFT 持有者和潜在用户制造了不必要的障碍,这可能因此阻碍将 NFT 用作特定实物资产所有权表示的大规模采用。

为了解决缺乏现成可用的信息,并为代币化经济的大规模采用铺平道路,本提案要求每个铸造的代币都包含一定数量的预定义变量,从而能够验证真实性并促进底层实物资产的赎回。

规范

本文档中的关键词 “MUST”、”MUST NOT”、”REQUIRED”、”SHALL”、”SHALL NOT”、”SHOULD”、”SHOULD NOT”、”RECOMMENDED”、”MAY” 和 “OPTIONAL” 必须按照 RFC 2119 中的描述进行解释。

当铸造代币时,应预先初始化其属性,每个字段定义如下:

  • 代币发行者:识别铸造 NFT 的个人或实体
    代币发行者是将实物资产和数字表示连接起来的关键人物。通过识别和披露代币发行者,NFT 持有者可以立即获得一个参考点,从而可以对 NFT 发行者进行尽职调查,并评估 NFT 发行者的可信度。同时,它为代币发行者创建了责任,从而全面改进和标准化 NFT 铸造流程。代币发行者将竞相争取最佳实践和认可,以获得相对于竞争对手的优势。例如,信誉良好的 NFT 发行者将保留有关铸造基础实物资产之前实物资产的合法所有者的信息,以满足任何 AML 和 KYC 问题。理想情况下,NFT 发行者通过名称识别,但也可能通过服务提供商发行的唯一识别号或网络 ID 来识别,该服务提供商存储有关 NFT 发行者的相关信息。

  • 资产持有者:识别底层实物资产的合法所有者
    鉴于要赎回底层实物资产并执行合法权益,(从法律角度来看)NFT 持有者必须识别底层实物资产的合法所有者。它允许 NFT 持有者考虑法律交易对手风险。不能假定 NFT 发行者是底层实物资产的合法所有者,因此,NFT 持有者必须能够立即访问此附加信息。与 NFT 发行者的身份相同,合法所有者最好通过名称识别,但也可能通过服务提供商发行的唯一识别号或网络 ID 来识别,该服务提供商存储有关合法所有者的相关信息。

  • 存储位置:识别底层实物资产的存储位置
    某些实物资产需要特定的存储条件。对存储不当的实物资产的数字表示可能会严重影响 NFT 的价值。披露存储位置并使其可直接供 NFT 持有者访问,使他们能够评估底层实物资产的存储风险。此外,它为 NFT 持有者提供了执行底层实物资产赎回的第二个联系点。

  • 条款:识别法律关系
    披露和访问 NFT 持有者与底层实物资产的合法所有者之间关系的法律依据,促使代币发行者规定和定义相关关键方的合法权益。此外,它允许 NFT 持有者进行法律风险和执行评估。理想情况下,通过嵌入指向实际法律文档(如协议或条款)的链接来提供信息。可以通过 NFT 访问的信息越多,NFT 持有者可以评估与执行底层实物资产赎回相关的法律风险就越好。

  • 管辖权:管辖法律和管辖权
    适用法律是法律合同披露的扩展,并使 NFT 持有者或智能合约可以立即了解在哪个管辖范围内执行,而无需查看详细的法律合同。这允许立即评估管辖权风险。

  • 声明价值:底层资产的价值
    某些辅助服务(如保险)与 NFT 和底层实物资产的价值相关联。通过定义声明价值,可以以某种方式对 NFT 进行分类,而声明价值则提供了有关底层资产价值的指示。底层实物资产的声明价值并不一定代表市场价值。

terms 参数应是存储在 IPFS 上的文档的 HTTP 链接。这是为了确保文档是不可变的,并且可以由 NFT 持有者验证。

当要销毁具有有效属性的代币时,必须删除这些属性。

合约接口

pragma solidity ^0.8.21;

/**
 * @notice Struct encapsulating fields required to by the ERC-7578 standard to represent the physical asset
 * @param tokenIssuer The network or entity minting the token
 * @param assetHolder The legal owner of the physical asset
 * @param storageLocation The physical location where the asset is stored
 * @param terms Link to IPFS contract, agreement or terms
 * @param jurisdiction The legal justification set out in the terms
 * @param declaredValue The declared value at time of token minting
 */
struct Properties {
    string tokenIssuer;
    string assetHolder;
    string storageLocation;
    string terms;
    string jurisdiction;
    Amount declaredValue;
}

/**
 * @notice Struct encapsulating fields describing the declared value of the physical asset
 * @param currency The currency of the amount
 * @param value The value of the amount
 */
struct Amount {
    string currency;
    uint256 value;
}

/**
 * @notice Required interface of an ERC-7578 compliant contract
 */
interface IERC7578 {
    /**
     * @notice Emitted when the properties of the `tokenId` token are set
     * @param tokenId The ID of the token
     * @param properties The properties of the token
     */
    event PropertiesSet(uint256 indexed tokenId, Properties properties);

    /**
     * @notice Emitted when the properties of the `tokenId` token are removed
     * @param tokenId The ID of the token
     */
    event PropertiesRemoved(uint256 indexed tokenId);

    /**
     * @notice Retrieves all properties of the `tokenId` token
     * @dev Does NOT revert if token doesn't exist
     * @param tokenId The token ID of the minted token
     */
    function getPropertiesOf(uint256 tokenId) external view returns (Properties memory properties);
}

设置 properties 时,会发出 PropertiesSet(uint256 indexed tokenId, Properties properties) 事件。

删除 properties 时,会发出 PropertiesRemoved(uint256 indexed tokenId) 事件。

getPropertiesOf(uint256 tokenId) 函数必须返回代币的唯一 properties。如果 ERC-721 代币被销毁或未设置任何属性,则应返回一个空的 Properties 结构。

理由

如果未在铸造之前初始化代币的属性,则存在无法确定代币所代表的资产来源的风险。

合约级别的验证不用在这些属性上,因为我们认为声明的数据的准确性由代币发行者负责。这在代币发行者和代币本身上建立了信任。

向后兼容性

此标准与 ERC-721 兼容。

参考实现

一个包含使用 OpenZeppelin ERC-721 v5 库的此提案的 ERC-721 示例:

pragma solidity ^0.8.21;

import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { IERC7578, Properties, Amount } from "./interfaces/IERC7578.sol";

/**
 * @title ERC7578
 * @author DESAT
 * @notice Implementation of the ERC-7578: Physical Asset Redemption standard
 **/
contract ERC7578 is ERC721, IERC7578 {
    /**
     * @notice Thrown when the properties of a token are not initialized
     */
    error PropertiesUninitialized();

    /**
     * @notice Retrieves the properties of the `tokenId` token
     */
    mapping(uint256 tokenId => Properties) private _properties;

    /**
     * @notice Initializes the name and symbol of the ERC-721 collection
     */
    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}

    /**
     * @inheritdoc IERC7578
     */
    function getPropertiesOf(uint256 tokenId) public view override returns (Properties memory properties) {
        properties = _properties[tokenId];
    }

    /**
     * @notice Initializes the ERC-7578 properties of the `tokenId` token
     *
     * WARNING: This method should only be called within a function that has appropriate access control
     * It is recommended to restrict access to trusted Externally Owned Accounts (EOAs),
     * authorized contracts, or implement a Role-Based Access Control (RBAC) mechanism
     * Failure to properly secure this method could lead to unauthorized modification of token properties
     *
     * Emits a {PropertiesSet} event
     */
    function _setPropertiesOf(uint256 tokenId, Properties calldata properties) internal {
        _properties[tokenId] = Properties({
            tokenIssuer: properties.tokenIssuer,
            assetHolder: properties.assetHolder,
            storageLocation: properties.storageLocation,
            terms: properties.terms,
            jurisdiction: properties.jurisdiction,
            declaredValue: Amount({
                currency: properties.declaredValue.currency,
                value: properties.declaredValue.value
            })
        });

        emit PropertiesSet(tokenId, _properties[tokenId]);
    }

    /**
     * @notice Removes the properties of the `tokenId` token
     * @param tokenId The unique identifier of the token whose properties are to be removed
     *
     * Emits a {PropertiesRemoved} event
     */
    function _removePropertiesOf(uint256 tokenId) internal {
        delete _properties[tokenId];
        emit PropertiesRemoved(tokenId);
    }

    /**
     * @notice Override of the {_update} function to remove the properties of the `tokenId` token or
     * to check if they are set before minting
     * @param tokenId The unique identifier of the token being minted or burned
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
        address from = _ownerOf(tokenId);
        if (to == address(0)) {
            _removePropertiesOf(tokenId);
        } else if (from == address(0)) {
            if (bytes(_properties[tokenId].tokenIssuer).length == 0) revert PropertiesUninitialized();
        }

        return super._update(to, tokenId, auth);
    }
}

安全注意事项

为了确保真实性,代币属性必须仅通过限制为受信任的外部拥有帐户 (EOA) 或合约的方法来设置。此受信任的实体必须验证这些属性是否准确反映了所表示资产的真实物理属性。此外,应实施适当的访问控制机制,以防止在设置代币属性后对其进行未经授权的修改。

版权

版权及相关权利通过 CC0 放弃。

Citation

Please cite this document as:

Lee Vidor (@V1d0r), David Tan <david@emergentx.org>, Lee Smith <lee@emergentx.org>, Gabriel Stoica (@gabrielstoica), "ERC-7578: 物理资产赎回," Ethereum Improvement Proposals, no. 7578, August 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7578.