Anfang dieses Jahres haben wir ein Gesamtzahlungsvolumen von 1 Milliarde US-Dollar in Stablecoins überschritten. Zum Vergleich: Unsere erste Stablecoin-Transaktion haben wir vor weniger als 12 Monaten abgewickelt. Es begann damit, dass eine Handvoll Kunden etwas verlangten, das eigentlich ganz einfach sein sollte: die Möglichkeit, Stablecoin-Zahlungen von ihren Kunden auf der ganzen Welt zu empfangen und diese Gelder in US-Dollar abrechnen- schnell und vorhersehbar, ohne dass man mit Gebühren überhäuft wird. Bestehende Off-Ramp-Lösungen bedeuteten Gebühren von 1-3 %, mehrtägige Abwicklung und unglaublich lange und frustrierende Compliance-Prozesse. Wir sahen eine Chance und entwickelten innerhalb von zwei Wochen ein MVP. Innerhalb eines Monats hatten wir ein echtes und bedeutendes Volumen.
Die Herausforderung bestand darin, es zu skalieren.
Stablecoins werden innerhalb von Sekunden abgewickelt, überall und jederzeit. Traditionelle Bankensysteme sind dafür nicht ausgelegt – sie basieren auf Stapelverarbeitung, Geschäftstag-Cutoffs und mehrtägigen Abwicklungsfenstern. Ein Kunde in Singapur sendet Ihnen um 2 Uhr morgens an einem Samstag 50.000 US-Dollar in USDC. In der Blockchain wird die Zahlung innerhalb von Sekunden abgewickelt. Die ACH-Überweisung auf Ihr Bankkonto wird jedoch erst am Montag veranlasst, kommt erst am Mittwoch an und wird möglicherweise irgendwo dazwischen geprüft. Um diese beiden Welten zu verbinden, müssen Systeme koordiniert werden, die nie dafür ausgelegt waren, miteinander zu kommunizieren, und die jeweils ihren eigenen Status haben.
Dieser Beitrag befasst sich mit den beiden Infrastruktur-Primitiven, die wir entwickelt haben, damit sich Stablecoins wie Geldbewegungen im Bankwesen verhalten:
1. GeldflussEine deklarative Orchestrierungs-Engine für lang andauernde, multisystemische Finanz-Workflows.
2. Unser On-Chain-AusführungsframeworkEin Lebenszyklusmodell für zuverlässige On-Chain-Operationen
Alles andere – Ausfahrten, Auffahrten und unsere nicht-verwahrenden Global-USD-Konten – wird durch die Zusammensetzung dieser Grundelemente aufgebaut. Wenn Sie eine Sache aus diesem Beitrag mitnehmen: Stablecoins sind einfach; Stablecoin Bankwesen ist nicht.
Geldfluss
Wenn Sie Geld über mehrere externe Systeme transferieren, benötigen Sie mehr als nur eine Ad-hoc-Koordination. Sie benötigen eine Möglichkeit, den gesamten Ablauf deklarativ darzustellen: Was soll passieren, als Reaktion auf welche Ereignisse und mit welchen Garantien? Und dieser Ablauf muss überprüfbar, wiederaufnehmbar und korrekt sein, selbst wenn Schritte während des Transfers fehlschlagen. Genau das bietet uns Flow of Funds.
Das Problem mit Geldbewegungen
Die meisten Herausforderungen bei der Orchestrierung von Software bestehen darin, Fehler elegant zu behandeln. Die finanzielle Orchestrierung unterliegt einer strengeren Einschränkung: Das Geld ist bereits in Bewegung..
Betrachten wir einen sofortigen Einzahlungsfluss. Ein Kunde erhält 10.000 USDC. Wir schreiben diesen Betrag sofort seinem Konto gut (noch bevor die zugrunde liegende ACH-Zahlung abgewickelt ist), sodass er dieses Kapital sofort einsetzen kann. Hinter den Kulissen haben wir einen Kredit vergeben. Wenn die ACH-Zahlung einige Tage später eintrifft, ziehen wir die Rückzahlung und die Gebühren ein.
Das sind vier Vorgänge über zwei externe Systeme hinweg: Krypto-Liquidation, Darlehensauszahlung, ACH-Abrechnung, Gebühreneinzug. Jeder Schritt hängt vom vorherigen ab, und jeder Schritt kann fehlschlagen. Mit verstreuten Zuständen und Ad-hoc-Handlern lässt sich das nicht bewältigen.
Die Kernabstraktion
Flow of Funds ist ein deklaratives, regelbasiertes Orchestrierungssystem. Die Kernabstraktion besteht aus drei Teilen:
Veranstaltungen sind Signale, dass etwas passiert ist – eine ACH-Zahlung wurde abgewickelt, Gelder wurden empfangen, eine Kartenautorisierung wurde erfasst usw. Ereignisse können aus externen Systemen stammen oder intern ausgelöst werden.
Regeln Definieren Sie, was als Reaktion auf Ereignisse geschehen soll. Jede Regel legt eine Liste von auslösenden Ereignissen und eine Abfolge von auszuführenden Nebenwirkungen fest.
Nebenwirkungen sind die Maßnahmen, die wir als Reaktion auf das Ereignis ergreifen: eine Überweisung initiieren, eine Sperre einrichten, einen Kredit auszahlen, eine Gebühr einziehen. Eine Regel wird einmal ausgelöst. Sobald ein passendes Ereignis eintrifft, werden die Nebenwirkungen der Reihe nach ausgeführt und die Regel wird verbraucht. Dies garantiert Idempotenz innerhalb des Flusskontexts.
Warum deklarativ?
Die Alternative ist eine zwingende Orchestrierung: Handler rufen Handler auf, der Status ist über Tabellen verstreut, der „Fluss“ existiert nur in der impliziten Koordination zwischen Code-Teilen.
Das funktioniert bei einfachen Abläufen. Bei mehrtägigen, systemübergreifenden Finanzoperationen mit Compliance-Sperren und Teilausfällen wird es jedoch unhaltbar. Die Fehlerbehandlung erfolgt ad hoc. Wiederherstellungspfade sind implizit. Sechs Monate später kann niemand mehr mit Sicherheit beantworten, was passiert, wenn Schritt 3 nach erfolgreichem Abschluss von Schritt 2 fehlschlägt.
Deklarative Regeln kehren das Modell um. Sie definieren die Zustandsmaschine explizit: diese Ereignisse lösen aus diese Aktionen. Die Orchestrierungs-Engine übernimmt die Ausführung, Persistenz und Wiederherstellung. Der Ablauf ist die Dokumentation.
Garantien
FoF gibt uns vier Invarianten, auf die wir uns verlassen können:
1. Idempotenz – Eine Regel wird genau einmal pro Flusskontext ausgelöst, unabhängig von doppelten Ereignissen oder Wiederholungsversuchen.
2. Deterministische Abstimmung – Bei gleichen Ereignissen führt der Ablauf zum gleichen Zustand.
3. Vollständige Überprüfbarkeit – Jede Nebenwirkung wird bis zum auslösenden Ereignis zurückverfolgt.
4. Kombinierbarkeit – Komplexe Abläufe entstehen aus einfachen Regeln, die sich zu einem Ganzen zusammenfügen, ohne monolithisch zu werden.
Ausführungsverfolgung
Wir verfolgen jede Ausführung von Nebenwirkungen über Node-Datensätze, die jeweils mit ihrem übergeordneten Datensatz verknüpft sind und so einen vollständigen Ausführungsbaum bilden. Wenn Compliance-Anforderungen einen Prüfpfad erfordern, können wir den genauen Weg durch das System nachverfolgen.
Kombinierbarkeit: Verschachtelte Regeln
Regeln können Unterregeln generieren. Auf diese Weise lassen sich komplexe, mehrstufige Abläufe zusammenstellen, ohne dass sie monolithisch werden. Wenn eine Off-Ramp-Transaktion erstellt wird, versucht die ursprüngliche Regel nicht, alles zu verarbeiten. Sie richtet lediglich Zukunft Regeln – Zuhörer, die auf Ereignisse warten, die später eintreten werden:
Die Abrechnungslogik existiert nicht als toter Code, der darauf wartet, aufgerufen zu werden. Sie existiert als Regel, die auf ihr Ereignis wartet. Wenn der Webhook des Bankdienstleisters einige Tage später eintrifft, wird die Regel ausgelöst und der Ablauf wird fortgesetzt. Die übergeordnete Regel wird verarbeitet und die untergeordnete Regel führt den Kontext weiter.
Das bedeutet auch, dass Abläufe beliebig kombinierbar sind. Möchten Sie Sofortüberweisungen implementieren? Kein Problem. Fügen Sie einfach eine Regel hinzu, die den Kredit ausbezahlt und Rückzahlungsregeln festlegt. Jeder Vorgang ist für sich isoliert, aber alle zusammen bilden einen kohärenten Ablauf.
Nebenwirkungsausführungskontexte
Nicht alle Nebenwirkungen sind gleich. Einige müssen atomar mit der Datenbanktransaktion sein. Einige rufen externe APIs auf. Einige sind Fire-and-Forget.
Die Auszahlung
Der größte Vorteil besteht darin, wie FoF die Art und Weise verändert, wie Ingenieure bei Slash Orchestrierungscode schreiben. Ohne FoF löst jeder Ingenieur dieselben Probleme auf unterschiedliche Weise. Jeder erfindet das Rad neu, und die Räder haben alle leicht unterschiedliche Formen.
FoF erhöht die Mindestanforderungen. Sie definieren was sollte geschehen, nicht wie um jeden Fehlermodus zu behandeln. Das Framework kümmert sich um die Ausführung, Persistenz und Beobachtbarkeit. Neue Ingenieure können eine Flussdefinition lesen und verstehen, ohne mehrere Schichten imperativen Codes durchgehen zu müssen. Und es ist schwieriger, schlechten Orchestrierungscode zu schreiben, wenn die Abstraktion Sie dazu zwingt, Ereignisse, Nebenwirkungen und Zustandsübergänge explizit anzugeben.
Rampen: FoF in der Praxis
Mit FoF als Grundlage für die Zusammenstellung von Finanzströmen ging es bei der Entwicklung unserer Kernprodukte darum, die richtigen Regeln für jeden einzelnen Strom zu definieren. Die Abstraktion kümmert sich nicht darum, welche Systeme am anderen Ende stehen, sondern koordiniert lediglich.
Aus- und Auffahrten sind „Abläufe“, die von dieser Engine koordiniert werden und ein neues externes System einführen: einen Krypto-Anbieter (oder OTC-Desk), der Stablecoin-/Fiat-Umrechnungen abwickelt. Wie jedes externe System liefern sie Statusaktualisierungen nach ihren eigenen Bedingungen, die wir zum Auslösen von FoF-Ereignissen verwenden können. Von dort aus handelt es sich lediglich um eine Zusammenstellung von Abläufen.
Ausfahrten
Über Auszahlungsoptionen können Kunden Zahlungen in Stablecoins erhalten und diese als USD in ihrem Slash-Konto abrechnen. Der Ablauf ist ganz einfach:
- Der Kunde erhält USDC oder USDT an einer Einzahlungsadresse, die wir über unseren Krypto-Anbieter generieren.
- Der Anbieter erkennt die Einzahlung, liquidiert sie in USD und initiiert eine ACH- oder Überweisung.
- Unser Bankdienstleister erhält die eingehende Überweisung.
- Wir gleichen die Überweisung mit der ursprünglichen Transaktion ab und schreiben den Betrag dem Konto gut.
Bei Sofortüberweisungen – bei denen wir dem Kunden den Betrag sofort gutschreiben und die Rückzahlung einziehen, sobald die ACH-Zahlung abgewickelt ist – umfasst der Ablauf die Auszahlung des Darlehens, den Einzug der Rückzahlung und die Erfassung der Gebühren. Jeder Vorgang ist eine separate Regel, die auf ihr Ereignis wartet und zu einem einzigen zusammenhängenden Ablauf zusammengefügt wird. Die FoF-Definition sieht in etwa so aus:
Auffahrten
On-Ramps sind das Gegenteil: Kunden senden USD von ihrem Slash-Konto und erhalten Stablecoins in einer externen Wallet. Der Ablauf:
- Der Kunde initiiert eine Überweisung an eine Ziel-Wallet-Adresse.
- Wir erstellen auf ihrem Konto einen Betrag in Höhe des Betrags zuzüglich Gebühren.
- Wir senden eine ACH- oder Überweisung an eine Einzahlungsanweisung bei unserem Krypto-Anbieter.
- Der Anbieter erhält die Gelder und liefert Stablecoins an den Bestimmungsort.
Bemerkenswert ist, wie wenig neue Infrastruktur dafür erforderlich war. Das FoF-Framework und die Abstimmungslogik, die wir für Off-Ramps entwickelt haben, konnten direkt übernommen werden. On-Ramps sind andere Regeln, die auf andere Ereignisse reagieren – aber die zugrunde liegende Maschinerie ist dieselbe.
Lebenszyklus in der Blockchain
FoF löste die Koordination auf der Fiat-Seite – Bankgeschäfte, Anbieter, Compliance. Als wir jedoch mit der Entwicklung von Global USD begannen, stießen wir auf einen neuen Bereich: die Blockchain selbst. Eine Transaktion in die Blockchain einzutragen, zu bestätigen, dass sie tatsächlich angekommen ist, Fehler und Umstrukturierungen der Blockchain zu bearbeiten und aus den Ergebnissen einen genauen Status abzuleiten – das ist ein ganz anderes Koordinationsproblem. Wir brauchten die gleichen Garantien wie bei FoF, aber für die Ausführung in der Blockchain.
Das Muster: Absicht → Ausführung → Abstimmung
Wir verwenden ein einheitliches Muster für alle Blockchain-Operationen:
1. Absicht: Erklären Sie, was wir versuchen zu tun.
2. Ausführen: Die Transaktion einreichen und zur Aufnahme in den Block begleiten
3 Abgleichen: Bestätigte Blöcke verarbeiten, internen Status aktualisieren, nachgelagerte Abläufe auslösen
Wenn Sie aus dem traditionellen Finanzwesen kommen, ist die Analogie ganz einfach:
- Absicht ≈ Zahlungsauftrag
- Ausführen ≈ ausstehend
- Abstimmen ≈ gebucht
Jede Phase hat unterschiedliche Verantwortlichkeiten und Fehlermodi. Im weiteren Verlauf dieses Abschnitts wird erläutert, wie wir jede Schicht aufgebaut haben.
Bevor wir irgendetwas ausführen können, müssen wir definieren was wir ausführen. Eine Blockchain-Transaktion ist im Grunde genommen eine Anweisung (eine mit Parametern aufgerufene Funktion), aber die Kette versteht keine für Menschen lesbaren Anweisungen. Alles wird in Anrufdaten - Ein Hex-Byte-Blob, der die aufzurufende Funktion und die zu übergebenden Argumente angibt.
Beispielsweise wird eine einfache USDC-Überweisung – „500 USDC an Adresse X senden“ – zu:
0xa9059cbb0000000000000000000000007e2f5e1fd4d79ed41118fc6f59b53b575c51f182000000000000000000000000000000000000000000000000000000001dcd6500
Rohe Anrufdaten wie diese sind undurchsichtig und sagen nichts über warum Geld bewegt. Und wenn Sie Systeme entwickeln, die den geschäftlichen Kontext verfolgen müssen – nicht nur, dass Vermögenswerte transferiert wurden, sondern dass es sich um eine Gebühreneinziehung für Rechnung Nr. 1234 handelte –, müssen Sie diesen Kontext beibehalten.
Wir lösen dies mit einem Register typisierter Aufrufdefinitionen:
Ingenieure arbeiten mit Domänenbegriffen – Vertrag, Empfänger, Betrag – statt mit Hexadezimalzeichenfolgen. Die Registrierungsstelle validiert Eingaben, übernimmt die Kodierung und speichert die Metadaten, die wir später benötigen: Kategorie, Tags und Geschäftskontext.
Das Erstellen eines Anrufs wird ganz einfach:
Jeder Anruf wird zu einem BlockchainCall-Datensatz:
Wir behandeln den BlockchainCall als atomare Arbeitseinheit. Eine Transaktion kann mehrere Aufrufe umfassen, aber jeder Aufruf stellt einen einzelnen abrechnungsfähigen Vorgang dar. Das Anforderungsfeld bewahrt zusätzlich zu den codierten Bytes die vollständige eingegebene Eingabe auf – einschließlich aller Metadaten und beliebigen Kontexts. Diese Metadaten ermöglichen es uns, die Frage „Wofür war diese Überweisung in Höhe von 500 Dollar?“ zu beantworten, wenn wir den Kettenstatus mit den Geschäftsvorgängen abgleichen.
Ausführung: Transaktionen bis zum Abschluss begleiten
Eine Transaktion zu senden, klingt einfach. In der Praxis gibt es jedoch viele Fallstricke zwischen „Senden“ und „Ankommen“.
Wenn Sie eine Transaktion einreichen, wird diese nicht direkt in einen Block aufgenommen. Sie gelangt in die Mempool- Ein Wartebereich, in dem Transaktionen verbleiben, bis ein Blockproduzent sie aufnimmt. Während des Wartens können Transaktionen verworfen werden (Mempool ist voll), überboten werden (jemand hat höhere Gebühren gezahlt) oder stecken bleiben (Gaspreis für die aktuellen Netzwerkbedingungen zu niedrig).
Gas So berechnen Ethereum-basierte Netzwerke die Kosten für Berechnungen. Jede Operation kostet Gas, und Sie bezahlen für Gas mit dem nativen Token des Netzwerks. Wenn Sie eine Transaktion einreichen, geben Sie den maximalen Gaspreis an, den Sie zu zahlen bereit sind. Wenn die Netzwerkauslastung nach der Einreichung stark ansteigt, ist Ihr Gaspreis möglicherweise nicht mehr wettbewerbsfähig – Ihre Transaktion bleibt im Mempool und wartet möglicherweise für immer.
Selbst nachdem eine Transaktion in einem Block gelandet ist, ist sie noch nicht wirklich endgültig. Blockchains können Umstrukturierungen (Reorgs) Situationen, in denen das Netzwerk kürzlich hinzugefügte Blöcke verwirft und durch eine andere Blockkette ersetzt. Eine Transaktion, die Sie für bestätigt gehalten haben, kann verschwinden. In ausgereiften Netzwerken kommt dies selten vor, aber „selten“ bedeutet nicht „nie“, wenn Sie mit echtem Geld handeln.
Jeder dieser Fehler tritt auf einer anderen Ebene auf: Gasschätzung, Signierung, Übermittlung, Bestätigung. Und die Behebung jedes Fehlers erfordert unterschiedliche Abhilfemaßnahmen – eine festgefahrene Transaktion muss mit höherem Gas erneut übermittelt werden, eine ungültige Signatur muss erneut signiert werden, eine Reorganisation erfordert eine Wiederholung des gesamten Ablaufs.
Wir lösen das, indem wir den Ausführungslebenszyklus als eine Hierarchie von vier Einheiten modellieren. Ganz oben steht das Geschäftsergebnis, das wir erreichen wollen. Darunter gibt es immer spezifischere Ebenen, die sich um die Vorbereitung, Unterzeichnung und Einreichung kümmern. Jede Ebene hat ihren eigenen Fehlerbereich und kann es selbstständig nochmal versuchen, bevor sie es an die nächste Ebene weitergibt:
Blockchain-Absicht stellt das Geschäftsergebnis dar: „Überweise 500 USDC an diese Adresse als Zahlung für Rechnung Nr. 1234.“ Es handelt sich um den Orchestrator der obersten Ebene, der den gesamten Lebenszyklus verfolgt und bei Bedarf Wiederholungsversuche auslösen kann.
Vorbereiteter Anruf ist eine unveränderliche, nicht signierte Transaktion mit festgelegten Gas-Schätzungen. Wenn die Gas-Schätzungen ablaufen (Netzwerkbedingungen haben sich geändert), erstellen wir einen neuen PreparedCall.
VorbereiteteAnrufausführung stellt einen Signaturversuch dar. Bei serverseitigen Vorgängen erfolgt die Signatur automatisch. Bei benutzerseitigen Vorgängen (wie Global USD) erfolgt die Genehmigung durch den Benutzer über OTP. In beiden Fällen können wir nach der Signatur die Übermittlung vornehmen.
VorbereiteterAufrufAusführungsknoten ist ein einzelner Übermittlungsversuch. Wir senden die Transaktion an das Netzwerk und fragen nach der Aufnahme. Wenn dies aus wiederholbaren Gründen fehlschlägt (Netzwerk-Timeout, aus dem Mempool entfernt), erstellen wir einen neuen Knoten und versuchen es erneut.
Jede Schicht behandelt ihren eigenen Fehlerbereich:
Die wichtigste Erkenntnis ist, dass Fehler auf die übergeordnete Ebene eskalieren, wenn eine Ebene ihre Behebungsoptionen ausgeschöpft hat. Betrachten wir einmal eine anhaltende Unterschätzung des Gas-Parameters. Die Netzwerküberlastung steigt sprunghaft an, und die in unserem PreparedCall festgelegten Gas-Parameter sind nicht mehr wettbewerbsfähig. Der Ausführungsknoten versucht es einige Male erneut, und vielleicht löst sich die Überlastung auf. Nach N Fehlern kann er nichts mehr tun. Der Fehler eskaliert zur Ausführung, die einen Endzustand erreicht und zur Absicht eskaliert. Die Absicht erzeugt eine untergeordnete Absicht mit höheren Gas-Multiplikatoren, erstellt einen neuen PreparedCall, und der Zyklus beginnt von vorne.
Jede Schicht behandelt ihren eigenen Fehlerbereich, aber die Eskalation ist explizit. Die übergeordnete Absicht bewahrt den vollständigen Verlauf; die untergeordnete Absicht erhält einen neuen Versuch mit angepassten Parametern. Wir verlieren niemals den Kontext über warum Wir versuchen es erneut.
Abstimmung: Von Kettenereignissen zum Produktstatus
Eine Transaktion ist in einem Block enthalten. Was nun?
Die Blockchain teilt uns nicht direkt mit, dass eine Überweisung von 1000 USDC stattgefunden hat. Sie teilt uns mit, dass eine Transaktion ausgeführt und einige EreignisprotokolleWir müssen diese Protokolle analysieren, ihre Bedeutung herausfinden und unseren internen Status entsprechend aktualisieren.
Ereignisprotokolle sind die Art und Weise, wie Smart Contracts kommunizieren, was während der Ausführung passiert ist. Wenn Sie die Übertragung Funktion eines USDC-Vertrags löst der Vertrag einen Übertragung Ereignis mit drei Daten: wer es gesendet hat, wer es empfangen hat und wie viel. Dieses Ereignis wird im Transaktionsbeleg als Protokolleintrag aufgezeichnet.
Protokolle werden jedoch als Themen- und Datenfelder mit hexadezimal codierten Werten codiert. Um sie zu analysieren, muss man die Ereignissignatur kennen und die Parameter decodieren. Ein rohes Transferprotokoll sieht in etwa so aus:
Wie können wir erkennen, dass es sich um eine Übertragung handelt? Jedes Protokoll Themen[0] ist der Keccak256-Hash der Ereignissignatur – in diesem Fall 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef ist der Hash von Transfer (Quelladresse, Zieladresse, uint256-Wert)- das Standard-ERC-20-Transferereignis. Als indiziert werden im Themenarray in der Reihenfolge ihrer Deklaration hinter dem Signatur-Hash gespeichert. Für dieses Transfer-Ereignis gilt Folgendes: von ist in Themen[1] und zu in Themen[2]Nicht indizierte Parameter wie Wert sind ABI-kodiert in Daten.
Extrahieren der Übertragungsdetails aus diesem Protokoll:
- von:
Themen[1](32 Bytes, mit Nullen aufgefüllt) →0x7e2f5e1fd4d79ed41118fc6f59b53b575c51f182 - zu:
Themen[2](32 Bytes, mit Nullen aufgefüllt) →0xa6dbc393e2b1c30cff2fbc3930c3e4ddfc9d1373 - Wert:
Datenals uint256 entschlüsselt →0x4c4b40= 5.000.000 (5 USDC, da USDC 6 Dezimalstellen hat).
Die mentale Belastung, die damit verbunden ist, zu wissen, wie man jede Art von Protokoll analysiert, scheint ein Albtraum zu sein. Aus diesem Grund haben wir Protokollprozessoren entwickelt, die bestimmte Ereignistypen analysieren und in einen Domänenstatus umwandeln können:
Der Prozessor nimmt die Rohdaten aus den Protokollen auf, zerlegt sie in typisierte Felder (anstelle von Hexadezimalzeichenfolgen) und erzeugt Domänenentitäten.
Inklusion vs. Bestätigung
Wir kümmern uns um zwei verschiedene Phasen des Lebenszyklus:
- Inklusion - Die Transaktion erscheint zunächst in einem Block. Der Status ist vorläufig – der Block könnte noch reorganisiert werden.
- Bestätigung – Der Block erreicht eine ausreichende Tiefe (genügend nachfolgende Blöcke, um die Möglichkeit einer Reorganisation auszuschließen). Der Status ist endgültig.
Diese Unterscheidung ist wichtig. Wir könnten die Benutzeroberfläche aktualisieren, um bei der Aufnahme einen ausstehenden Status anzuzeigen, aber wir würden erst nach der Bestätigung nachgelagerte FoF-Abläufe auslösen. Die Kosten für Maßnahmen im vorläufigen Status sind unbegrenzt.
Log-Prozessoren verarbeiten einzelne Ereignisse, aber oft müssen wir diese koordinieren oder einen Status auf Transaktionsebene hinzufügen. Transaktionsprozessoren fassen dies zusammen: Sie empfangen die zusammengeführte Ausgabe aller Log-Prozessoren und können diese transformieren, ergänzen oder zusätzliche nachgelagerte Effekte auslösen. Hier kommt auch der zweiphasige Lebenszyklus zum Tragen. Transaktion verarbeiten läuft bei Einbeziehung – wir erzeugen einen vorläufigen Zustand. Prozessbestätigung wird ausgeführt, sobald der Block endgültig ist – hier schließen wir in der Regel die Lebenszyklen für Finanzoperationen ab.
Protokolle wieder mit Anrufen verbinden
Wenn unser Protokollprozessor einen Übertragungsdatensatz erstellt, muss er einen Verweis auf den ursprünglichen BlockchainCall enthalten. Das Protokoll gibt uns Auskunft darüber. was geschehen – Vermögenswerte wurden von A nach B verschoben. Der BlockchainCall teilt uns mit, dass warum– handelte es sich um eine Gebühreneinziehung, eine Zahlung an einen Lieferanten oder eine Rückerstattung. Bei einfachen Transaktionen mit einem Aufruf ist dies unkompliziert. Bei gebündelten Transaktionen, bei denen wir mehrere Vorgänge in einer einzigen On-Chain-Transaktion bündeln, um Gas zu sparen, wird es schwieriger. Die Quittung liefert uns eine flache Liste aller während der Ausführung ausgegebenen Protokolle, ohne Angabe, welcher Aufruf welches Protokoll erzeugt hat. Wir lösen dies mit Call-Frame-Tracing, das wir im Abschnitt „Fortgeschrittene Funktionen“ weiter unten behandeln.
Erweitert: Zuordnung von gebündelten Protokollen zu einzelnen Anrufen
Dieser Abschnitt behandelt eine spezifische technische Herausforderung bei gebündelten Transaktionen. Wenn Sie nicht mit ERC-4337 oder gebündelter Ausführung arbeiten, können Sie gerne zu Global USD weitergehen. Wir haben bereits erwähnt, dass die Verknüpfung von Protokollen mit ihrem ursprünglichen BlockchainCall bei einfachen Transaktionen unkompliziert ist. Bei gebündelten Transaktionen ist dies jedoch nicht der Fall.
Das Problem
Wenn wir mehrere Vorgänge in einer einzigen Transaktion zusammenfassen – beispielsweise eine Zahlung in Höhe von 500 Dollar plus eine Gebühr von 1 Dollar –, werden beide Vorgänge atomar ausgeführt. Der Transaktionsbeleg enthält eine flache Liste aller während der Ausführung ausgegebenen Protokolleinträge:
Wir erhalten ein flaches Array aller während der Ausführung ausgegebenen Protokolle. Anhand dieser Aufstellung können wir zwei Transfer-Ereignisse an den Protokollindizes 1 und 2 identifizieren (beide mit dem gemeinsamen 0xddf252ad... Übertragungsereignissignatur, die wir zuvor besprochen haben).
Aber welche war die Zahlung und welche die Gebühr? Die Quittung gibt darüber keinen Aufschluss – Protokolle werden der Transaktion auf oberster Ebene zugeordnet, nicht einzelnen Anrufen innerhalb eines Stapels. Man könnte meinen: Man muss nur die Protokolle der Reihe nach den Anrufen zuordnen. Das funktioniert jedoch nur, wenn jeder Anruf genau ein Protokoll erzeugt. Eine einfache Überweisung erzeugt eines, ein Tausch möglicherweise fünf. Ohne die Grenzen zu kennen, kann man sie nicht zuverlässig zuordnen.
Aufrufrahmenverfolgung
Die Lösung stellte sich heraus zu sein debug_traceTransaction- Eine RPC-Methode des Geth-Archivknotens, die von den meisten Benutzern zum Debuggen fehlgeschlagener Transaktionen verwendet wird. Sie hat jedoch noch eine weitere Funktion: Sie wiederholt die Transaktion und gibt den vollständigen Aufrufbaum zurück, wobei die Protokolle in der richtigen Tiefe in der Aufruffhierarchie angehängt sind.
Das Ergebnis ist eine rekursiv verschachtelte Struktur von Aufruf-Frames (zur besseren Lesbarkeit vereinfacht dargestellt).
Wir glätten diese rekursive Struktur zu einem Schema, das die Baumbeziehungen beibehält:
Betrachten wir eine gebündelte UserOp mit zwei USDC-Überweisungen: eine Zahlung in Höhe von 500 $ und eine Gebühr in Höhe von 1,10 $, dargestellt durch den oben aufgeführten Ausführungstrace. Der Trace liefert uns folgende Informationen:

