通过 EIP-3664 实现的高级 NFT 属性:完整指南

  • cyfrin
  • 发布于 2025-03-03 16:34
  • 阅读 21

EIP 3664 是一种扩展 NFT 标准的提案,允许 NFT 属性的可定制性、互操作性和演变能力。本文详细介绍了 EIP 3664 的实现原理、与现有标准的不同之处,以及其对 NFT 生态系统的影响,结合具体示例阐述了多种属性类型.

EIP 3664 - 高级 NFT 属性的完整指南

EIP 3664 扩展了 NFT 标准,以支持可定制、互操作和可进化的 NFT 属性。你将学习如何使用它,它是如何工作的,以及它对生态系统的影响。

如果你的 NFT 可以升级,获得技能,并像视频游戏中的角色一样进化,那会怎样?

近年来,NFT 在实用性和技术方面都有了巨大的进步。

从数字艺术和收藏品到进入元宇宙、房地产和 web3 游戏,NFT 推动着新的数字拥有权和价值范式的形成。但随之而来的新用例带来了新的功能,这反过来又要求开发更新和更强大的技术标准。

《以太坊改进提案(EIP 3664)》于 2021 年 7 月发布, 这就是一种这样的演变,扩展了现有的 NFT 标准,以启用可定制、互操作和可进化的 NFT 属性。

在本文中,我们将介绍 EIP 3664 是什么,为什么我们需要它,它与现有的 NFT 协议有何不同,它是如何工作的,以及它对 NFT 生态系统带来了什么影响。

EIP 3664 - 概述

EIP 3664 是一个可扩展的 NFT 元数据协议,允许所有现有的 NFT 协议,如 ERC 721 和 1155 标准,增强其属性的描述能力。如果你不知道 EIP 是什么,请查阅 从零到英雄的智能合约审计师指南

EIP 3664 不是像 ERC 721 或 1155 的 NFT 创建协议。

相反,它充当一个可扩展的 NFT 元数据框架,以为使用 ERC 721 或 ERC 1155 创建的 NFT 提供属性可扩展性。该规范规定了可以 将属性标记化并用于自定义 NFT 的各种方式

每个属性都有一个与之相关的 attrId,借助于这个属性,独立的属性可以被 标记化、转移和组合,以创建动态艺术作品、游戏内资产和化身。

为什么 EIP 3664?

EIP 3664 背后的目标是将静态 NFT 转换为可变 NFT。 允许开发者创建模块化的基于组件的 NFT,其属性可以根据特定应用事件转化、转移和过渡。

用户还可以组合和交易这些属性组件,以创造出更好的可组合 NFT。

因此,EIP 3664 旨在补充基础标准,而不是取代它们。

要理解它的必要性,我们必须花一点时间理解基础的 ERC 721 和 ERC 1155 合同提供了什么,以及它们缺少什么。

ERC721 和 ERC1155 是什么?

ERC-721 的关键特性:

  • 被确立为以太坊上 NFT 创建的基本标准。
  • 仅支持不可替代代币的创建和转移。
  • 提供简单的Token与所有者之间的映射。
  • 包括跟踪和从一个帐户转移代币的基本方法。
  • 拥有多个代币类型的所有者只能一次部署一个集合。因此,对于多个代币,必须部署多个智能合约。

ERC-1155 的关键特性:

  • 多代币标准,支持可替代(ERC 20)和不可替代(ERC 721)代币。
  • 允许在同一合约中配置多种代币类型,每种代币由唯一的 tokenID 表示。
  • 每个 tokenId 可以有自己的元数据、供给和属性。
  • 引入 批量转移 功能,允许在一个交易中转移多个代币,从而降低手续费和 避免重复 API 调用来铸造每个集合。
  • 包含烧毁和批量烧毁方法,以永久从供给中移除代币。
  • 安全转移规则 允许发送者指定在启动代币转账之前必须满足的条件。

751 和 1155 的比较:

ERC 721 ERC1155
支持的代币创建类型 仅限不可替代 两者,可替代和不可替代
一份合约可以创建的 NFT 收藏数量 仅一个 多个(无穷无尽)
开箱即用的批量交易支持 不支持 支持
代币供给 固定 可铸造和可烧毁
开箱即用的交易撤销 不能回退交易 安全转移功能支持交易撤销
支持属性可变性 不支持 不支持

