使用web3.py爬取ETH指定地址交易value为0及ERC20金额获取问题
问题1:交易的value值始终为0的原因
你获取的transaction['value']字段仅记录该笔交易中原生ETH的转账数量,你遇到的value为0的交易本质是调用智能合约的交易,没有伴随原生ETH的转账:
你给出的交易示例中input字段的前8个字符是0xa9059cbb,这是ERC20标准中transfer方法的函数选择器,说明该笔交易是发起ERC20代币转账的合约调用,自然不会在value字段记录数值。
问题2:区分钱包地址与智能合约地址的方法
直接调用web3.eth.get_code(待查询地址)即可:
- 如果返回结果为
0x或者长度小于3的空字节串,说明该地址是普通钱包地址(外部账户EOA),链上没有部署合约代码 - 如果返回结果为长字节串,说明该地址是智能合约地址,链上存储了对应的合约字节码
问题3:获取ERC20代币转账金额的方法
两种常用方案,优先推荐第二种:
方案1:解析交易input字段
仅适用于外层交易直接调用ERC20的transfer/transferFrom方法的场景:
- 先判断交易input前8个字符是否为
0xa9059cbb(transfer方法)或0x23b872dd(transferFrom方法) - 将input除前8位以外的内容按32字节拆分:
- 对应transfer方法:第一组32字节后20位是接收地址,第二组32字节是转账数量(十六进制转十进制即可)
- 对应transferFrom方法:第一组是转出地址,第二组是接收地址,第三组是转账数量
- 获取对应ERC20合约的decimal小数位,将拿到的原始数量除以10的decimal次方,得到实际代币金额
方案2:抓取ERC20 Transfer事件日志(更稳妥,效率更高)
ERC20标准要求所有代币转账都要触发Transfer事件,你可以直接过滤区块范围内的对应事件日志,不需要遍历所有交易:
- Transfer事件的固定topic0为
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef - 调用
web3.eth.get_logs()接口,过滤参数:fromBlock、toBlock指定查询的区块范围topics参数设置为[事件哈希, 可选转出地址过滤, 可选接收地址过滤]
- 日志返回结果中:
topics[1]是转出地址topics[2]是接收地址data字段是转账的原始数量
- 同样按对应代币的decimal转换为实际金额即可
这个方法还能捕获到合约内部发起的ERC20转账,不会漏单,查询效率远高于遍历所有区块交易。
内容的提问来源于stack exchange,提问作者taga
相关产品推荐
相关产品推荐

