ERC-20 Transfer Event: Struktur, Topics und wie man es abonniert
Wie das ERC-20 Transfer Event funktioniert: seine Signatur, der Topic-Hash, wie man Logs decodiert, die Fallstricke von eth_getLogs und wie Sie Einzahlungsbenachrichtigungen erhalten, ohne Nodes zu betreiben.

Das ERC-20 Transfer-Event ist der Log, den ein Token-Vertrag jedes Mal ausgibt, wenn Token bewegt werden. Seine Signatur lautet Transfer(address indexed from, address indexed to, uint256 value), und es ist der einzige zuverlässige Weg für eine Anwendung außerhalb der Chain, um zu erfahren, dass eine Zahlung stattgefunden hat. Um es abzufangen, filtern Sie Logs nach dem Topic-Hash des Events, dekodieren Absender, Empfänger und Betrag und warten, bis der Block als sicher gilt. Dieser Leitfaden führt Sie durch jeden Schritt, die Fallen, die echtes Geld kosten, und wann es Sinn ergibt, Logs nicht mehr selbst zu pollen.
TL;DR
- Der Standard definiert
Transfer(address indexed from, address indexed to, uint256 value). Er muss bei jeder Bewegung von Token ausgelöst werden, einschließlich Transfers mit dem Wert null. - Zum Filtern von Logs verwenden Sie den Keccak256-Hash von
Transfer(address,address,uint256)als Topic 0. Topics 1 und 2 sind die gepaddetenfrom- undto-Adressen; der Betrag befindet sich im Data-Feld. eth_getLogsan öffentlichen Endpoints unterliegt Limits und kann für große Blockbereiche unvollständige Ergebnisse ohne Fehler zurückgeben. Paginieren Sie, und nutzen Sie für die Produktion dedizierte Infrastruktur.- ERC-20 besitzt keinen Callback an den Empfänger, daher ist das Off-Chain-Listening nicht optional, wenn Sie Nutzer-Guthaben gutschreiben.
- Wenn Sie keine Log-Indexer betreiben möchten, kann ein Webhook-Service dekodierte Transfer-Benachrichtigungen an Ihr Backend pushen.
Inhaltsverzeichnis
- Was das Transfer-Event tatsächlich ist
- Anatomie eines Transfer-Logs
- Transfers mit eth_getLogs lesen
- Bestätigungen, Reorgs und Idempotenz
- Warum Sie sich nicht auf den Empfänger verlassen können
- Edge Cases, die naive Listener brechen
- Selbst bauen oder kaufen: eigenen Listener betreiben
- Perspektive: Was wir sehen, wenn Teams Einzahlungserkennung bauen
- Transfer-Benachrichtigungen erhalten, ohne Indexer zu betreiben
- Ein minimaler Handler, Schritt für Schritt
- FAQ
- Quellen
Was das Transfer-Event tatsächlich ist
Ein Smart Contract kann Events ausgeben, die als Signale in den Transaktions-Receipts als Logs geschrieben werden. Sie werden nicht im Contract State gespeichert, daher sind sie günstig zu schreiben und günstig zu lesen, aber ein Contract kann sie nachträglich nicht lesen. Ihre Zielgruppe ist die Außenwelt: Wallets, Block Explorer, Indexer und Ihr Backend. Ethereums eigenes Tutorial zu Events beschreibt sie als Signale, auf die dApps und alles, was mit der JSON-RPC API verbunden ist, hören und reagieren können.

