-
前言: 在开发中也是遇到这个问题了,并非常见的
Transfer
,Approve
等在ERC20中定义的事件,只要你的事件在sol文件中存在,那还好处理,但是如果不存在,刚开始接触的时候,你可能就有点懵,我也是找了两天,查阅了很多资料,并没什么niao用,偶然看见了区块浏览器中的log才恍然大悟。 -
问题:Uniswap闪兑事件金额统计,userA在sushi,uniswap中使用USDT兑换了某个代币,我们要统计这个人到底统计了多少这个代币?
-
构造查询:
- 使用
ethereum.FilterQuery
构造查询,例如:query := ethereum.FilterQuery{ FromBlock: big.NewInt(43804**3), ToBlock: big.NewInt(4380**7), Addresses: []common.Address{ common.HexToAddress("0xcEc4*******a689"), common.HexToAddress("0x7135a****7046"), }, //Topics: [][]common.Hash{}, }
- 注意事项:
FromBlock And ToBlock 你一定要填写,不然就timeout了 数量很多很大,建议不要设置太大的交叉数值,一个Block也有很多数据的,可以在address里面写入你要筛选的地址,减少范围
- 使用
-
执行查询:
- 使用
client.FilterLogs(context.Background(), query)
执行查询,例如:logsList, err := w.client.FilterLogs(context.Background(), query)
- 使用
-
筛选:
- 获取调用函数签名
functionSignature := "Swap(address,uint256,uint256,uint256,uint256,address)" eventSwapKey := crypto.Keccak256Hash([]byte(functionSignature)).Hex() fmt.Println("eventSwapKey", eventSwapKey)
- 这里如何查看?
- 前往区块浏览器 比如这个地址[随便找的]:
注意我们查看的是https://bscscan.com/tx/0xcc77df7570e70abb743ba1dc45ee7457ebabdca1c154f4ce863a3a8e52da9bee#eventlog
Logs
不是Overview
Name就是方法名 将其拷贝下来 去掉除了类型意外所有的字符串空格,变成:
Transfer(address,address,uint256)
然后再生成key就可以了 就能和扫描出来的Topic一致
因为这个方法一般合约都是基于ERC20创建,在你根据合约sol文件生成的时候,会有这个event,所以你很轻易的就能发现你的合约里面有一个ParseTransfer
方法,
PS:
但是如果你的合约里面没有这个方法怎么办 比如我的是一个Swap,他是uniswap中的一个方法,这个时候 你就要去Name后面的那个View Source
中找到这个Event,然后Copy到你的合约中,随便找个位置丢下,然后重新生成Go文件,你就可以在你合约Go文件中找到这个ParseSwap
方法 ,传入当前匹配的Log,就能很轻松的解析出这一个数据。例如我的:-
Swap方法追踪:
-
合约中注入Swap方法
-
重新生成Go文件:
abigen --abi .\build\Token.abi --bin .\bin\Token.bin --pkg token --out Token.go
-
查看
-
这里所有的解析方法,都是有合约event事件支持的!!!
- w.instance是NewToken得到的 你可以去查看你生成的go文件 检索
Parse
关键字
- 获取调用函数签名
测试代码:
// QueryBlockInfo query block info
func (w *Web3TokenUseCase) QueryBlockInfo() error {
query := ethereum.FilterQuery{
FromBlock: big.NewInt(43****53),
ToBlock: big.NewInt(43****07),
Addresses: []common.Address{
common.HexToAddress("-------"),
common.HexToAddress("-------"),
},
//Topics: [][]common.Hash{
// //{tokenABI.Events["Transfer"].ID},
//},
}
logsList, err := w.client.FilterLogs(context.Background(), query)
color.Red("[records] %d \n", len(logsList))
if err != nil {
panic(err)
}
functionSignature := "Swap(address,uint256,uint256,uint256,uint256,address)"
eventSwapKey := crypto.Keccak256Hash([]byte(functionSignature)).Hex()
fmt.Println("eventSwapKey", eventSwapKey)
for _, logv := range logsList {
event := logv.Topics[0].Hex()
fmt.Println("event", event)
if eventSwapKey != event {
continue
}
swapInfo, err := w.instance.ParseSwap(logv)
if err != nil {
panic(err)
}
fmt.Println("== swapInfo", swapInfo)
fmt.Println("record data", logv.Data)
fmt.Println("record Address", logv.Address.Hex())
fmt.Println("record Topics", logv.Topics)
fmt.Println("record TxHash", logv.TxHash.Hex())
fmt.Println("record BlockNumber", logv.BlockNumber)
fmt.Println("record BlockNumber", logv.Index)
fmt.Println("\n\n\n\n")
}
return nil
}
后面又什么坑再分享 有帮助点个赞