什么是 NFT 属性?

让我们假设你在玩一个 基于 web3 的宝可梦游戏,每个宝可梦都是一个 NFT。

在你的游戏开始时,教授“X”赠送给你 Auditchu - 一个 Eth 类型 的宝可梦 - 它热爱审计智能合约,寻找漏洞,并保护 dApps 免受恶意利用。

Aditchu。图片来源:Midjourney

Auditchu 的属性(特征)可以是它的物理特征,比如爪子和翅膀。

属性也可以描述它的整体特征,如“力量”、“技能”、“类型”和“等级”。

让我们来看一下 Auditchu 的一些属性:

宝可梦类型 主要属性(不变)
WingsLevel 等级 1 在完成游戏内任务和使命时升级。
WingsImage 图片 每个 wingsLevel 有不同的 wingsImage。可以附加、拆卸或转移。
Strength 30 / 100 可变的 - 可能根据审计记录增加或减少
Logic 40 / 100 可变的 - 可能根据审计记录增加或减少
Vision 35 /100 可变的 - 可能根据审计记录增加或减少
Aura 美学 可转移特征,可以交易其他光环

EIP 3664 中的动态属性

  • 属性是特定的 提供 NFT Token的额外细节或元数据的属性或特征。它们拥有独立于基础 NFT 的元数据和值。
  • 它们作为 可组合组件,可以附加到基础 NFT 并从中删除 - 例如“力量”、“等级”和“世代”。
  • 在 ERC-3664 中定义的每个属性都有一个自己的 唯一 ID。这些 ID 用于单独管理和操作属性(链上)。
  • EIP-3664 目前扩展了对 可升级、可变、可转移、可进化和基于文本的属性 的支持。我们将在接下来的内容中详细了解它们。

每个属性 ID (attrId) 有一个唯一的 URI。URI 是某些数据或资源的唯一标识符。


function attrURI(uint256 attrId) external view returns (string memory);

该 URI 可以指向描述属性的 JSON 元数据文件。


{
  "name": "WingsImage",
  "description": "在完成游戏内任务和使命时升级。",
  "type": "转移可能",
  "visual": {
    "src": "ipfs://wing.svg",
    "alt": "wing component"
  }
}

作为 Auditchu 逐渐变老(游戏内活动时间),审计更多合约并在 CodeHawks 赢得安全比赛后,它的力量和经验逐渐增加。

力量的增加带来了像更大翅膀这样的新特征升级!

最终,Auditchu 解锁了他的进化种子,成功转变为更大、更强、聪明的宝可梦 - Auditmax!

图像:Auditmax(Auditchu 的进化版)

宝可梦类型 主要属性(不变)
WingsLevel 等级 3 在完成游戏内任务和使命时升级。
WingsImage 图片 每个 wingsLevel 有不同的 wingsImage。可以附加、拆卸或转移。
Strength 80 / 100 可变的 - 可能根据审计记录增加或减少
Logic 90 / 100 可变的 - 可能根据审计记录增加或减少
Vision 90 / 100 可变的 - 可能根据审计记录增加或减少
Aura 威严 可转移特征,可以交易其他光环。在进化时解锁新光环。
Crown (新解锁的特征!) 图片 在进化后附加的特征

理解这一点至关重要,在我们的例子中,进化的 NFT 并不是被其他新的 NFT 替代。旧的 NFT 特征正在被更新特征所修改。

这就是属性可组合性的强大之处!

现在我们已经理解了 EIP 3664 的目的,是时候看看代码了!

EIP 3664 - 理解合同

当前实现的 EIP 3664 扩展了 ERC1155 标准。但 EIP 3664 被设计为 兼容任何类型的不可替代代币标准,不仅仅是 ERC 721 或 1155。

ERC 3664 的主接口定义了某些函数和事件,用于 附加、管理和删除属性


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev ERC3664 合约所需的接口。
 */
