按钮点下去之后:Frame 动作里可伪造的数据与可信数据 图 1
按钮点下去之后:Frame 动作里可伪造的数据与可信数据 · 图 1

在社交信息流里点一个”Mint”按钮就完成 NFT 铸造,看起来像网页电商一样简单。但这张嵌在帖子里的交互卡片(社区称 Frame)背后,是一次默认不安全的网络请求:按钮点击只是让客户端向你的 Frame 服务器发了一个 POST 请求,而请求体本身——按开发者文档的说法——默认未经认证,任何人都可以伪造。

拆开一份真实的动作请求,会看到两组泾渭分明的数据。第一组叫 untrustedData:里面写着谁点了(fid 用户编号)、点了哪个按钮(buttonIndex)、发生在哪条帖子上(castId)、时间戳等。名字里的 untrusted 不是谦虚——这组字段由发起方拼装,一个熟悉格式的任何人手工拼出同样的 JSON,就能声称自己是某个用户点了某个按钮。第二组叫 trustedData:只有一段 messageBytes,是客户端对这条动作消息的签名。签名本身难以伪造,但它是否可信仍要验证——服务器要把这串字节提交给 Hub 网络(或通过验证服务)校验,通过后才能还原出”确实是编号某的用户、在时间某、点了这条帖子的按钮几”。文档给出的示例流程很直白:把 trustedData 提交验证接口,返回里才出现真实的用户档案、绑定钱包地址和按钮索引。

为什么要把设计讲得这么细?因为 Frame 的典型用途对”身份是否真实”极其敏感。服务器逻辑往往是”校验通过就铸造一枚 NFT 并发给这个 fid 绑定的地址”。如果偷懒只读 untrustedData,等于把发件人自报的姓名当作汇款凭证:脚本可以无限重放别人的动作、冒充不存在的用户、在限额活动里刷出成倍领取量。防刷、防冒领、防重放,三道门都卡在同一个节点——服务端校验签名字节,并且以校验结果为准,而不是以表单内容为准。

校验通过也不是一劳永逸。签名能证明”这一下确实是用户点的”,但点击的时点、按钮序号、帖子哈希是否与你挂出的交互一致,仍要服务器逐字段比对;用户绑定的钱包地址列表可能有多个,发给哪一个、由谁最终签名收款,是另一层业务规则。文档示例里那串返回字段(验证后的 fid、带时间戳的 cast 信息、tapped_button 索引)正是为这种逐项比对准备的原材料。

另一类高频事故是状态不同步:Frame 的界面卡片本质是一张服务器生成的图片加几个按钮链接,服务器内存里”还剩几件”的判断,在多人同时点击时可能超发。成熟做法是把限量判断挪到链上——由合约函数或带条件的铸造交易兜底,服务器只做转发与展示;不成熟的做法则依赖服务器自己记账,页面显示”成功”而链上根本没发、或链上发了两次,都要靠用户自己回查交易记录确认。这也是为什么教程反复强调:交互卡片给你的每一句”已铸造”,都值得去区块浏览器用交易哈希复核一遍再当回事。

对使用者,这套机制的启示在于体验与信任是分开建设的:你在信息流里点一下,只是发出了一封带火漆的信;至于 NFT 会不会真的到账,取决于收信的那台服务器有没有认真验章、验完有没有按承诺执行。评估一个 Frame 小应用是否可靠,可以看它对失败与重放的处理是否透明——重复点击会不会连扣两次、验证失败时提示什么、到账凭据去哪查。按钮背后从来不是魔法,是一段老老实实的校验代码,或者一段偷懒跳过的空门。

安全边界上还有两句话要说在前头。其一,按钮回传的账户身份以签名为凭,用户不需要授权任何代币,但点击按钮不等于上链交易——只有点了交易型按钮并另行签名,资产才真的动起来,界面上把二者混在一起的框架要格外小心。其二,回跳地址与图片来源都在域名持有者控制下,冒牌站点可以做出形似的按钮与画面,判断交互真假的最硬证据不是页面漂亮,而是 Hub 验签后的消息记录与链上交易,这两样造假成本高、核验路径清晰,是 Frames 生态里少数可以完全信任的事实层。

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

按钮点下去之后:Frame 动作里可伪造的数据与可信数据 图 2
按钮点下去之后:Frame 动作里可伪造的数据与可信数据 · 图 2