跳到正文

研究指南

加密现货研究

原生资产流:把调用树与净余额变动核对

一笔交易经过路由器时,同一原生资产可以移动多次。把轨迹里所有value相加,不等于用户净流出,也不等于协议新存入。应把已提交转移做成有方向的数量账,保留调用类型与回滚边界。

本题解释单笔交易造成的地址余额变化,不是解码函数名、统计内部调用行数,也不能因外层成功就说每一层经济动作都完成。

展平之前保留树

Geth内置tracer文档的callTracer部分列出嵌套frame的type、from、to、value、error和子调用,并区分DELEGATECALL代码目标与普通接收地址。不同提供方格式可能不同,应保存客户端版本和配置。

给每个frame标交易哈希和结构路径,例如root、子零、子一,导出成行后仍保留父关系。否则子调用本地成功,后来父层失败回滚整棵子树,也可能被错算为已付款。

不能只按金额或地址对去重。两次真实调用可以有相同from、to和数量;同一frame也可能同时出现在外层摘要和内部转账表。应先确定行对应哪个执行位置,再判断重复。

明确定义入账规则

只有按语义实际转移原生资产、并且效果保留到相关祖先回滚之后的frame,才形成本表的转移边。DELEGATECALL继承的上下文value,不自动是给代码地址的另一笔付款。

拟议但失败的边另列,它可解释行为和成本,却不能因为轨迹显示请求数量就变成已提交资产移动。外层成功也不免除检查内层error。

对每个地址,净贡献等于已提交流入减已提交流出。在覆盖完整的转移图里,手续费和其他余额机制另列之前,各地址贡献之和应为零。这是对账检查,不是轨迹已覆盖所有状态变化的保证。

假设主例:路由一百单位

设虚构账户A、路由R、接收者B和C,原生资产单位足够大无需处理舍入。A给R一百,R执行一次显示上下文value一百的委托代码调用,向B转七十,尝试向C转十但该调用回滚且被捕获,再退A三十。

外层交易成功。R到C的十单位不保留,委托代码地址也不因上下文显示一百而另收一百。下面均按这些明确假设分类。

frame显示value类型判断已提交数量边
root A到R一百成功普通价值调用A到R一百
R上下文委托代码一百上下文执行不由此产生付款
R到B七十成功价值调用R到B七十
R到C十回滚且被捕获无
R退A三十成功退款R到A三十

全显示值求和为三百一十,仅已提交边的毛转移量为二百。两者都不是A净经济流出。A为三十减一百等于负七十;R为一百减七十减三十等于零;B加七十,C零。

四者合计负七十加零加七十加零,等于零。此式能暴露漏退款或重复委托边,却不能把B认作商户,也不识别这次是否出售资产;经济目的需要另一层证据。

如果同一frame在服务摘要与内部表各出现一次,应以结构身份合并,而不是把毛转移二百再翻倍。若两条相同金额有不同路径,则不能仅凭数值相同删除其中之一。重复显示和真实重复动作都可能发生。

另对余额与费用

假设A起始一百五十单位,并有独立依据确认交易费零点零二。在完整假设下,期末为一百五十减七十减零点零二,等于七十九点九八。不能把七十点零二全记成给B的付款。

B若起始十且无其他变化,期末八十;R余额不变。手续费究竟由A还是另一发送者支付必须核对,赞助等安排会改变这条对账,不能一律扣被研究者。

费用各部分也不保证全部流到同一可见地址。窄转移研究可以将已核总费用借项另列,不对无法解释残差编接收者。协议燃烧、接收者及其他分配应按相应规则单独查。

使用适合交易边界的前后状态。整块前后余额可能同时包含其他交易与系统操作,未经排除就归给本笔,会把正确的余额差解释成错误的单笔流量。

不同机制边界:子成功后父回滚

另设替代历史:R给B七十,B内部给D二十并局部成功返回;随后B回滚,R捕获失败。二十这条子调用虽然本地成功,其效果也会随父子树一起回滚。