interface ERC3664 {
    /**
     * @dev 当新的属性类型 `attrId` 被铸造时触发。
     */
    event AttributeCreated(
        uint256 indexed attrId,
        string name,
        string symbol,
        string uri
    );

    /**
     * @dev 当属性类型 `attrId` 的 `value` 被附加到 "to"
     * 或从 `from` 被移除时触发,操作员为 `operator`。
     */
    event TransferSingle(
        address indexed operator,
        uint256 from,
        uint256 to,
        uint256 indexed attrId,
        uint256 value
    );

    /**
     * @dev 等同于多个 {TransferSingle} 事件。
     */
    event TransferBatch(
        address indexed operator,
        uint256 from,
        uint256 to,
        uint256[] indexed attrIds,
        uint256[] values
    );

    /**
     * @dev 返回 `tokenId` 所拥有的主要属性类型。
     */
    function primaryAttributeOf(uint256 tokenId)
        external
        view
        returns (uint256);

    /**
     * @dev 返回 `tokenId` 所拥有的所有属性类型。
     */
    function attributesOf(uint256 tokenId)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev 返回 `tokenId` 所拥有的属性类型 `attrId` 的值。
     */
    function balanceOf(uint256 tokenId, uint256 attrId)
        external
        view
        returns (uint256);

    /**
     * @dev 返回 `tokenId` 所拥有的属性类型 `attrIds` 的批量值。
     */
    function balanceOfBatch(uint256 tokenId, uint256[] calldata attrIds)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev 设置 `tokenId` 所拥有的主要属性类型。
     */
    function setPrimaryAttribute(uint256 tokenId, uint256 attrId) external;

    /**
     * @dev 将 `amount` 值的属性类型 `attrId` 附加到 `tokenId`。
     */
    function attach(
        uint256 tokenId,
        uint256 attrId,
        uint256 amount
    ) external;

    /**
     * @dev {attach} 的 [批量] 版本。
     */
    function batchAttach(
        uint256 tokenId,
        uint256[] calldata attrIds,
        uint256[] calldata amounts
    ) external;
}

interface ERC165 {
    /// @notice 查询合约是否实现某个接口
    /// @param interfaceID 接口标识符,如 ERC-165 中所述
    /// @dev 接口识别由 ERC-165 中描述。本函数使用不到 30,000 gas。
    /// @return `true` 如果合约实现了 `interfaceID` 且
    ///  `interfaceID` 不是 0xffffffff,否则返回 `false`
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

将 ERC-3664 应用于 EIP-1155 合约的第一步是定义一个或多个属性,这些属性将附加到 NFT 上。这些属性通常在使用 (_mint)(_mintBatch) 函数进行代币创建时定义。


_mint(address account, uint256 id, uint256 amount, bytes data)

_mintBatch(address to, uint256[] ids, uint256[] amounts, bytes data)
  • to - 新铸造的代币将分配给的地址。
  • id - 每个 ID 代表一个新的可配置代币类型。每种代币类型可以有自己的元数据、供给和其他属性。
  • amount - 指定要铸造的代币数量。
  • data: - 一些自定义实现的额外数据或签名。

铸造的属性以两种方式附加到代币/NFT 上:

  1. 要么是在铸造过程中
  2. 或者动态地应用于更新已经铸造的 NFT。

EIP 3664 合约函数

有三个状态变化的方法用于附加和定义属性。

这些函数只能由代币的所有者或被所有者授权的其他人调用:

1) attach(): 用于单个属性


/**
 * @dev 将 `amount` 值的属性类型 `attrId` 附加到 `tokenId`。
 */
function attach(
    uint256 tokenId,
    uint256 attrId,
    uint256 amount
) external;

2) batchAttach(): 用于从预先确定的属性列表中附加多个可组合的属性,通过 (calldata) 指定


/**
 * @dev {attach} 的 [批量] 版本。
 */
function batchAttach(
    uint256 tokenId,
    uint256[] calldata attrIds,
    uint256[] calldata amounts
) external;

3 setPrimaryAttribute(): 有助于定义 NFT 的“主要”属性。通过此功能,NFT 可以被归类到特定的类别或类型。

示例:武器类型属性定义一种武器属性类别

EIP3664 合约事件

