提交前检查
1. epusdt 版本
v1.0.3
2. 问题概述
目前 BSC / Polygon 的 EVM 自动监听逻辑主要依赖实时 WebSocket eth_subscribe(logs) 推送。
我检查 v1.0.3 源码后发现:
- 监听断开后会重连
- 节点失败达到阈值后会切换到其他 WS 节点
- 但是没有看到任何“区块断点续扫 / 历史补扫”逻辑
也就是说,如果在以下时间窗口内发生充值:
subscribe: Too many requests
websocket abnormal closure
subscription error
log channel closed
- WS 节点故障后切换节点的间隔
系统看起来只会“重新订阅”,不会从断线前最后处理区块继续补扫到最新区块,因此存在漏单风险。
3. 相关代码
1)BSC / Polygon 只建立实时 WS 订阅
BSC:
query := ethereum.FilterQuery{
Addresses: contracts,
Topics: [][]common.Hash{},
}
runEvmWsLogListener(ctx, "[BSC-WS]", wsNode, query, func(client *ethclient.Client, vLog types.Log) {
...
service.TryProcessEvmERC20Transfer(...)
})
Polygon:
src/task/listen_polygon.go
query := ethereum.FilterQuery{
Addresses: contracts,
Topics: [][]common.Hash{},
}
runEvmWsLogListener(ctx, "[POLYGON-WS]", wsNode, query, func(client *ethclient.Client, vLog types.Log) {
...
service.TryProcessEvmERC20Transfer(...)
})
这两处都没有看到 fromBlock / toBlock / FilterLogs / getLogs 一类补扫逻辑。
2)公共 EVM WS 监听器只做“重连订阅”,没有历史回放
src/task/listen_evm_ws.go
client, err := ethclient.Dial(wsURL)
...
sub, err := client.SubscribeFilterLogs(ctx, query, logsCh)
...
case err := <-sub.Err():
if err != nil {
log.Sugar.Warnf("%s subscription error: %v, reconnecting", logPrefix, err)
return fmt.Errorf("subscription error")
} else {
log.Sugar.Warnf("%s subscription closed, reconnecting", logPrefix)
return fmt.Errorf("subscription closed")
}
case vLog, ok := <-logsCh:
if !ok {
log.Sugar.Warnf("%s log channel closed, reconnecting", logPrefix)
return fmt.Errorf("log channel closed")
}
handleLog(client, vLog)
这里可以看到:
- 断线后会返回外层重连
- 但没有记录
lastProcessedBlock
- 没有在重连后执行
FilterLogs / eth_getLogs
- 没有从“上次处理到的区块 + 1”补扫到当前最新区块
3)对比:Tron 的 block scanner 是有块号推进逻辑的
src/task/listen_trc20_block.go
latestNum := latest.BlockHeader.RawData.Number
if latestNum <= s.lastBlock {
...
return
}
for num := s.lastBlock + 1; num <= latestNum; num++ {
...
s.lastBlock = num
}
Tron 这里至少明确有 lastBlock 和逐块推进逻辑,但 EVM WS 监听侧没有看到对应实现。
4. 风险点
如果充值恰好发生在以下窗口,可能不会被自动识别:
- WS 订阅断开到重新建立之间
- 节点限流报错到下一次重试之间
- 当前节点失败到切换到新节点之间
- 进程重启后,如果启动前一段时间有 EVM 充值,也没有看到自动补扫逻辑
从代码实现看,这部分当前更像是:
- 实时 WS 自动监听
- 失败后重连 / 切节点
- 漏掉的单需要依赖手动补单
而不是:
5. 建议
建议为 EVM 链增加区块补扫机制,例如:
- 记录每条链 / 每个监听器最近成功处理到的区块号
- WS 重连成功后,先获取当前最新区块
- 用
FilterLogs / eth_getLogs 从 lastProcessedBlock + 1 补扫到最新区块
- 补扫完成后再继续实时
SubscribeFilterLogs
- 节点切换时也执行同样的补扫逻辑
这样可以显著降低 subscribe: Too many requests、abnormal closure、节点故障切换期间的漏单风险。
6. 补充说明
我这里说的是“自动监听流程”本身缺少补扫,不是“完全没有补单手段”。
项目目前确实有手动提交交易哈希 / 手动补单能力,但这属于人工兜底,不能替代自动区块补扫。
提交前检查
1. epusdt 版本
v1.0.3
2. 问题概述
目前 BSC / Polygon 的 EVM 自动监听逻辑主要依赖实时 WebSocket
eth_subscribe(logs)推送。我检查
v1.0.3源码后发现:也就是说,如果在以下时间窗口内发生充值:
subscribe: Too many requestswebsocket abnormal closuresubscription errorlog channel closed系统看起来只会“重新订阅”,不会从断线前最后处理区块继续补扫到最新区块,因此存在漏单风险。
3. 相关代码
1)BSC / Polygon 只建立实时 WS 订阅
BSC:
src/task/listen_bsc.goPolygon:
src/task/listen_polygon.go这两处都没有看到
fromBlock / toBlock / FilterLogs / getLogs一类补扫逻辑。2)公共 EVM WS 监听器只做“重连订阅”,没有历史回放
src/task/listen_evm_ws.go这里可以看到:
lastProcessedBlockFilterLogs/eth_getLogs3)对比:Tron 的 block scanner 是有块号推进逻辑的
src/task/listen_trc20_block.goTron 这里至少明确有
lastBlock和逐块推进逻辑,但 EVM WS 监听侧没有看到对应实现。4. 风险点
如果充值恰好发生在以下窗口,可能不会被自动识别:
从代码实现看,这部分当前更像是:
而不是:
5. 建议
建议为 EVM 链增加区块补扫机制,例如:
FilterLogs/eth_getLogs从lastProcessedBlock + 1补扫到最新区块SubscribeFilterLogs这样可以显著降低
subscribe: Too many requests、abnormal closure、节点故障切换期间的漏单风险。6. 补充说明
我这里说的是“自动监听流程”本身缺少补扫,不是“完全没有补单手段”。
项目目前确实有手动提交交易哈希 / 手动补单能力,但这属于人工兜底,不能替代自动区块补扫。