ERC-7813 Store 表式存储:链上数据长得像数据库表时,索引器怎么不再猜
每上一个新协议,索引器就要重写一遍解析逻辑:这个事件第三参数是 uint256 还是地址、那笔改动落在哪个状态槽——链上数据的语义全靠人肉读源码补齐。ERC-7813(Store, Table-Based Introspectable Storage)提出一种让合约状态自带说明书的存法:数据组织成表,表的结构登记在链上,状态变化用统一事件广播。所有表的目录放在一张用固定资源标识(以 ASCII 前缀 tb 加 store 与 Tables 拼成的 bytes32 标识)登记的 Tables 元表里,索引器天然知道从哪找起。按以太坊 ercs 仓库的记录,这份提案状态为 Last Call,创建于 2024 年 11 月 8 日。
表、记录与键元组
在这套模式里,一张表由 ResourceId 标识,记录用一组 bytes32 键元组定位,字段有固定的静态与动态布局。读取侧是 IStore 三个函数:getRecord 传入表标识与键元组,返回静态数据、一组编码长度和动态数据三段;getField 只取第 fieldIndex 个字段;getFieldLength 量单个字段的字节长度。对工具来说,这意味着任意一个 7813 合约都可以用同一套读法遍历——不再需要为每个合约写定制解析器。
但真正让索引器省事的不是读函数,而是事件。标准定义了一组以 Store 为前缀的事件:Store_SetRecord 广播整条记录的写入,Store_DeleteRecord 广播删除,Store_SpliceStaticData 与 Store_SpliceDynamicData 广播字段级的局部改写。事件里带上表标识、键元组和编码后的新值,一个通用索引器订阅这些事件,就能按 schema 自动把链上状态镜像进数据库——标准文本称之为 schema-aware 的状态复制。

Tables 元表:让系统长出内省能力
新增的表从哪来?答案是每张 Store 里都有一张特殊的 Tables 表,登记着所有表的资源标识、字段布局等 schema 元数据。客户端启动时先读这张元表,就拿到了整座”链上数据库”的目录,之后按目录逐表同步。运行中新建的表会触发 Store_SetRecord 更新元表,索引器追到这条记录就自动感知新表,不需要人工配置。合约升级加表、加字段都不再破坏既有工具,这是”可内省”三个字的真正含义。
代价:编码格式成了新的必读文件
一次真实读取的完整路径
假设你要为某个 7813 协议做一个持仓页面,标准给的工作流只有一条直线。先定位合约的 Store 地址,对 Tables 元表发一次 getRecord,拿到全部已注册表的清单与资源标识;再对目标表读 schema 记录,解析出字段布局——静态字段各有固定字节宽度,动态字段用 Splice 语义记录切片位置。页面需要展示哪个键元组,就调 getRecord 拿三段返回值,或干脆用 getField 只取需要的那列,配合 getFieldLength 预分配缓冲区。历史部分不进状态读取的路:从最近一次部署块开始订阅四类 Store 事件,按事件里的表标识路由到对应表,按键元组 upsert,剪枝操作(Splice 事件)按字节偏移就地改写。整条链路没有一处需要读合约源码。这个流程同时也是排障手册:页面数字与链上对不上时,先对根因二分——是 Tables 目录版本落后于合约升级,还是某条 Store_SpliceDynamicData 的切片偏移解错——两类错误的修复路径完全不同。标准还把访问控制单独成节,提醒读接口与写权限分离,任何人免 Gas 可查正是这套设计的卖点而非补丁。
统一带来的另一面是门槛转移。7813 为静态与动态数据定义了自己的紧凑二进制编码,字节切片用 Splice 语义表达局部修改,还明令禁止动态类型的数组这类无法定长编码的形状。读不惯这套编码的人,看到的 getRecord 返回值就是一团 bytes。对普通用户,这层变化其实中性:链上事实没变,变的只是工具解析它的方式。真正要留意的是两点:其一,元数据说表有某字段,不代表写入方填了有意义的值,schema 描述的是形状不是真相;其二,采用这套模式的协议往往把大量业务状态放进 Store,审计时先拉 Tables 目录再逐表核对,比逐事件猜测高效得多。本文为机制说明,不构成任何投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。