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") } }