事件允许跟踪属性的变化,例如新铸造和属性值更新。

EIP 3664 接口触发3个事件。前端 dApps 可以监听这些事件以自动更新 UI/元数据。

AttributeCreated 在新的属性类型被铸造时触发,包含 ID、名称、符号和 URI 等详细信息。TransferSingle 在属性值变化时触发,或者在属性附加到 NFT 或从 NFT 中删除时触发。TransferBatch 在多个属性值变化(附加或移除)时触发。

EIP 3664 视图函数

视图函数使得能够查询链上任何 NFT 当前组合的属性。

primaryAttributeOf 返回Token的主要属性 ID。attributesOf 返回给定 (tokenId) 的 NFT 所拥有的所有属性 ID 的数组。balanceOf 获取属于 (tokenId) 的特定属性类型 (attrId) 的值。balanceOfBatch 与 (balanceOf) 相似,但允许调用者一次检查多个属性的值。

提供一个 (attrId) 数组。函数返回与每个 ID 相对应的值数组。

EIP 3664 属性类型

EIP 3664 主要支持以下类型的属性可扩展性(确认):

  1. 一般属性
  2. 可变属性
  3. 可转移属性
  4. 可升级属性
  5. 可进化属性
  6. 文本属性

每个这些属性接口都从 IERC3664Metadata 接口继承了一些属性。

元数据接口:

  • ERC 3664 协议中的 IERC3664Metadata 接口是可选的,使得可以管理属性的元数据。

/**
 * @dev ERC3664 标准中的可选元数据函数接口。
 */
interface IERC3664Metadata is IERC3664 {
    /**
     * @dev 返回属性的名称。
     */
    function name(uint256 attrId) external view returns (string memory);

    /**
     * @dev 返回属性的符号。
     */
    function symbol(uint256 attrId) external view returns (string memory);

    /**
     * @dev 返回 `attrId` 属性的统一资源标识符 (URI)。
     */
    function attrURI(uint256 attrId) external view returns (string memory);
}

我们即将研究的每个属性都扩展自 IERC3664Metada 接口以方便处理。

1) 一般属性

  • 一般属性指的是在本质上不可修改的属性(属性值不能被修改的)。
  • 示例:NFT 的创作者,宝可梦类型
  • 这些属性在铸造 NFT 代币时设定。

2) 可变或可更新属性

  • 可变属性与数值相关联,这些数值可以根据游戏或故事情节中的事件而改变(增加或减少)。
  • 示例:健康值、胜利场次、Auditmax 的力量和逻辑(来自我们的宝可梦示例),或武器的战斗力。
  • remove(uint256 tokenId, uint256 attrId):此函数从某个代币( tokenId)中移除属性 ( attrId)。在此操作之后,该代币将不再拥有该属性。在游戏场景中很有用,例如角色可能会失去某种能力或特征。
  • 特定属性( attrId)的值可以通过某个 amount 的值来增加或减少,使用 increasedecrease 函数。

/**
 * @dev ERC3664 中的可更新函数接口。
 */
interface IERC3664Updatable is IERC3664Metadata {
    /**
     * @dev 从 `tokenId` 中移除属性类型 `attrId`。
     */
    function remove(uint256 tokenId, uint256 attrId) external;

    /**
     * @dev 增加 `tokenId` 的属性类型 `attrId` 的 `amount` 值。
     */
    function increase(
        uint256 tokenId,
        uint256 attrId,
        uint256 amount
    ) external;

    /**
     * @dev 从 `tokenId` 中减少 `attrId` 的 `amount` 值。
     */
    function decrease(
        uint256 tokenId,
        uint256 attrId,
        uint256 amount
    ) external;
}

3) 可转移属性

  • 显而易见,可转移属性可以在同一系列的 NFT 之间进行“转移”。
  • 这为在游戏内市场上交易单独属性创造了机会,并与它们关联了稀缺性/稀有性。
  • 一旦转移完成,NFT ID 保持不变,但其价格和稀缺性可能波动。
  • isApproved(uint256 from, uint256 to, uint256 attrId):isApproved 是一个返回布尔值的函数,用于检查 属性 ( attrId) 是否被批准可以从一个 tokenID ( from) 转移到另一个 tokenID ( to)。
  • 函数 approve(uint256 from, uint256 to, uint256 attrId):批准属性 ( attrId) 从一个代币 ( from) 转移到另一个代币 ( to)。