Für Token definiert die ERC-20-Spezifikation das Event wie folgt:
event Transfer(address indexed _from, address indexed _to, uint256 _value)Die Regeln, die in der Praxis zählen:
- Es MUSS ausgelöst werden, wenn Token übertragen werden, und das schließt Übertragungen mit dem Wert null ein.
- Die Funktion
transfermuss es auslösen, und ebensotransferFrom, die Funktion, die ein Spender nach Erteilung einer Erlaubnis verwendet. - Beim Minting wird erwartet, dass es mit der
from-Adresse auf die Null-Adresse gesetzt wird, ausgelöst wird. Beim Burning spiegelt sich dies wider, wobei die Null-Adresse der Empfänger ist (viele Implementierungen folgen dieser Konvention).
Dieser letzte Punkt ist eine häufige Fehlerquelle. Ein Listener, der nur „Übertragungen an meine Adresse“ überwacht, verhält sich korrekt, aber einer, der jeden Transfer als Zahlung von Benutzer zu Benutzer behandelt, wird Mints und Burns falsch interpretieren.
Der Token-Kontostand ist das, was on-chain zählt, und das Event ist ein Bericht darüber. Wenn Sie den Hintergrund zur vollständigen Schnittstelle wünschen, behandeln wir dies in unserem Beitrag zum ERC-20-Token-Standard.
Anatomie eines Transfer-Logs
Wenn das Event ausgelöst wird, speichert der Knoten ein Log mit drei Teilen: der Adresse des auslösenden Vertrags, einer Liste von Topics und einem Data-Blob. Die Indizierung entscheidet, wo jedes Argument landet.
| Log-Feld | Inhalt für einen ERC-20 Transfer |
|---|---|
address | Der Token-Vertrag, der das Event ausgelöst hat (z. B. ein Stablecoin-Vertrag) |
topics[0] | Hash der Event-Signatur |
topics[1] | Sender (from), links auf 32 Bytes aufgefüllt |
topics[2] | Empfänger (to), links auf 32 Bytes aufgefüllt |
data | Der value, ein 32-Byte-Integer ohne Vorzeichen |
Die beiden Adressen sind indiziert, daher sind sie über den Log-Filter durchsuchbar. Der Wert ist nicht indiziert, daher wird er im Data-Feld gespeichert, was die On-Chain-Kosten niedrig hält und bedeutet, dass Sie auf Knotenebene nicht nach Betrag filtern können. Wenn Sie „Übertragungen über 1.000 Token“ benötigen, rufen Sie die Daten ab und filtern in Ihrem eigenen Code.
Der Topic-0-Hash
Für Abfragen über JSON-RPC benötigen Sie den Keccak256-Hash der kanonischen Signatur-Zeichenkette Transfer(address,address,uint256). Keine Leerzeichen, keine Parameternamen, kein indexed-Schlüsselwort. Das Ergebnis lautet:
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efDie ethers.js Events-Dokumentation verwendet denselben Mechanismus: Topic 0 ist der Signatur-Hash, und Topics 1 und 2 entsprechen den indizierten from- und to-Adressen, jeweils auf 32 Bytes aufgefüllt.
Zwei Details sparen Debugging-Zeit:
- Dezimalstellen sind Ihre Aufgabe. Der
valueist ein roher Integer. Ein Token mit 6 Dezimalstellen und einem Wert von2500000entspricht 2,5 Token. Lesen Siedecimals()vom Vertrag (oder cachen Sie es pro Token), bevor Sie Beträge anzeigen. - Derselbe Hash, unterschiedliche Standards. ERC-721 verwendet denselben Event-Namen und dieselben Argumenttypen, daher ist sein Topic 0 identisch. Der Unterschied besteht darin, dass die Token-ID indiziert ist, sodass ein NFT-Transfer-Log vier Topics und ein leeres Data-Feld enthält, während ein fungibler Transfer drei Topics aufweist. Prüfen Sie die Topic-Anzahl vor dem Decodieren, andernfalls werden Sie NFT-Bewegungen als Token-Zahlungen interpretieren. Unser Beitrag zum ERC-721-Standard behandelt diese Seite.
Transfers mit eth_getLogs lesen
Der klassische Ansatz ist ein direkter JSON-RPC-Aufruf. Ein Filter, der alle Transfers eines Tokens in eine Wallet findet, sieht wie folgt aus:
{ "method": "eth_getLogs", "params": [{ "fromBlock": "0x10d4f00", "toBlock": "0x10d4f64", "address": "0xTokenContractAddress", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", null, "0x000000000000000000000000YourDepositAddressWithoutThe0x" ] }]}Ein null an einer Topic-Position bedeutet „jeder Wert“. Hier akzeptieren wir jeden Absender und legen den Empfänger fest. Beachten Sie, dass der Empfänger mit Nullen auf 32 Bytes aufgefüllt wird.
Wenn Sie eine Bibliothek bevorzugen, zeigt eine kurze Anleitung wie dieser web3.py Gist für ERC-20 Transfer-Logs denselben Aufruf, eingebettet in Python. Für Live-Updates anstelle von Historie sendet eth_subscribe mit dem Typ logs neue Treffer über einen WebSocket.
Wo eth_getLogs Sie beißt
Es sieht einfach aus und funktioniert in einem Tutorial. In der Produktion ist es anders. Der SQD-Artikel zu eth_getLogs-Limits weist darauf hin, dass Standard-Node-Anbieter die Anzahl der zurückgegebenen Logs oft begrenzen und dass die Abfrage eines großen Blockbereichs unvollständige Daten liefern kann, ohne dass ein Fehler auftritt. Ihre Empfehlung: Anfragen paginieren und für historische Daten Archive-Nodes verwenden. Derselbe Artikel warnt davor, sich für schwere Produktionslast auf öffentliche Endpunkte zu verlassen, da dies aufgrund von Bloom-Filter-Beschränkungen und Index-Lücken, die von Node zu Node variieren, unzuverlässig ist.
Die praktischen Regeln:
- Kleine Blockfenster abfragen und vorwärtsgehen, anstatt einen riesigen Bereich auf einmal anzufordern.
- Die Anzahl der Ergebnisse mit dem vergleichen, was Sie erwarten. Eine stille Abschneidung sieht genau aus wie ein ruhiger Tag.
- Die letzte verarbeitete Blocknummer speichern, damit ein Neustart dort fortgesetzt wird, wo er aufhörte, anstatt Blöcke zu überspringen.
- Bei jedem Durchlauf eine Überlappung von wenigen Blöcken beibehalten und anhand von Transaktionshash plus Log-Index deduplizieren.
Bestätigungen, Reorgs und Idempotenz
Ein Log, der im neuesten Block erscheint, ist nicht final. Die Kette kann sich reorganisieren, und ein Block, der Ihren Transfer enthielt, kann durch einen ersetzt werden, der dies nicht tut. Eine solide Einzahlungs-Pipeline behandelt das Ereignis als Behauptung, nicht als Tatsache, bis genügend Blöcke darauf aufgebaut wurden.
Eine einfache Zustandsmaschine funktioniert gut:
- Gesehen. Der Log wird erkannt. Ihn aufzeichnen, dem Nutzer „ausstehend“ anzeigen und nichts gutschreiben.
- Bestätigt. Der Block ist älter als Ihr gewählter Schwellenwert. Den Betrag einmal gutschreiben.
- Verwaist. Der Log verschwand nach einer Reorg. Den Datensatz als ungültig markieren und alle informieren, die es wissen müssen.
Der Schwellenwert ist eine Geschäftsentscheidung. Ein kleiner Kauf verträgt weniger Bestätigungen als eine große, auszahlungsberechtigte Einzahlung. Wählen Sie ihn pro Kette und pro Betrag und dokumentieren Sie ihn.
Was auch immer Sie wählen, machen Sie die Gutschreibung idempotent. Der eindeutige Schlüssel für einen Log ist der Transaktionshash plus der Log-Index, nicht der Transaktionshash allein, da eine Transaktion mehrere Transfer-Ereignisse auslösen kann (ein Swap löst beispielsweise mindestens zwei aus). Wenn Ihr Handler dasselbe Ereignis zweimal empfängt, durch einenRetry oder eine zweite Quelle, darf er beim zweiten Mal nichts tun.
Warum Sie sich nicht darauf verlassen können, dass der Empfänger es bemerkt
ERC-20-Übertragungen sind von der empfangenden Seite aus stumm. Eine Wallet-Adresse führt keinen Code aus, und ein empfangender Vertrag wird nicht benachrichtigt. Die ethereum.org ERC-20-Seite weist darauf hin, dass Token verloren gehen, wenn sie an Verträge gesendet werden, die die eingehende Übertragung nicht erkennen, da der Standard keinen nativen Callback vorsieht, und gibt an, dass bis zum 20. Juni 2024 ERC-20-Token im Wert von über 83.656.418 $ auf diese Weise verloren gegangen waren. Eine gängige Abhilfe ist eine require-Prüfung im Token, die das Senden an den Token-Vertrag selbst blockiert.
Zwei Erkenntnisse für Entwickler:
- Wenn Sie einen Vertrag betreiben, der Token empfangen soll, benötigen Sie eine eigene Buchhaltung. Standards wie ERC-1363 Hooks existieren dafür, aber Sie können nicht davon ausgehen, dass der Token des Absenders diese unterstützt.
- Wenn Sie ein Backend betreiben, ist das Transfer-Log Ihr einziger Trigger. Fehlt eines, hat ein Kunde gezahlt und Sie haben es nie erfahren.
Es gibt eine zweite Lücke: Das Ereignis enthält keine Zahlungsreferenz. Nichts verknüpft eine Übertragung mit Rechnung 4471. Die meisten Unternehmen lösen dies, indem sie jeder Rechnung oder jedem Nutzer eine einzigartige Einzahlungsadresse zuweisen. Ein neuerer Vorschlag, ERC-7699, würde ERC-20 um eine Transfer-Referenz erweitern, sodass eine Nachricht für den Empfänger mit der Zahlung mitreist, aber es ist ein Vorschlag und die heutigen populären Token implementieren ihn nicht.
Edge Cases, die naive Listener brechen
Native-Style-Token. Auf manchen Chains ist ein Stablecoin in das Protokoll eingebaut, anstatt ein normaler Vertrag zu sein. Die Arc-Dokumentation zum Erkennen von Einzahlungen erklärt, dass native USDC-Bewegungen dort ein standardmäßiges ERC-20-Transfer-Log von einer Systemadresse ausgeben, sodass Entwickler nach diesem Emitter filtern, anstatt nach dem individuellen Token-Vertrag. Die Lektion ist allgemein: Lesen Sie die Einzahlungs-Dokumentation jeder Chain, bevor Sie annehmen, dass ein Vertragsadress-Filter ausreicht.
Fee-on-Transfer- und Rebasing-Token. Der Betrag im Ereignis kann von dem abweichen, um den sich das Guthaben des Empfängers ändert, oder Guthaben können sich ohne jegliches Transfer-Ereignis verschieben. Wenn Sie unbekannte Token akzeptieren, gleichen Sie mit balanceOf ab, anstatt dem Ereignis allein zu vertrauen.
Nullwert-Übertragungen. Der Standard verlangt, dass sie das Ereignis ausgeben. Angreifer nutzen dies für Address Poisoning, indem sie Nullwert-Übertragungen senden, die eine ähnlich aussehende Adresse in der Historie des Opfers platzieren. Ignorieren Sie Nullwert-Logs in jedem Einzahlungs-Flow.
Gefälschte Token. Jeder kann einen Vertrag bereitstellen, der ein Transfer-Ereignis mit einem beliebigen Token-Namen ausgibt. Filtern Sie nach Vertragsadressen, die Sie erkennen, nicht nur nach Topic 0.

Andere Chains. Die gleiche Ereignisstruktur erscheint auf EVM-kompatiblen Netzwerken wie Polygon, BNB Chain (BEP-20) und Arbitrum. TRONs TRC-20-Token folgen dem gleichen Prinzip mit ihren eigenen Werkzeugen; siehe unseren Vergleich von TRC10 und TRC20, wie sie sich unterscheiden.
Selber bauen oder kaufen: Betrieb des eigenen Listeners
Ein selbstgebauter Listener ist ein gutes Projekt und eine faire Wahl, wenn Blockchain-Daten Ihr Kernprodukt sind. Für die meisten Teams, die Zahlungen akzeptieren, ist es ein Nebenprojekt mit einem langen Wartungsschwanz. Sie besitzen den Node oder den Provider-Vertrag, den Block-Cursor, das Reorg-Handling, die Retries, das Decoding für jeden Token und den gleichen Stack erneut für jede zusätzliche Chain.
Eine grobe Entscheidungsgrundlage:
| Frage | Wenn ja, eher selbst bauen | Wenn nein, eher API nutzen |
|---|---|---|
| Sind On-Chain-Daten Ihr Produkt? | Ja | Nein |
| Benötigen Sie benutzerdefinierte Log-Analysen, die über Zahlungen hinausgehen? | Ja | Nein |
| Haben Sie einen Entwickler, der für die Knotenverfügbarkeit und Reorg-Logik verantwortlich ist? | Ja | Nein |
| Unterstützen Sie von Tag eins an mehrere Ketten? | Nein | Ja |
Wenn Sie in der rechten Spalte landen, entfernt eine verwaltete API, die dekodierte Events an Sie sendet, die gesamte Indexierungsschicht.
Perspektive: Was wir sehen, wenn Teams Einzahlungserkennung bauen
Wir entwickeln eine einheitliche API für Krypto-Zahlungen, daher sehen wir immer wieder dasselbe Muster. Ein Team beginnt mit einer eth_getLogs-Schleife für einen Token auf einer Kette. Es funktioniert. Dann fügen sie eine zweite Kette, einen zweiten Token-Standard, einen Retry-Job und einen Reorg-Patch hinzu, und das Zahlungsfeature ist stillschweigend zu einem Infrastrukturprojekt geworden.
Unsere Sichtweise ist, dass das Transfer-Event die richtige Primitivkomponente ist, aber der falsche Ort, um Ihre Entwicklungszeit zu investieren. Was Ihre Anwendung braucht, ist eine klare Aussage: Diese Adresse hat diesen Betrag dieses Tokens in dieser Transaktion erhalten. Deshalb liefern wir vordekodierte Daten statt roher Topics, und Benachrichtigungen treffen über Webhooks ein, die HMAC-signiert sind, damit Ihr Server verifizieren kann, dass eine Nachricht wirklich von uns stammt, bevor er gutschreibt. Wir vertreten auch die Ansicht, dass Sie Ihre eigenen Knoten nicht betreiben oder chain-spezifische Endpoints jonglieren sollten, um dorthin zu gelangen.
Der Rat, den wir unabhängig vom Tooling geben: Verwenden Sie pro Zahler oder Rechnung eine Einzahlungsadresse, buchen Sie idempotent, warten Sie auf Bestätigungen, die dem Betrag auf dem Spiel entsprechen, und verifizieren Sie die Token-Vertragsadresse. Diese vier Gewohnheiten verhindern die meisten der Vorfälle, von denen wir hören.
— Bitblade
Transfer-Benachrichtigungen erhalten, ohne Indexer zu betreiben
Chaingateway bietet Entwicklern eine einzige REST-API für Wallets, Token-Transfers und dekodierte Transaktionsdaten über Ethereum, Bitcoin, Tron, Solana, Polyggon, BNB Chain und Arbitrum. Für dieses Thema ist der relevante Teil die Chaingateway Webhooks: Sie abonnieren eine Adresse, und wenn ein Token-Transfer diese bertrifft, erreicht eine Echtzeit-Benachrichtigung Ihren Endpoint mit den bereits dekodierten Daten, sodass Sie Topic-Hashing und Padding überspringen. Unsere Ethereum API zeigt, wie man ERC-20-Token über REST ohne web3.js sendet, und der ERC-20-Adressenleitfaden behandelt Adressformat und Guthabenabfragen.
Pläne sind auf der Preisseite veröffentlicht: Plus kostet 49 € pro Monat, Pro 99 €, Premium 249 € und Enterprise 499 € pro Monat, bei jährlicher Abrechnung 490 €, 990 €, 2.490 € und 4.990 € entsprechend. Der Zugriff auf die Blockchain API beginnt mit einer kostenlosen Testphase.
Ein minimaler Handler, Schritt für Schritt
Ob Sie rohe Logs oder Webhooks nutzen, die serverseitige Logik ist dieselbe.
- Quelle verifizieren. Bei Webhooks die HMAC-Signatur des rohen Anfragekörpers prüfen, bevor dieser geparst wird. Für den eigenen Log-Reader vertrauen Sie bereits Ihrem Knoten.
- Token prüfen. Die Vertragsadresse mit Ihrer Allowlist vergleichen.
- Empfänger prüfen. Die
to-Adresse in Ihrer Datenbank der Einzahlungsadressen nachschlagen. Alles Unbekannte ignorieren. - Rauschen ausfiltern. Nullwert-Transfers sowie Mints oder Burns, die Sie nicht interessieren, verwerfen.
- Deduplizieren. Transaktions-Hash und Log-Index unter einer Unique-Constraint einfügen. Schlägt der Insert fehl, abbrechen.
- Betrag umrechnen. Den Rohwert durch 10 hoch der Dezimalstellen des Tokens teilen, dabei Ganzzahl- oder Dezimaltypen verwenden, niemals Gleitkomma.
- Als ausstehend, dann als bestätigt buchen. Erst gutschreiben, nachdem Ihre Bestätigungsschwelle überschritten ist.
- Schnell antworten. Einem Webhook sofort mit einem Erfolgsstatus quittieren und die schwere Arbeit in eine Queue legen.
Quellen
- ERC-20: Token Standard (EIP-20)
- ERC-20 Token Standard | ethereum.org
- Logging data from smart contracts with events | ethereum.org
- Events | ethers.js documentation
- eth_getLogs: Limits, Pagination, and the Logs It Leaves Out | SQD
- ERC-7699: ERC-20 Transfer Reference Extension
- Detect and process deposits | Arc Docs
- Use web3.py to get ERC-20 transfer logs for a specific account
Empfohlen
Häufig gestellte Fragen
Es ist der keccak256-Hash von Transfer(address,address,uint256), nämlich 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. Er steht immer in Topic 0 des Logs. Topic 1 und 2 enthalten Absender und Empfänger.
Indizierte Argumente werden zu Topics, die Knoten durchsuchen können, aber jedes erhöht die Log-Kosten, und der Standard indiziert nur die beiden Adressen. Der Wert landet im Data-Feld, daher müssen Sie ihn selbst dekodieren und Beträge im eigenen Code filtern.
Der Standard verlangt dies, auch für Nullwert-Transfers. In der Praxis tun dies konforme Verträge, aber nicht-standardisierte Tokens können sich anders verhalten, und manche Ketten behandeln native Assets speziell. Behandeln Sie das Event als Hauptsignal und gleichen Sie bei unbekannten Tokens gegen balanceOf ab.
Nur mit Vorsicht. Anbieter können die zurückgegebenen Logs begrenzen, und große Bereiche können unvollständige Daten ohne Fehlermeldung liefern. In kleinen Fenstern paginieren, den letzten verarbeiteten Block verfolgen und für alles, was echtes Geld bewegt, dedizierte Infrastruktur oder einen Benachrichtigungsdienst nutzen.
Es gibt keine universelle Zahl. Es hängt von der Kette, dem Betrag und Ihrer Risikotoleranz ab. Pro Kette und Wertstufe eine Schwelle festlegen und erst gutschreiben, nachdem diese überschritten ist.
Möchten Sie das selbst umsetzen? API-Key erhalten — 7 Tage kostenlos testen, keine Karte nötig — oder werfen Sie einen Blick auf Blockchain-API für die vollständige Endpoint-Referenz.