Ich hole die Protokolle mit client.SubscribeFilterLogs
. Die Ereignisparameter sind in codiert types.Log.Data
. Wie kann ich es entschlüsseln go
?
Das go-ethereum abi- Paket hat im Oktober 2017 das Update zum Entpacken der Ereignisausgabe erhalten. Anfangs war es nur möglich, die Methodenausgabe zu entpacken.
Alle Funktionen werden über das abi.ABI
Objekt bereitgestellt. Um es zu verwenden, benötigen Sie Event ABI (JSON-String). Verwenden Sie dann func (abi *ABI) UnmarshalJSON , um das ABI
Objekt zu erstellen. Von dort aus können Sie die Unpack
Methode using Data
aus Ihrem Protokollobjekt verwenden.
Denken Sie daran, dass indizierte Attribute Topic
eher in log als in Data
.
Für weitere Nutzungsdetails können Sie diesen Beispielen folgen:
HINWEIS: In der aktuellen Implementierung (2017-11-29) gibt es einen Fehler mit indizierten Attributen. Ich habe dafür eine PR eingereicht und warte immer noch auf die endgültige Genehmigung.
Hier ist ein vollständiges Codebeispiel für alle, die immer noch verwirrt sind (dank der Antwort von @Robert Zaremba).
package main
import (
"context"
"log"
"math/big"
"strings"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/myorg/myrepo/go-contracts/token"
"github.com/ethereum/go-ethereum/core/types"
)
func main() {
contractAddress := common.HexToAddress("0x0d8775f648430679a709e98d2b0cb6250d2887ef")
query := ethereum.FilterQuery{
Addresses: []common.Address{contractAddress},
}
var ch = make(chan types.Log)
ctx := context.Background()
sub, err := Client.SubscribeFilterLogs(ctx, query, ch)
if err != nil {
log.Fatal(err)
}
tokenAbi, err := abi.JSON(strings.NewReader(string(token.TokenABI)))
if err != nil {
log.Fatal(err)
}
for {
select {
case err := <-sub.Err():
log.Fatal(err)
case eventLog := <-ch:
var transferEvent struct {
From common.Address
To common.Address
Value *big.Int
}
err = tokenAbi.Unpack(&transferEvent, "Transfer", eventLog.Data)
if err != nil {
log.Println("Failed to unpack")
continue
}
transferEvent.From = common.BytesToAddress(eventLog.Topics[1].Bytes())
transferEvent.To = common.BytesToAddress(eventLog.Topics[2].Bytes())
log.Println("From", transferEvent.From.Hex())
log.Println("To", transferEvent.To.Hex())
log.Println("Value", transferEvent.Value)
}
}
}
burn
oder mint
, woher wissen Sie also im Voraus, welche Art von Ereignis Sie entpacken müssen?keccak256(eventName(arg1,arg2))
Wenn es sich also um ein Übertragungsereignis handelt, ist Thema[0] keccak256(Transfer(address,address,uint256))
=> ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
. Kurz gesagt: Sie kennen den Ereignistyp, indem Sie nach Thema[0] filtern, das der Hash der Ereignissignatur ist. Sehen Sie sich diese Ethereum-Entwicklung mit Go-Leitfaden für Beispiele an goethereumbook.orgkeccak256(Transfer(address,address,uint256))
=>ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
keccak256(Approval(address,address,uint256))
=>8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925
geth
Version mit diesem Code verwendet wurde?Version: 1.8.10-stable
So habe ich es mit dem ABI gemacht:
path, _ := filepath.Abs("./resources/etherdelta.abi")
file, err := ioutil.ReadFile(path)
if err != nil {
fmt.Println("Failed to read file:", err)
}
edabi, err := abi.JSON(strings.NewReader(string(file)))
if err != nil {
fmt.Println("Invalid abi:", err)
}
var orderStruct struct {
TokenGet common.Address
AmountGet *big.Int
TokenGive common.Address
AmountGive *big.Int
Expires *big.Int
Nonce *big.Int
User common.Address
}
err = edabi.Unpack(&orderStruct, "Order", log.Data)
if err != nil {
fmt.Println("Failed to unpack:", err)
}
fmt.Println("TokenGet:", orderStruct.TokenGet.Hex())
fmt.Println("AmountGet:", orderStruct.AmountGet.Hex())
data := common.TrimLeftZeroes(log.Data)
hex := common.Bytes2Hex(data)
hex = TrimLeftZeroes(hex)
if hex != "" {
erc20Amount, err := hexutil.DecodeBig("0x" + hex)
}
func TrimLeftZeroes(hex string) string {
idx := 0
for ; idx < len(hex); idx++ {
if hex[idx] != '0' {
break
}
}
return hex[idx:]
}
Robert Zaremba