→ 该函数只能由 from 代币的所有者调用。

→ 触发 AttributeApproval 事件。


/**
 * @dev ERC3664 中可转移的函数接口。
 */
interface IERC3664Transferable is IERC3664Metadata {
    /**
     * @dev 当属性类型 `attrId` 被批准转移 "to" 从 `from` 由 `operator` 时触发。
     */
    event AttributeApproval(
        address indexed operator,
        uint256 from,
        uint256 to,
        uint256 attrId
    );

    /**
     * @dev 如果 `attrId` 被批准转移至 `to` 代币,那么返回 true。
     */
    function isApproved(
        uint256 from,
        uint256 to,
        uint256 attrId
    ) external view returns (bool);

    /**
     * @dev 由 `from` 持有者调用,批准 `from` 的 token 中的属性 `attrId` 转移到 `to` 代币
     * 触发 {AttributeApproval} 事件。
     */
    function approve(
        uint256 from,
        uint256 to,
        uint256 attrId
    ) external;

    /**
     * @dev 将属性类型 `attrId` 从代币 `from` 转移到 `to`
     * 触发 {TransferSingle} 事件。
     */
    function transferFrom(
        uint256 from,
        uint256 to,
        uint256 attrId
    ) external;
}

4) 可升级属性

  • 可升级属性为属性提供了一个 离散的等级/级别进展标度
  • 示例:普通、稀有、史诗级、超超史诗,或者简单的,等级 1、2 或 3,正如我们的宝可梦示例的情况。
  • mintWithLevel(uint256 attrId, string memory name, string memory symbol, string memory uri, uint8 maxLevel) 函数用于铸造具有给定 attrId、名称、符号、URI 和最大等级的属性。
  • upgrade(uint256 tokenId, uint256 attrId, uint8 level) 是一个将特定属性 ( attrId) 的代币 ( tokenId) 升级到某个等级的函数。该函数只能由代币的所有者调用。

interface IERC3664Upgradable is IERC3664Metadata {

    /*当属性 (attrId) 的代币 (tokenId) 升级到某个等级时触发。*/
    event AttributeUpgraded(
        uint256 indexed tokenId,
        uint256 indexed attrId,
        uint8 level
    );
    /*返回特定属性 (attrId) 的代币 (tokenId) 的当前等级。*/
    function levelOf(uint256 tokenId, uint256 attrId)
        external
        view
        returns (uint8);

    function mintWithLevel(
        uint256 attrId,
        string memory name,
        string memory symbol,
        string memory uri,
        uint8 maxLevel
    ) external;

    function upgrade(
        uint256 tokenId,
        uint256 attrId,
        uint8 level
    ) external;
}

5) 可进化属性:

  • 在我看来,这是最有趣和具有变革意义的属性。
  • 可进化属性允许 NFT 有机会“进化”成更强大、稀有的版本。
  • 所以,你可能会问 - 通过进化,你是指我们的 Auditchu 宝可梦 NFT 将会进化成一个更大的 Auditmax 宝可梦 NFT 吗?
  • 这个问题的答案,是不完全是!
  • ERC-3664 为 NFT 的属性提供了 进化能力(并不是让整个 NFT 转变为完全不同的 NFT)。该协议描述了 NFT 如何通过进化来强化其属性,而不是将根 NFT 转变为完全不同的 NFT。

示例:在进化过程中解锁的王冠属性。

  • 函数 period(uint256 tokenId, uint256 attrId) - 返回在何种时间段后,代币 ( tokenId) 的属性 ( attrId) 可以进化或尝试进化。
  • evolutive(uint256 tokenId, uint256 attrId) : 到达进化资格后,持有者可以调用该函数尝试进化。

进化的成功可能并不确定,可能依赖于 NFT 创建者定义的各种因素。

一些方法可能包括:

→ 在达到某个阈值(例如:等级 10、魔法技能达到-黄金等级)时触发资格。

→ 硬编码进化成功概率(60%)。

