Etherscan官方活动页示例。
Etherscan官方活动页示例。

图片资料:官方来源

查看完整图片 ↗

在Etherscan地址页的Activity区,Internal Transactions和Token Transfers (ERC-20)是两个独立标签,记录的内容不同,既不能互相替代,也不该把金额相加。常见的误读有两种:把内部交易当成用户又签了一笔转账;把代币转账的数量直接加进ETH余额变动里。

先把三个层次分开。

第一层是顶层交易,即Transactions标签里的记录。每一条对应一笔由外部账户签名并被打包的交易,有交易哈希、nonce、gas价格和实际支付的gas费。

第二层是内部交易。Etherscan把它展示为合约发起的内部调用,本质是合约执行过程中产生的调用记录。它不是用户另外签名的一笔顶层交易,没有独立签名,也没有独立nonce,不能脱离那笔顶层交易单独存在。一个顶层交易可以触发零个、一个或多个内部调用;看到一个Internal Transactions条目,也不能倒推用户当时签了一笔新交易。

第三层是ERC-20代币转账,来自代币合约执行时发出的事件日志,标签页按事件整理代币的转出与转入。代币不是ETH,代币数量与ETH金额单位不同,不能混加。

用一个假设合约算一遍。假设某合约的提现函数被调用时向调用者退回0.5 ETH。用户签名发出的顶层交易只有一笔,哈希只有一个,其顶层Value通常为0;在Internal Transactions里能看到合约向用户地址转出0.5 ETH的内部调用。这笔交易对被检查地址的ETH净变化约为0(顶层Value,本例为支出0)+0.5(内部转入收入)-gas费,而不是0.5再加一遍0.5。顶层Value要按收/支带符号计入:地址是发送方时记支出,是接收方时记收入;gas费也只扣该地址实际承担的部分。两栏指向同一笔顶层交易,但各自记录的是不同流向:顶层是用户发起的调用,内部是合约退给用户的价值。看清这一点,既不会把0.5算成1,也不会因为“同一个哈希”就漏掉真实的内部入账。

还要避免另一个方向的过度推断:不是每个内部调用都伴随ETH转移。合约之间的调用可能只改状态、只发事件或只传递数据,内部调用列表里出现条目,并不等于有ETH到账。判断是否有ETH移动,要看该条目是否带有Value字段及具体数额,而不是数条目个数。已回滚交易的最终收据不会保留成功执行的事件日志,调试轨迹里的调用记录也不证明资金到账,只有成功交易留下的状态变化才作数。

代币一侧同样要小心。Token Transfers页面通常已按代币精度换算显示数量,不需要读者再对显示值除一次decimals;需要换算的是你自己从日志或接口拿到的原始整数。日志本身只是线索,不是最终余额的证明:核对代币余额,应以成功交易执行后的地址余额或合约状态为准,非标准代币的实现也可能让日志与实际余额不一致。

排障可以按这个顺序:先在Transactions找到顶层交易,确认发送方、接收方、状态和gas费;再打开交易详情看Internal Transactions,确认合约内部是否发生价值转移;最后单独看Token Transfers,把代币变动与ETH变动分开记录。ETH余额变化以带符号的顶层Value加上带符号的内部ETH转移再减该地址实际承担的gas为线索;代币余额变化则回到成功交易后的余额或合约状态核对,日志只用来定位是哪几笔交易动了它。两者各记各的。

Etherscan把这几类活动分栏展示,不是为了让人相加,而是为了让人分清来源。地址页上的数字,只有按来源分开读,才不会越看越乱。

资料来源