猫的档案里有几个格子:getKitty 返回的基因、代数与父母编号 图 1
猫的档案里有几个格子:getKitty 返回的基因、代数与父母编号 · 图 1

早期的链上宠物把”一只猫”压缩到了极致:在主合约的数据结构注释里,作者特意说明每只猫的状态被精心排布,刚好塞进两个字长的存储槽。听起来简陋,但这套字段至今仍是读懂这个经典项目的钥匙——链上关于一只猫能确认的一切,都出自这张小卡片。

查询入口是主合约的视图函数 getKitty,传入猫的编号,返回一整排字段:是否怀孕(isGestating)、是否就绪(isReady)、冷却索引(cooldownIndex)、下次可行动时间(nextActionAt)、配种对象编号(siringWithId)、出生时间、母猫编号(matronId)、父猫编号(sireId)、代数(generation)与基因(genes)。源码注释写得很直白:判断一只猫是否怀孕,看的不是哪个专门的布尔值,而是 siringWithId 是否非零——设计上用”零即无”的约定省空间,读的人必须知道这个约定。

最常被问的是 genes。源码里它是一整个 256 位整数,注释直接标注”猫的基因永不改变”。官方指南解释了这串数字的内部结构:基因组按块排布,每四个基因一组对应一个性状,组内一个是显性基因、三个是隐性基因;显性基因决定猫的外观,隐性基因不外露但可能遗传,显性传递概率约四分之三,隐性合计约四分之一。也就是说,你看到的花色只是这 256 位里被”显示”的那一层,剩下的大半编码在链上静静留存,任何能读合约的人都可以把它解码出来。这套”四元组加显隐性”的结构,也是后来一切”链上遗传”类玩法的原型。

generation 的推导规则同样写在注释里:官方铸造的初代猫编号为 0;其余猫的代数取父母中较大的那个加一。配套地,matronId 与 sireId 用 32 位整数记录父母编号,初代猫的这两个字段为 0——这个”零”不是缺失,而是”官方直发”的标记。32 位的取值上限在注释里也被作者拿来算过一笔账:约 42 亿只,对比当时以太坊的年交易量级绰绰有余。代数与父母指针合起来构成一棵可以回溯的家谱:任意一只非初代猫,理论上都能沿字段一路解码回两只初代祖先。

cooldownIndex 藏着繁育节奏的开关。源码注释说明:初代猫此值从 0 起步,非初代猫按”代数除以二向下取整”初始化,此后每完成一次成功繁育动作就加一,无论它当的是母亲还是父亲。冷却时长逐档递增,这就是这套系统用时间换稀缺的核心机制,也是老玩家口中”时间税”的出处——猫越生越慢,官方不再增发之后,新猫的速度由全体存量猫的冷却共同决定。

最后一个细节关于”神秘感”。主合约的注释提到,基因混合算法被单独拆到一个外部合约里,其余代码开源,唯独这步”超-secret”操作早期不公开,为的是不让遗传结果太容易被算尽。后来的开发者确实通过逐条分析字节码把组合函数还原了出来——这也是链上项目的一个普遍宿命:只要规则最终要在链上被执行,它就只是延迟公开,不会永远公开不了。

读这些字段最大的收获不是养猫,而是一个视角:藏品在链上从来不是”一张图”,而是一份格式紧凑、约定隐晦的状态记录。界面替你翻译了多少、略过了多少,决定了你看到的是一只猫的全部,还是它的名牌。今天大量新协议往元数据里塞几十个字段,回头看这张两个字长的卡片反而更清楚:链上档案的价值不在字段数量,而在每个字段是否有明确规则、可否被任何人独立验证。查询时也要留意合约版本差异——早期教学仓库里的测试网代码把部分时间参数改短了,冷却档位等生产数值以主网合约源码为准。

本文为机制说明,不构成任何投资建议。

猫的档案里有几个格子:getKitty 返回的基因、代数与父母编号 图 2
猫的档案里有几个格子:getKitty 返回的基因、代数与父母编号 · 图 2