在这条历史中,假设R最终退A全部一百。已提交边只有A到R一百、R到A一百。B与D净贡献均零,A转移净贡献也零,仍需另算交易费。

它不是原七十付款历史再加二十,而是不同执行分支。展平表若保留子success却丢父error,就会造出未进入状态的付款。因此每条候选边都要检查所有相关祖先,而不仅当前frame。

另一种情况是root整体失败。此时普通应用转移也不能因为内部曾成功就保留,费用等不同回滚边界另核。不要将“消耗了gas”和“收款已完成”混为一谈。

CALL覆盖不应普遍化

合约创建、适用规则下的自毁相关余额变化、验证者提款及其他系统机制,可能需要额外处理。只收普通CALL的数据集,不是全部原生余额变化的完整证书。

残差出现时先确定机制。Geth页面还描述状态型tracer,可协助比较变动账户,但仍需适当历史上下文。状态差证明余额变化,不自动解释经济用途,不能把一切差异都命名为隐形转账。

保存残差金额、地址和候选原因,再取缺失frame、系统记录或正确状态边界。不能静默放入“其他内部流”使总账强行平。明确未解决项比假造平衡边更有用。

区分全图与研究子集

若只报告R所属地址集合,A到R与R退A跨越边界,R到B也可能跨越;R内部另一地址之间的转移则不必形成集合净流入。先按地址对账,再按有依据的集合归并,避免把每个内部跳转都计作外部需求。

集合归属若未知,应保留地址级结果和待核边,不凭路由品牌把所有被调用地址并进一个实体。这样才能说明所谓净流入究竟净掉了哪些内部关系,而不是只有一个不可复算数字。

给实体边界一个复算例

若独立材料把R和B都归入同一实体,主例跨界流入一百,跨界退回三十,实体净流入七十;R到B七十属于该集合内部。若问题只覆盖R,流入一百被流出七十加三十抵消,净额零。相同执行图可以有两个正确结果,差异来自明确边界,而非哪套工具更准确。

先保存地址级净额,再按有依据成员归并。成员未知就保留候选集合与金额影响,不能仅凭路由品牌把被调用地址全部纳入。发布时说清哪些边被内部抵消,别人才能复算所称协议净流入。

替代全额退款历史中,若A仍付假设零点零二费,起始一百五十会变一百四十九点九八。转移贡献为零而费用仍扣,这两个事实不能压成给B付款。root失败等其他情况也应按真实回滚边界另外核,不能从一个成功退款推整笔免费。

金额解析还要保留原始量纲。比如独立测试中的十六进制0x64是十进制一百,若tracer单位为wei,就是一百wei,不是一百ETH。先解码原始整数、再换研究单位,能防止数值守恒看似成立却整体差十八位尺度。主例的一百是明确假设单位,没有冒充真实原始响应。

净额总和零也不能自证完整。若把R到B七十整条边漏掉,A仍负七十、R变加七十、B零,合计仍零。实际R余额未变、B增加七十,才能暴露漏边。守恒和实际地址状态必须一起核,不能用一个恒等式认证全部来源覆盖。

可执行对账表

操作记录能发现的错误
固定执行身份网络、交易、区块、客户端混链、混分支、混格式
保留层级路径与父frame回滚后代被入账
分类语义调用类型与价值效果委托上下文重复扣款
记录保留结果当前error与祖先结局捕获失败被当完成
计算地址净额已提交边的流入流出毛跳数混用户流出
对余额状态边界、费与其他机制所有差额归单笔付款

tracer更正、父错误补回、链状态改变或系统操作识别后,应重核。分别发布毛已提交跳转量、地址净贡献和手续费,解释真实执行路径,而不把调用树长度夸大为存入或用户需求。

常见问题

所有内部value相加能测原生流入吗?

不能。它们可能是连续跳转、失败尝试或上下文,需要先分类再算目标净流。

子调用成功是否在父回滚后保留?

相关父层回滚会移除其效果,需要保留祖先关系判断。

相关阅读