Die gesamte Transaktion kann nun als Baum dargestellt werden. Dadurch wird das gesamte Problem neu formuliert: Anstatt die Struktur aus einem flachen Log-Array abzuleiten, rekonstruieren wir den Ausführungsbaum, in dem die Aufrufhierarchie explizit ist und die Logs an die Frames angehängt sind, die sie ausgegeben haben.
Von dort aus ist die Zuordnung einfach. Suchen Sie den Knoten, der dem executeBatch() Aufruf, Durchlaufen seiner Kinder an Indizes 0..N-1und sammelt rekursiv Protokolle aus jedem Teilbaum. Jeder untergeordnete Index 0..N-1 wird direkt der entsprechenden BlockchainCall zugeordnet indexInBatchWir wissen nun genau, welcher Anruf welche Protokolle erzeugt hat.

Da praktisch jede Transaktion diese Zuordnung benötigt, haben wir sie direkt in unseren Protokollprozessor integriert. Dieser rekonstruiert den vollständigen Aufrufbaum, ordnet Protokolle ihren ursprünglichen Frames zu und löst alle BlockchainCalls im Batch auf. Jeder Protokollprozessor erhält dann den spezifischen Aufruf- und Frame-Kontext für das von ihm verarbeitete Protokoll:
Die vollständige Attributionskette:
Global USD: Der Schlussstein
Off-Ramps und On-Ramps lösten ein Problem für unsere bestehenden Kunden – Unternehmen mit US-Bankkonten, die zwischen Fiat- und Kryptowährungen wechseln wollten. Aber wir hörten immer wieder von einem anderen Segment: internationalen Unternehmen, die Zugang zu US-Dollar-Rails benötigen, diese aber nicht ohne Weiteres bekommen können.
Wenn Sie ein Software-Auftragnehmer in Argentinien, ein E-Commerce-Händler in Nigeria oder ein SaaS-Unternehmen in Südostasien sind, erfordert die Eröffnung eines US-Bankkontos oft die Gründung einer US-Gesellschaft – mit Anwälten, registrierten Vertretern und monatelangen Gemeinkosten. Viele seriöse Unternehmen sind praktisch aus der Dollar-Wirtschaft ausgeschlossen, nicht wegen ihrer Handlungen, sondern wegen ihres Firmensitzes.
Stablecoins ändern dies. Ein USDC-Guthaben ist ein Dollar-Guthaben. Global USD ist unser Versuch, auf dieser Prämisse eine Bankinfrastruktur aufzubauen.
Von Grund auf nicht verwahrend
Wir haben Global USD als nicht-verwahrendes System aufgebaut. Diese Entscheidung wurde von zwei Faktoren beeinflusst: der Komplexität der Regulierung und dem Vertrauen.
Die Verwahrung von Kundengeldern unterliegt je nach Rechtsordnung unterschiedlichen Lizenzanforderungen. Eine nicht-verwahrende Architektur vereinfacht unsere Lizenzierung in vielen dieser Märkte. Was das Vertrauen angeht, so kontrollieren die Kunden ihre eigenen Schlüssel – Slash kann grundsätzlich keine Überweisungen ohne kryptografische Autorisierung durch die Kontoinhaber vornehmen.
Die Kernprimitive ist die intelligente GeldbörseEin Smart Contract, der als Wallet fungiert, jedoch mit programmierbarer Zugriffskontrolle.
Jedes Global-USD-Konto ist eine intelligente Geldbörse, die durch eine Multi-Signatur verwaltet wird. Jedes autorisierte Mitglied des Unternehmens verfügt über einen Schlüssel. Überweisungen müssen vor der Ausführung genehmigt werden. Slash kann vorbereiten eine Transaktion, aber wir können nicht ausführen ohne Unterschriftsberechtigung.
Unterzeichnung ohne Sorgerecht
Dies wirft eine Frage zur Benutzererfahrung auf: Wenn Benutzer die Schlüssel kontrollieren, müssen sie dann nicht auch die Seed-Phrasen verwalten und Transaktionen manuell signieren?
Wir verwenden die integrierte Wallet-Infrastruktur von Privy und Alchemy. Wenn ein Benutzer ein Konto erstellt, wird ein privater Schlüssel in einem hardwareisolierten Speicher (einer „vertrauenswürdigen Ausführungsumgebung“ oder TEE) generiert. Der Schlüssel existiert, ist jedoch so konzipiert, dass er für Slash oder andere Personen nicht direkt zugänglich ist. Wenn ein Benutzer eine Überweisung initiiert, genehmigt er diese über OTP, wodurch die TEE autorisiert wird, in seinem Namen zu unterschreiben. Die signierte Transaktion wird dann an das Netzwerk übermittelt.
Aus Sicht des Benutzers fühlt es sich an wie die Genehmigung einer Banküberweisung. Aus Sicht der Verwahrung kommen wir niemals mit privaten Schlüsseln in Berührung.
Was dies ermöglicht
Ein Unternehmen in Lagos kann nun Dollar halten, Zahlungen von US-Kunden entgegennehmen und internationale Lieferanten bezahlen – und das alles ohne US-Bankkonto, ohne Verwahrungsrisiko und mit denselben Prüfpfaden und Compliance-Workflows, die wir für jeden Slash-Kunden anwenden würden.
Das ist es, was Stablecoins tatsächlich sein können: nicht nur eine Zahlungsmethode, sondern eine grundlegende Infrastruktur für ein zugänglicheres Finanzsystem.
Was kommt als Nächstes?
Die von uns entwickelten Primitive dienen nicht nur dem Transfer von Geld zwischen Fiat- und Kryptowährungen. Sie bilden die Grundlage für alles, was wir bei Slash aufbauen. Wir erweitern unser globales Kontoangebot und ermöglichen so mehr Unternehmen den Zugang zu USD-Rails, unabhängig davon, wo sie ihren Sitz haben. Außerdem entwickeln wir unsere globale Karte: eine Karte mit hohem Cashback, die durch Stablecoins gedeckt ist und mit der Kunden ihr Guthaben überall ausgeben können. Beide basieren in hohem Maße auf denselben Orchestrierungs- und Ausführungsframeworks, die wir hier beschrieben haben. Wenn Sie bis hierher gelesen haben und als Ingenieur schwierige Infrastrukturprobleme für echte Kunden in einem schnell wachsenden Unternehmen lösen möchten, dann sind Sie bei uns genau richtig.