NFT 也能拥有 NFT:ERC-998 可组合代币的父子账本
大多数 ERC-721 合约里,一枚代币只有一个主人,主人是一个钱包地址。ERC-998 想回答一个更绕的问题:如果主人不是地址,而是另一枚代币呢?这份在 ethereum/ERCs 仓库里标注为 Draft 的提案把“代币持有代币”写成了一套接口,最常见的举例是游戏:角色拿装备、背包装道具、皮肤挂头像框,一整串资产跟着角色走。
四种角色拼出一棵树
ERC-998 覆盖了四类实现:能持有 ERC-721 的顶层组合代币(ERC998ERC721 top-down)、能持有 ERC-20 的顶层组合代币(ERC998ERC20 top-down)、主动把自己挂到别的 ERC-721 名下的底层组合代币(bottom-up),以及同样挂在 ERC-721 名下的 ERC-20 代币。顶层组合合约替自己每枚代币记一份“孩子清单”,底层组合合约反过来记录“家长是谁”。两种记账法拼起来,就是一棵以所有权为边的树,整棵树只有一个根主人——站在树根位置的那个地址。

接口里值得逐个看的函数
想问“追到树根是谁”,用 rootOwnerOf 和 rootOwnerOfChild;想翻某枚代币名下的孩子,用 ownerOfChild、getChild、totalChildContracts、childContractByIndex、childTokenByIndex;想把单个孩子拆走,用 transferChild 或 safeTransferChild;想把整枚代币挂上或摘下父代币,用 transferAsChild、transferToParent、transferFromParent。配套的 ReceivedChild、TransferChild、TransferToParent、TransferFromParent 事件是给索引器重建树形结构用的。设计意图很直白:换整棵树的主人只需改一次根所有权,一笔交易带走一背包资产。
复杂度留在了哪一层
组合的代价不在链上,在工具链。市场、钱包、区块浏览器默认看到的是“地址持币”,父子关系要多问几层合约才能还原;索引器若没实现 998 接口,你的装备可能干脆显示为空。还要分清两种授权语义:对父代币的 approve 不自动等于对每个孩子的 approve,孩子代币在不同合约里各管各的转账。这份提案在标准流程里停在 Draft,也说明生态没有形成统一采用,不少游戏最终选择把装备记在自己服务器的账本里,而不是上链组合。
买这类资产前核对什么
一笔交易的旅程:装备跟着角色走
把标准文本里的流程走一遍更能看清它省了什么。假设角色币在合约 A 的 42 号,头盔币在合约 B 的 7 号。头盔先“穿上”:调用方对 B 合约执行 transferAsChild,把 7 号转成 A 合约 42 号的子币,A 侧记账登记这个孩子——B 合约里这笔代币的所有权字段不再指向某个地址,而是指向父代币坐标,事件流里能看到这次挂载。之后头盔再想单飞,需要有人对 B 执行 transferFromParent 之类接口把它从父名下摘回地址名下。整套语义的要点是:孩子代币在“挂树”期间没有独立的主人地址,任何想绕过树直接动孩子的尝试都会被父合约层的记账拒绝或显形。对索引器而言,还原一匹马的全部家当是一次递归:从地址出发拿余额,再对每枚代币查子清单,循环直到叶子。Gas 上这笔旅程并不便宜——多层合约回调意味着转账成本随树深上升,标准自己也承认顶层组合的 safeTransferFrom 语义比朴素 721 复杂得多。
新手最常问的三个问题
第一个问题:我的普通 NFT 会因为别人实现了 998 就自动多出孩子吗?不会——组合关系必须有人显式调用转移函数,你钱包里的 ERC-721 不会无故变成谁的子币。第二个问题:怎么知道我买的是不是组合币?用 ERC-165 探测合约是否声明 998 相关接口,再试着调用 totalChildContracts,报错或返回零通常说明没有挂载结构。第三个问题:市场显示的和链上一致吗?以链上递归查询为准,展示页漏掉子资产是常见问题,尤其在不认识这套接口的平台。把这三问养成习惯,绝大多数“买角色送装备”的承诺都能在售前验出成色。
先确认市场能否完整显示孩子代币,再确认转让走不走标准事件,最后看一眼父合约的权限:如果父合约可以随意更换孩子的绑定,你买“带装备的角色”就等于接受装备可被改写。它能说明所有权结构被写成了什么样,不能说明这套结构值多少钱。本文只讲协议机制,不构成投资建议,也不对任何项目做优劣判断。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。