Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-6806: ERC-721 持有时间跟踪

向 ERC-721 代币添加持有时间信息

Authors Saitama (@saitama2009), Combo <combo@1combo.io>, Luigi <luigi@1combo.io>
Created 2023-03-30
Discussion Link https://ethereum-magicians.org/t/draft-eip-erc721-holding-time-tracking/13605
Requires EIP-721

摘要

本标准是 ERC-721 的扩展。它添加了一个接口,用于跟踪和描述一个账户持有 Non-Fungible Token (NFT) 的时间。

动机

在某些用例中,了解 NFT 被一个账户持有的时长非常有价值。此信息可用于奖励长期持有者,确定对独家内容的访问权限,甚至可以基于持有时间来实现特定的业务逻辑。然而,当前的 ERC-721 标准没有内置的机制来跟踪 NFT 持有时间。

本提案旨在通过扩展 ERC-721 标准,使其包含持有时间跟踪功能,从而解决这些限制。

规范

本文档中的关键词“必须”,“不得”,“必需”,“应该”,“不应该”,“推荐”,“可以”和“可选”应按照 RFC 2119 中的描述进行解释。

接口

以下接口扩展了现有的 ERC-721 标准:

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0

interface IERC6806 {
    function getHoldingInfo(
        uint256 tokenId
    ) external view returns (address holder, uint256 holdingTime);
}

函数

getHoldingInfo

function getHoldingInfo(uint256 tokenId) external view returns (address holder, uint256 holdingTime);

此函数返回指定 NFT 的当前持有者以及该 NFT 被当前账户持有的时长(以秒为单位)。

  • tokenId: NFT 的唯一标识符。
  • 返回值: 一个元组,包含当前持有者的地址和持有时间(以秒为单位)。

原理

getHoldingInfo 函数添加到 ERC-721 标准的扩展允许开发人员实现需要持有时间信息的基于 NFT 的应用程序。此扩展保持与现有 ERC-721 实现的兼容性,同时为新的用例提供额外的功能。

getHoldingInfo 函数提供了一种直接的方法来检索 NFT 的持有时间和持有者地址。通过使用秒作为持有持续时间的单位,它可以确保精度并与智能合约中其他基于时间的函数兼容。

getHoldingInfo 同时返回 holderholdingTime,以便出于计算持有时间的目的,可以忽略某些代币所有者(由实现决定)。例如,合约可以获得 NFT 的所有权作为贷款的抵押品。这样的贷款合约可以被忽略,因此实际所有者的持有时间会正确增加。

向后兼容性

此提案与现有的 ERC-721 标准完全向后兼容,因为它使用不影响核心功能的新函数扩展了该标准。

参考实现

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./IERC6806.sol";

contract ERC6806 is ERC721, Ownable, IERC6806 {
    mapping(uint256 => address) private _holder;
    mapping(uint256 => uint256) private _holdStart;
    mapping(address => bool) private _holdingTimeWhitelist;

    constructor(
        string memory name_,
        string memory symbol_
    ) ERC721(name_, symbol_) {}

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstotTokenId,
        uint256
    ) internal override {
        if (_holdingTimeWhitelist[from] || _holdingTimeWhitelist[to]) {
            return;
        }

        if (_holder[firstotTokenId] != to) {
            _holder[firstotTokenId] = to;
            _holdStart[firstotTokenId] = block.timestamp;
        }
    }

    function getHoldingInfo(
        uint256 tokenId
    ) public view returns (address holder, uint256 holdingTime) {
        return (_holder[tokenId], block.timestamp - _holdStart[tokenId]);
    }

    /**
     * @dev 设置是否忽略重置持有时间
     * @param account 需要设置的地址
     * @param ignoreReset 是否忽略重置
     */
    function setHoldingTimeWhitelistedAddress(
        address account,
        bool ignoreReset
    ) public onlyOwner {
        _holdingTimeWhitelist[account] = ignoreReset;
        emit HoldingTimeWhitelistSet(account, ignoreReset);
    }
}

安全考虑

此 EIP 引入了用于跟踪持有时间的额外状态管理,这可能具有安全隐患。实施者应警惕与持有时间操纵相关的潜在漏洞,尤其是在转移期间。

在实施此 EIP 时,开发人员应注意潜在的攻击媒介,例如重入攻击和抢先交易攻击,以及智能合约的一般安全最佳实践。应进行充分的测试和代码审查,以确保实施的安全性和正确性。

此外,开发人员应考虑与维护和更新持有时间信息相关的 gas 成本。可能需要进行优化以最大程度地减少对合约执行成本的影响。

同样重要的是要注意,持有时间信息的准确性取决于底层区块链时间戳的准确性。虽然区块时间戳通常是可靠的,但矿工可以在一定程度上对其进行操纵。因此,在需要绝对精度的情况下,不应将持有时间数据作为唯一的真实来源。

版权

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

Citation

Please cite this document as:

Saitama (@saitama2009), Combo <combo@1combo.io>, Luigi <luigi@1combo.io>, "ERC-6806: ERC-721 持有时间跟踪 [DRAFT]," Ethereum Improvement Proposals, no. 6806, March 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6806.