合约解码:选择器匹配不等于动作已证实
区块浏览器显示的函数名,是对字节的解释,不是经济动作的独立证明。合约研究应保留原始调用数据、适用ABI和执行证据,再把可读标签写成已验证事件。
Solidity ABI规范说明编码不是自描述的,函数选择器是从函数签名推导的四字节。这使模式选择非常重要。公开签名库可以给出候选名称,却不能证明目标部署实现的就是这个候选。
建立解码证据链
保存网络、交易哈希、目标地址、区块和原始calldata,找到与当时生效代码对应的ABI。若使用代理,区分交易目标和真正处理调用的实现。当前验证ABI不一定适用于历史交易。
记录ABI来自哪里,为什么能对应部署。与代码匹配的验证结果,应和签名数据库猜测分开。四字节可能取值有限,不同签名可以产生相同选择器,仅可读名称无法解决歧义。
按候选模式解码全部负载,核对动态偏移、长度和剩余字节。第一个参数看起来合理还不够;类型能够解码,也不证明代码按熟悉名称暗示的经济用途使用了参数。
假设案例:标签说存入,状态却不是
假设虚构浏览器在公开签名库找到前四字节,把调用标为deposit。原始负载包含选择器及64字节参数。研究者直接写成“100代币已存入金库”。
再假设历史实现的已验证ABI把这些字节对应到另一种双参数函数,实际只修改内部设置,没有转移代币。最初标签只是候选解释,不能证明存入。
| 证据层 | 需要核对的问题 |
|---|---|
| 原始字节 | 真正提交了哪个目标与负载? |
| 历史ABI | 哪个模式匹配当时代码? |
| 执行 | 相关调用是否成功? |
| 日志与状态 | 改变了什么,合约如何定义? |
| 经济结论 | 是完成存入,还是只提交请求? |
例子没有声称存在某个真实碰撞或交易,只展示标签不能替代证据链。即使正确名称确实是deposit,实现也可能只登记请求或权利,而非马上移动命名资产。
日志同样需要模式
事件应结合发出地址和匹配事件模式解码。索引参数与非索引参数位于不同位置,部分类型的topic哈希也不是明文值。保留原始topics及data,让复查者能够重现。
将成功执行与相关余额或状态变化连接。总交易成功标记,不证明每个内部经济动作都完成。反过来,没有熟悉事件,也不证明没有变化,代码可能采用其他事件或状态路径。
用少量直接核对结果测试解码器,相关时包括升级边界、动态参数和模式未解决样本。不能只为让数据完整,就把歧义调用强行分入最熟悉的类别。
发布解码值时带上模式出处、区块对应代码和经济验证状态。ABI纠错、实现历史更新、标签与状态不符时复查。交付的是可审计解释,不是断言所有浏览器标签都错。
原始整数应与展示换算并列。ABI可能正确解码uint256,但界面套错代币小数位,或标成另一种资产。模式正确与经济单位正确是两个检查;函数名和金额看似合理,仍需核实资产身份、尺度和研究时点。代理升级后若字段含义改变,不能仅因类型未变就沿用旧经济解释。
批量调用还应保留子调用顺序和目标地址;相同参数在不同目标可能具有不同语义,不能只解码最外层就断言全部内部动作完成。
常见问题
选择器匹配就证明函数名吗?
不能。它提供候选,需确认当时实现及ABI,再解码完整负载。
事件名称能独立证明资产转账吗?
不能。还要检查发出方、模式、代码语义和相关余额状态,名称是证据的一部分而非结论。