→ 随机数生成。

→ 每次失败后增加成功的机会,以保证最后能够进化。

→ 或者一些基于时间的解锁技术,如区块编号。

repair(uint256 tokenId, uint256 attrId): 无法进化的属性需要自我修复才能正常操作。( repair)函数用于修复代币 ( tokenId) 的属性 ( attrId),允许其在进化失败后重新进化


/**
 * @dev ERC3664 中可进化函数的接口。
 */
interface IERC3664Evolvable is IERC3664Metadata {

/*当代币 (tokenId) 的属性 (attrId) 可进化(状态为 true)或不再可进化(状态为 false)时触发。*/
    event AttributeEvolvable(
        address indexed operator,
        uint256 tokenId,
        uint256 attrId,
        bool status
    );

/*当代币 (tokenId) 的属性 (attrId) 被修复时触发。*/
    event AttributeRepaired(
        address indexed operator,
        uint256 tokenId,
        uint256 attrId
    );

    function period(uint256 tokenId, uint256 attrId)
        external
        view
        returns (uint256);
    /*此函数只能由代币的所有者或被授权的人调用。*/
    function evolutive(uint256 tokenId, uint256 attrId) external;

/*此函数只能由代币的所有者或被授权的人调用。*/
    function repair(uint256 tokenId, uint256 attrId) external;
}

6) 文本属性

  • 基于文本的属性允许将任意文本元数据与其他属性类型相关联。这使得 NFT 也能够保持非结构化的基于文本的属性。这与 Loot Project NFTs 类似。
  • 函数 attachWithText(uint256 tokenId, uint256 attrId, uint256 amount, bytes memory text) : 将文本 (text) 附加到代币 ( tokenId) 的属性 ( attrId) 上。amount 参数表示该属性的值。

interface IERC3664TextBased is IERC3664Metadata {

/*返回与代币 (tokenId) 的特定属性 (attrId) 相关联的文本。*/

    function textOf(uint256 tokenId, uint256 attrId)
        external
        view
        returns (bytes memory);

    function attachWithText(
        uint256 tokenId,
        uint256 attrId,
        uint256 amount,
        bytes memory text
    ) external;

    function batchAttachWithTexts(
        uint256 tokenId,
        uint256[] calldata attrIds,
        uint256[] calldata amounts,
        bytes[] calldata texts
    ) external;
}

最后,如果我们考虑我们的宝可梦示例,Auditmax 的属性可以分类为以下几种。

属性 类型
WingsLevel 等级 3 可升级
WingsImage 图片 可转移
Strength 80 / 100 可变
Logic 85 / 100 可变
Vision 90 / 100 可变
Aura - 可转移
Crown (新解锁的特征!) 等级 1 可进化

使用 EIP 3664 扩展现有的 NFT 收藏

  • 将现有 NFT 收藏扩展到 3664 不需要对其核心实现进行任何修改。
  • ERC-3664 可以简单地附加在现有 NFT 之上,以增强它们的额外属性。
  • 对于 ERC-721 和 ERC-1155 NFTs,ERC-3664 属性可以在不需要更改基础合约的情况下添加。
  • 基础的 ERC-721 和 ERC-1155 实现保持完全不变。

因此,ERC-3664 仅能通过其合约定义可定制的补充属性。

结论

恭喜你到达了终点! 🏁🏁🏁 现在你成功了解了整个新的 NFT 标准。

我们首先了解了 EIP 3664 的内容,它的重要性,以及它与其他 NFT 标准的比较。接下来,我们通过我们的宝可梦示例理解了 可组合属性 的概念。Auditmax 是个高手!⚡

最后,我们深入研究了合约,理解了它的流程,并研究了 EIP 3664 提供的各种属性类型的细微差别,以创造出终极的、可定制的、可进化的非同质化资产。

如果你想了解更多关于智能合约开发的知识,请务必查看 Cyfrin Updraft - 这是智能合约工程师最全面的学习平台。

祝你发挥出色 💪

  • 原文链接: cyfrin.io/blog/eip-3664-...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
cyfrin
cyfrin
Securing the blockchain and its users. Industry-leading smart contract audits, tools, and education.