Skip to content

Instantly share code, notes, and snippets.

@crazygit
Last active April 26, 2022 08:48
Show Gist options
  • Save crazygit/55f539626be6557f9db7d1c010fcd694 to your computer and use it in GitHub Desktop.
Save crazygit/55f539626be6557f9db7d1c010fcd694 to your computer and use it in GitHub Desktop.
read contract event with go ethereum
package main
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"log"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/ethclient"
)
const rawABI = `
[
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "FallbackEvent",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "ReceiveEvent",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "WithDrawEvent",
"type": "event"
},
{
"stateMutability": "payable",
"type": "fallback"
},
{
"inputs": [],
"name": "destory",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "withDraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
]
`
const ropstenHttpsEndpoint = "https://ropsten.infura.io/v3/77a8f7b1379d440b8c06e82f37d05657"
const ropstenFaucetContractAddress = "0xf1EEfEE62A8651c3772cd8D7ba9031b7029316f7"
const blockNumber = 12218203
func main() {
contractAbi, err := abi.JSON(strings.NewReader(rawABI))
if err != nil {
log.Fatal(err)
}
// get abi events info
for _, event := range contractAbi.Events {
fmt.Printf("Event Name: %s\n", event.Name)
fmt.Printf("Event ID: %s\n", event.ID)
fmt.Printf("Event RawName: %s\n", event.RawName)
fmt.Printf("Event Sig: %s\n", event.Sig)
for index, input := range event.Inputs {
fmt.Printf("input %d, Name: %s, Type:%s, indexed: %t\n", index, input.Name, input.Type, input.Indexed)
}
}
client, err := ethclient.Dial(ropstenHttpsEndpoint)
if err != nil {
log.Fatal(err)
}
contractAddress := common.HexToAddress(ropstenFaucetContractAddress)
blockLimit := big.NewInt(blockNumber)
query := ethereum.FilterQuery{
FromBlock: blockLimit,
ToBlock: blockLimit,
Addresses: []common.Address{contractAddress},
}
// query contract event in block 12218203
logs, err := client.FilterLogs(context.Background(), query)
if err != nil {
log.Fatal(err)
}
// parse logs
for _, vLog := range logs {
fmt.Printf("Log Block Number: %d\n", vLog.BlockNumber)
fmt.Printf("TxHash: %s\n", vLog.TxHash)
fmt.Printf("Topics[0]: %s\n", vLog.Topics[0].Hex())
// Topic[0] is the event signature hash value
// equals to
// logWithDrawEventSig := []byte("WithDrawEvent(address,uint256)")
// logWithDrawEventSigHash := crypto.Keccak256Hash(logWithDrawEventSig)
switch vLog.Topics[0] {
case contractAbi.Events["WithDrawEvent"].ID:
fmt.Printf("Log Name: WithDrawEvent\n")
// 解析所有Topic的信息
for index := range vLog.Topics {
fmt.Printf("topic %d: %s\n", index, vLog.Topics[index].Hex())
}
// ====================================
// decode event log data
// ====================================
// method 1:
data, errUnpack := contractAbi.Unpack("WithDrawEvent", vLog.Data)
if errUnpack != nil {
log.Fatal(errUnpack)
}
fmt.Printf("data: %s\n", data)
// method 2: decode to map
dataMap := make(map[string]interface{})
err = contractAbi.UnpackIntoMap(dataMap, "WithDrawEvent", vLog.Data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("dataMap: %v\n", dataMap)
// method 3: decode by event inputs
inputs, unpackValuesErr := contractAbi.Events["WithDrawEvent"].Inputs.UnpackValues(vLog.Data)
if unpackValuesErr != nil {
log.Fatal(unpackValuesErr)
}
fmt.Printf("inputs: %v\n", inputs)
// method 4: decode by event inputs into map
inputsMap := make(map[string]interface{})
err := contractAbi.Events["WithDrawEvent"].Inputs.UnpackIntoMap(inputsMap, vLog.Data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("inputsMap: %v\n", inputsMap)
}
fmt.Printf("\n\n")
}
}
module ReadContractEvent
go 1.18
require github.com/ethereum/go-ethereum v1.10.17
require (
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.1.2 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
)
@crazygit
Copy link
Author

This is how to parse contract log event info with the latest go-ethereum(v1.10.17).
The contract is deploy by on ropsten faucet website and the query log event is under https://ropsten.etherscan.io/tx/0x488561fb7a18bdc4627f6be2bbf3b660520ace7a5dad1de5ef1b693c6eeaf168#eventlog

Here is the output

Event Name: FallbackEvent
Event ID: 0x26875833861a2b006512a11f1b86edf95df96131040f3caeed72989ee9858083
Event RawName: FallbackEvent
Event Sig: FallbackEvent(address,uint256)
input 0, Name: from, Type:address, indexed: true
input 1, Name: amount, Type:uint256, indexed: false
Event Name: OwnershipTransferred
Event ID: 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0
Event RawName: OwnershipTransferred
Event Sig: OwnershipTransferred(address,address)
input 0, Name: previousOwner, Type:address, indexed: true
input 1, Name: newOwner, Type:address, indexed: true
Event Name: ReceiveEvent
Event ID: 0xcc85d09d309785db93d6df19917f2e6cc07fe27cd01c08c8279145deb5cf4526
Event RawName: ReceiveEvent
Event Sig: ReceiveEvent(address,uint256)
input 0, Name: from, Type:address, indexed: true
input 1, Name: amount, Type:uint256, indexed: false
Event Name: WithDrawEvent
Event ID: 0x95f64928a3a24eaef05a724d2235d5a7bd84368972737e2596b1110e117dfc65
Event RawName: WithDrawEvent
Event Sig: WithDrawEvent(address,uint256)
input 0, Name: receiver, Type:address, indexed: true
input 1, Name: amount, Type:uint256, indexed: false
Log Block Number: 12218203
TxHash: 0x488561fb7a18bdc4627f6be2bbf3b660520ace7a5dad1de5ef1b693c6eeaf168
Topics[0]: 0x95f64928a3a24eaef05a724d2235d5a7bd84368972737e2596b1110e117dfc65
Log Name: WithDrawEvent
topic 0: 0x95f64928a3a24eaef05a724d2235d5a7bd84368972737e2596b1110e117dfc65
topic 1: 0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266
data: [100000000000000000]
dataMap: map[amount:100000000000000000]
inputs: [100000000000000000]
inputsMap: map[amount:100000000000000000]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment