Pada awal tahun ini, kami telah melampaui $1 miliar dalam volume pembayaran stablecoin secara total. Sebagai gambaran, kami memproses transaksi stablecoin pertama kami kurang dari 12 bulan yang lalu. Semua berawal dari beberapa pelanggan yang meminta sesuatu yang seharusnya sederhana: kemampuan untuk menerima pembayaran stablecoin dari klien mereka di seluruh dunia dan memiliki dana tersebut dibayar dalam dolar AS- Dengan cepat dan dapat diprediksi, tanpa harus membayar biaya yang tinggi. Solusi off-ramp yang ada sebelumnya membebankan biaya 1-3%, proses penyelesaian yang memakan waktu beberapa hari, dan proses kepatuhan yang sangat panjang dan menjengkelkan. Kami melihat peluang dan membangun MVP dalam dua minggu. Dalam sebulan, kami sudah memiliki volume yang nyata dan signifikan.
Tantangannya adalah menskalakan hal tersebut.
Stablecoin diproses dalam hitungan detik, di mana saja, kapan saja. Sistem perbankan tradisional tidak dirancang untuk itu—mereka beroperasi dengan pemrosesan batch, batas waktu hari kerja, dan jendela penyelesaian multi-hari. Seorang pelanggan di Singapura mengirimkan $50.000 dalam bentuk USDC pada pukul 2 pagi pada hari Sabtu. Di rantai blok, transaksi tersebut diselesaikan dalam hitungan detik. Transfer ACH ke rekening bank Anda tidak akan dimulai hingga Senin, tidak akan tiba hingga Rabu, dan mungkin akan tertunda dalam proses peninjauan di antara keduanya. Menghubungkan dua dunia ini berarti mengoordinasikan sistem-sistem yang tidak pernah dirancang untuk berkomunikasi satu sama lain, masing-masing dengan statusnya sendiri.
Postingan ini membahas dua infrastruktur dasar yang kami bangun untuk membuat pergerakan stablecoin berperilaku seperti pergerakan uang berstandar perbankan:
1. Aliran DanaMesin orkestrasi deklaratif untuk alur kerja keuangan yang berjalan lama dan melibatkan beberapa sistem.
2. Kami Kerangka kerja eksekusi on-chainModel siklus hidup untuk operasi on-chain yang andal
Semua hal lainnya—jalan keluar, jalan masuk, dan akun Global USD non-penitipan kami—dibangun dengan menggabungkan elemen-elemen dasar ini. Jika ada satu hal yang bisa Anda ambil dari posting ini: stablecoin itu mudah; stablecoin perbankan bukan.
Aliran Dana
Ketika Anda mentransfer dana melalui beberapa sistem eksternal, Anda membutuhkan lebih dari sekadar koordinasi ad-hoc. Anda memerlukan cara untuk menggambarkan aliran dana secara deklaratif: apa yang harus terjadi, sebagai respons terhadap peristiwa apa, dengan jaminan apa. Dan Anda memerlukan aliran tersebut agar dapat diaudit, dilanjutkan, dan tetap benar bahkan jika langkah-langkahnya gagal di tengah jalan. Itulah yang diberikan oleh Flow of Funds.
Masalah dengan Pergerakan Uang
Sebagian besar tantangan orkestrasi dalam perangkat lunak berkaitan dengan penanganan kegagalan secara elegan. Orkestrasi keuangan memiliki batasan yang lebih ketat: Uang sudah mulai bergerak..
Pertimbangkan aliran setoran instan. Seorang pelanggan menerima $10.000 USDC. Kami langsung mengkreditkan akun mereka (sebelum transaksi ACH yang mendasarinya diselesaikan) sehingga mereka dapat menggunakan dana tersebut segera. Di balik layar, kami telah menerbitkan pinjaman. Ketika transaksi ACH tiba beberapa hari kemudian, kami mengumpulkan pembayaran kembali dan biaya.
Itu adalah empat proses yang melibatkan dua sistem eksternal: likuidasi kripto, pencairan pinjaman, penyelesaian ACH, dan pengumpulan biaya. Setiap langkah bergantung pada langkah sebelumnya, dan setiap langkah dapat gagal. Anda tidak dapat mengelola ini dengan status yang terpisah-pisah dan penangan ad-hoc.
Abstraksi Inti
Aliran Dana adalah sistem orkestrasi berbasis aturan yang deklaratif. Abstrak inti terdiri dari tiga bagian:
Acara adalah sinyal bahwa sesuatu telah terjadi—seperti transaksi ACH yang diselesaikan, dana diterima, otorisasi kartu berhasil, dan sebagainya. Peristiwa dapat berasal dari sistem eksternal atau dihasilkan secara internal.
Aturan Tentukan tindakan yang harus dilakukan sebagai respons terhadap peristiwa. Setiap aturan menentukan daftar peristiwa pemicu dan urutan efek samping yang harus dieksekusi.
Efek Samping adalah tindakan yang kita ambil sebagai respons terhadap peristiwa: memulai transfer, membuat penahanan, menyalurkan pinjaman, dan mengumpulkan biaya. Sebuah aturan dijalankan sekali. Saat peristiwa yang sesuai pertama kali tiba, efek samping dieksekusi secara berurutan, dan aturan tersebut dikonsumsi. Hal ini menjamin idempotensi dalam konteks alur.
Mengapa Deklaratif?
Alternatifnya adalah orkestrasi imperatif: pemanggil memanggil pemanggil, keadaan tersebar di berbagai tabel, dan "aliran" hanya ada dalam koordinasi implisit antara potongan-potongan kode.
Hal itu berlaku untuk alur kerja sederhana. Namun, untuk operasi keuangan multi-hari dan multi-sistem yang melibatkan penahanan kepatuhan dan kegagalan parsial, hal itu menjadi tidak dapat dipertahankan. Penanganan kesalahan dilakukan secara ad-hoc. Jalur pemulihan bersifat implisit. Enam bulan kemudian, tidak ada yang dapat dengan yakin menjawab, "Apa yang terjadi jika langkah 3 gagal setelah langkah 2 berhasil?"
Aturan deklaratif membalik model. Anda mendefinisikan mesin keadaan secara eksplisit: ini Pemicu acara ini Aksi. Mesin orkestrasi menangani eksekusi, penyimpanan, dan pemulihan. Alur adalah Dokumentasi.
Jaminan
FoF memberikan kita empat invarians yang dapat kita andalkan:
1. Idempotensi - Sebuah aturan dijalankan tepat sekali per konteks aliran, terlepas dari adanya peristiwa duplikat atau upaya ulang.
2. Rekonsiliasi deterministik - Jika peristiwa yang sama terjadi, aliran akan berakhir pada keadaan yang sama.
3. Auditabilitas penuh - Setiap efek samping yang terjadi dilacak dengan jejak balik hingga ke peristiwa pemicu.
4. Komposabilitas - Aliran kompleks dibangun dari aturan-aturan sederhana yang saling berinteraksi tanpa menjadi monolitik.
Pelacakan Pelaksanaan
Kami melacak setiap eksekusi efek samping melalui catatan Node—masing-masing terhubung dengan induknya, membentuk pohon eksekusi yang lengkap. Ketika kepatuhan memerlukan jejak audit, kami dapat melacak jalur tepat melalui sistem.
Komposabilitas: Aturan Bersarang
Aturan dapat menghasilkan aturan anak. Inilah cara alur yang kompleks dan bertahap terbentuk tanpa menjadi monolitik. Saat transaksi off-ramp dibuat, aturan awal tidak mencoba menangani semuanya. Ia mengatur masa depan Aturan—pendengar yang menunggu peristiwa yang akan terjadi di kemudian hari:
Logika penyelesaian tidak ada sebagai kode mati yang menunggu untuk dipanggil. Logika tersebut ada sebagai aturan, menunggu peristiwa yang memicunya. Ketika webhook penyedia perbankan tiba beberapa hari kemudian, aturan tersebut dijalankan dan alur proses berlanjut. Aturan induk dikonsumsi, dan aturan anak melanjutkan konteks ke tahap berikutnya.
Hal ini juga berarti alur dapat disusun secara arbitrer. Ingin menerapkan setoran instan? Mudah. Tambahkan aturan yang mencairkan pinjaman dan menetapkan aturan pembayaran. Setiap komponen terisolasi, tetapi semuanya tersusun menjadi alur yang kohesif.
Kontekst Eksekusi Efek Samping
Tidak semua efek samping sama. Beberapa harus dijalankan secara atomik dengan transaksi basis data. Beberapa memanggil API eksternal. Beberapa bersifat fire-and-forget.
Imbalannya
Manfaat terbesar adalah bagaimana FoF mengubah cara insinyur menulis kode orkestrasi di Slash. Tanpa FoF, setiap insinyur menyelesaikan masalah yang sama dengan cara yang berbeda. Semua orang mengulang-ulang hal yang sama, dan hasilnya pun berbeda-beda.
FoF menaikkan batas bawah. Anda menentukan apa harus terjadi, bukan bagaimana Untuk menangani setiap mode kegagalan. Kerangka kerja ini menangani eksekusi, persisten, dan observabilitas. Insinyur baru dapat membaca definisi alur dan memahaminya tanpa perlu melacak melalui lapisan kode imperatif. Dan lebih sulit untuk menulis kode orkestrasi yang buruk ketika abstraksi memaksa Anda untuk secara eksplisit menyatakan peristiwa, efek samping, dan transisi keadaan.
Ramps: FoF dalam Praktik
Dengan FoF sebagai landasan untuk menyusun aliran keuangan, pengembangan produk inti kami menjadi soal menentukan aturan yang tepat untuk setiap aliran. Abstrak ini tidak peduli sistem apa yang ada di ujung lain, ia hanya mengoordinasikan.
Off-ramps dan on-ramps adalah "aliran" yang diatur oleh mesin ini, memperkenalkan sistem eksternal baru: penyedia kripto (atau meja OTC) yang menangani konversi stablecoin/fiat. Seperti sistem eksternal lainnya, mereka mengirimkan pembaruan status sesuai dengan ketentuan mereka sendiri—yang dapat kita gunakan untuk memicu peristiwa FoF. Dari sana, ini hanya soal komposisi aliran.
Keluar dari jalan tol
Off-ramps memungkinkan pelanggan menerima pembayaran stablecoin dan mencairkannya sebagai USD di akun Slash mereka. Alurnya sederhana:
- Pelanggan menerima USDC atau USDT di alamat deposit yang kami generate melalui penyedia kripto kami.
- Penyedia mendeteksi setoran, mencairkannya ke USD, dan memulai transfer ACH atau transfer kawat.
- Penyedia layanan perbankan kami menerima transfer masuk.
- Kami mencocokkan transfer dengan transaksi asli dan mengkreditkan akun.
Untuk setoran instan—di mana kami langsung mengkreditkan pelanggan dan mengumpulkan pembayaran kembali saat ACH diselesaikan—alurnya mencakup pencairan pinjaman, pengumpulan pembayaran kembali, dan penagihan biaya. Setiap proses merupakan aturan terpisah, mendeteksi peristiwa masing-masing, dan digabungkan menjadi alur yang terintegrasi. Definisi FoF terlihat seperti ini:
Jalur Masuk
On-ramps adalah kebalikannya: pelanggan mengirim USD dari akun Slash mereka dan menerima stablecoin di dompet eksternal. Alurnya:
- Pelanggan memulai transfer ke alamat dompet tujuan.
- Kami membuat penahanan pada akun mereka sebesar jumlah tersebut ditambah biaya.
- Kami mengirimkan transfer ACH atau transfer kawat ke instruksi setoran di penyedia kripto kami.
- Penyedia menerima dana dan mengirimkan stablecoin ke tujuan.
Yang menonjol adalah betapa sedikitnya infrastruktur baru yang diperlukan. Kerangka kerja FoF dan logika rekonsiliasi yang kami bangun untuk off-ramps dapat diterapkan langsung. On-ramps memiliki aturan yang berbeda yang mendeteksi peristiwa yang berbeda—tetapi menggunakan mesin dasar yang sama.
Daur Hidup On-Chain
FoF telah menyelesaikan masalah koordinasi di sisi fiat—sistem perbankan, penyedia layanan, dan kepatuhan. Namun, saat kami mulai membangun Global USD, kami menghadapi area baru: rantai blok itu sendiri. Memasukkan transaksi ke dalam rantai, memastikan transaksi tersebut benar-benar tercatat, menangani kegagalan dan reorganisasi rantai, serta menghasilkan keadaan yang akurat dari hasil tersebut—itu adalah masalah koordinasi yang berbeda. Kami membutuhkan jaminan yang sama seperti yang kami miliki dengan FoF, tetapi untuk eksekusi di dalam rantai.
Polanya: Niat → Pelaksanaan → Rekonsiliasi
Kami menggunakan pola yang konsisten di seluruh operasi blockchain:
1. Niat: Nyatakan apa yang sedang kita upayakan.
2. LaksanakanKirimkan transaksi dan pastikan transaksi tersebut dimasukkan ke dalam blok.
3 RekonsiliasiProses blok yang telah dikonfirmasi, perbarui keadaan internal, dan picu alur kerja hilir.
Jika Anda berasal dari bidang keuangan tradisional, analoginya cukup sederhana:
- Niat ≈ perintah pembayaran
- Jalankan ≈ tertunda
- Rekonsiliasi ≈ yang telah diposting
Setiap fase memiliki tanggung jawab dan mode kegagalan yang berbeda. Bagian selanjutnya dari bagian ini menjelaskan cara kami membangun setiap lapisan.
Sebelum kita dapat melakukan apa pun, kita perlu mendefinisikan apa Kami sedang menjalankan. Transaksi blockchain pada dasarnya adalah instruksi (fungsi yang dipanggil dengan parameter), tetapi rantai tidak memahami instruksi yang dapat dibaca manusia. Segala sesuatu dienkode menjadi calldata - Sebuah blok byte heksadesimal yang menentukan fungsi yang akan dipanggil dan argumen yang akan diteruskan.
Misalnya, transfer USDC sederhana—"kirim 500 USDC ke alamat X"—menjadi:
0xa9059cbb0000000000000000000000007e2f5e1fd4d79ed41118fc6f59b53b575c51f182000000000000000000000000000000000000000000000000000000001dcd6500
Data panggilan mentah seperti ini tidak jelas dan tidak memberikan informasi apa pun tentang mengapa Uang telah dipindahkan. Dan ketika Anda membangun sistem yang perlu melacak konteks bisnis—bukan hanya bahwa aset telah dipindahkan, tetapi bahwa ini adalah penagihan biaya untuk faktur #1234—Anda perlu mempertahankan konteks tersebut.
Kami menyelesaikan hal ini dengan menggunakan daftar definisi panggilan bertipe:
Insinyur bekerja dengan istilah-istilah domain—kontrak, penerima, jumlah—bukan dengan string heksadesimal. Pendaftaran memvalidasi masukan, menangani enkoding, dan menyimpan metadata yang akan kita butuhkan nanti: kategori, tag, dan konteks bisnis.
Membuat panggilan menjadi mudah:
Setiap panggilan menjadi catatan BlockchainCall:
Kami menganggap BlockchainCall sebagai unit kerja atomik. Sebuah transaksi mungkin menggabungkan beberapa panggilan, tetapi setiap panggilan mewakili operasi tunggal yang dapat dipertanggungjawabkan. Bidang permintaan menyimpan input bertipe lengkap beserta byte yang dienkode—termasuk metadata dan konteks arbitrer. Metadata inilah yang memungkinkan kami menjawab "untuk apa transfer $500 ini?" saat kami mencocokkan keadaan rantai dengan operasi bisnis.
Pelaksanaan: Mengawal Transaksi hingga Selesai
Mengirimkan transaksi terdengar sederhana. Namun, dalam praktiknya, ada banyak hal yang perlu diperhatikan antara "kirim ini" dan "sudah sampai."
Ketika Anda mengirimkan transaksi, transaksi tersebut tidak langsung masuk ke dalam blok. Transaksi tersebut masuk ke dalam mempool- Area tunggu tempat transaksi ditempatkan hingga diproses oleh produsen blok. Selama menunggu, transaksi dapat ditolak (mempool penuh), dikalahkan (seseorang membayar biaya lebih tinggi), atau terjebak (harga gas terlalu rendah untuk kondisi jaringan saat ini).
Gas Begitulah cara jaringan berbasis Ethereum menentukan harga komputasi. Setiap operasi membutuhkan gas, dan Anda membayar gas menggunakan token asli jaringan tersebut. Saat Anda mengirimkan transaksi, Anda menentukan harga gas maksimum yang bersedia Anda bayar. Jika kepadatan jaringan meningkat setelah Anda mengirimkan transaksi, harga gas Anda mungkin tidak lagi kompetitif—transaksi Anda akan tertahan di mempool, menunggu, dan berpotensi selamanya.
Bahkan setelah transaksi masuk ke dalam blok, transaksi tersebut belum benar-benar final. Blockchain dapat mengalami Restrukturisasi (reorgs)- Situasi di mana jaringan membuang blok-blok terbaru dan menggantinya dengan rantai blok yang berbeda. Transaksi yang Anda anggap sudah dikonfirmasi bisa menghilang. Hal ini jarang terjadi di jaringan yang sudah matang, tetapi "jarang" bukan berarti "tidak pernah" ketika Anda sedang bertransaksi dengan uang sungguhan.
Setiap kegagalan ini terjadi pada lapisan yang berbeda: perkiraan gas, penandatanganan, pengiriman, dan konfirmasi. Dan pemulihan dari masing-masing memerlukan tindakan perbaikan yang berbeda—transaksi yang macet memerlukan pengiriman ulang dengan gas yang lebih tinggi, tanda tangan yang tidak valid memerlukan penandatanganan ulang, dan reorganisasi memerlukan pengulangan seluruh alur.
Kami menangani hal ini dengan memodelkan siklus eksekusi sebagai hierarki dari 4 entitas. Di bagian atas terdapat hasil bisnis yang ingin kami capai. Di bawahnya, lapisan-lapisan yang semakin spesifik menangani persiapan, penandatanganan, dan pengiriman. Setiap lapisan bertanggung jawab atas domain kegagalannya sendiri dan dapat mencoba ulang secara mandiri sebelum menaikkan masalah ke lapisan di atasnya:
Niat Blockchain Menunjukkan hasil bisnis: "Transfer 500 USDC ke alamat ini sebagai pembayaran untuk faktur #1234." Ini adalah pengatur tingkat atas yang melacak seluruh siklus hidup dan dapat memicu ulang jika diperlukan.
Panggilan yang Dipersiapkan adalah transaksi yang tidak dapat diubah dan tidak bertanda dengan perkiraan gas yang terkunci. Jika perkiraan gas kadaluwarsa (kondisi jaringan berubah), kami membuat PreparedCall baru.
Eksekusi Panggilan yang Dipersiapkan Menandakan upaya penandatanganan. Untuk operasi di sisi server, kami menandatangani secara otomatis. Untuk operasi yang berinteraksi dengan pengguna (seperti Global USD), pengguna menyetujui melalui OTP. Dalam kedua kasus, setelah ditandatangani, kami siap untuk mengirimkan.
Node Eksekusi Panggilan yang Dipersiapkan Ini adalah upaya pengiriman tunggal. Kami mengirimkan transaksi ke jaringan dan memantau apakah transaksi tersebut dimasukkan. Jika gagal karena alasan yang dapat diulang (waktu tunggu jaringan habis, transaksi terhapus dari mempool), kami membuat node baru dan mencoba lagi.
Setiap lapisan menangani domain kegagalan masing-masing:
Inti dari temuan ini adalah bahwa kegagalan akan meningkat ke lapisan induk ketika suatu lapisan telah menghabiskan semua opsi pemulihannya. Pertimbangkan underestimasi gas yang persisten. Kongesti jaringan melonjak, dan parameter gas yang terkunci dalam PreparedCall kami tidak lagi kompetitif. Node eksekusi mencoba ulang beberapa kali, dan mungkin kongesti mereda. Setelah N kegagalan, node tidak dapat melakukan lebih banyak. Kegagalan meningkat ke Execution, yang mencapai keadaan terminal dan meningkat ke Intent. Intent membuat intent anak dengan multiplier gas yang lebih tinggi, membangun PreparedCall baru, dan siklus dimulai lagi.
Setiap lapisan menangani domain kegagalan masing-masing, tetapi eskalasi dilakukan secara eksplisit. Intent orang tua mempertahankan riwayat lengkap; intent anak mendapatkan upaya baru dengan parameter yang disesuaikan. Kami tidak pernah kehilangan konteks tentang mengapa Kami mencoba lagi.
Rekonsiliasi: Dari Rangkaian Acara ke Status Produk
Sebuah transaksi dimasukkan ke dalam blok. Lalu apa yang terjadi?
Blockchain tidak secara langsung memberitahu kita bahwa transfer 1000 USDC telah terjadi. Ia memberitahu kita bahwa transaksi telah dieksekusi dan menghasilkan beberapa catatan peristiwaKami perlu menganalisis log-log tersebut, memahami artinya, dan memperbarui keadaan internal kami sesuai dengan itu.
Catatan peristiwa adalah cara kontrak pintar menyampaikan apa yang terjadi selama eksekusi. Saat Anda memanggil kontrak pintar, transfer Fungsi pada kontrak USDC, kontrak tersebut mengeluarkan sebuah Transfer Acara dengan tiga data: siapa yang mengirimnya, siapa yang menerimanya, dan berapa jumlahnya. Acara ini dicatat dalam bukti transaksi sebagai entri log.
Namun, log dienkripsi sebagai bidang topik dan data yang berisi nilai yang dienkripsi dalam format heksadesimal. Memprosesnya memerlukan pengetahuan tentang tanda tangan peristiwa dan mendekripsi parameter-parameternya. Sebuah log Transfer mentah terlihat seperti berikut:
Bagaimana kita bisa mengetahui bahwa ini adalah Transfer? Setiap log's topik[0] adalah hash keccak256 dari tanda tangan acara - dalam hal ini, 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef adalah hash dari Transfer (alamat asal yang diindeks, alamat tujuan yang diindeks, nilai uint256)- Acara transfer standar ERC-20. Parameter yang ditandai sebagai terindeks disimpan dalam array topik sesuai urutan deklarasi, mengikuti hash tanda tangan. Untuk acara Transfer ini, dari ada di topik[1] dan untuk di topik[2]Parameter yang tidak diindeks seperti nilai dienkode dalam ABI data.
Mengekstrak detail transfer dari log ini:
- dari:
topik[1](32 byte, diisi nol) →0x7e2f5e1fd4d79ed41118fc6f59b53b575c51f182 - untuk:
topik[2](32 byte, diisi nol) →0xa6dbc393e2b1c30cff2fbc3930c3e4ddfc9d1373 - nilai:
dataDiterjemahkan sebagai uint256 →0x4C4B40= 5.000.000 (5 USDC, karena USDC memiliki 6 desimal).
Beban mental yang diperlukan untuk memahami cara memproses setiap jenis log terasa seperti mimpi buruk—itulah mengapa kami telah mengembangkan pemroses log yang mampu memproses jenis peristiwa tertentu dan mengubahnya menjadi keadaan domain:
Prosesor memproses data log mentah, memecahnya menjadi bidang bertipe (bukan string heksadesimal), dan menghasilkan entitas domain.
Inklusi vs. Konfirmasi
Kami menangani dua tahap siklus hidup yang berbeda:
- Inklusi - Transaksi pertama kali muncul dalam sebuah blok. Statusnya masih sementara—blok tersebut masih bisa di-reorg.
- Konfirmasi - Blok telah mencapai kedalaman yang cukup (cukup banyak blok berikutnya untuk menghilangkan kemungkinan reorganisasi). Status telah final.
Perbedaan ini penting. Kami mungkin memperbarui antarmuka pengguna (UI) untuk menampilkan status tertunda saat penambahan, tetapi kami tidak akan memicu aliran FoF hilir hingga konfirmasi. Biaya bertindak berdasarkan status sementara tidak terbatas.
Pengolah log menangani peristiwa individu, tetapi seringkali kita perlu mengoordinasikan di antara mereka atau menambahkan status tingkat transaksi. Pengolah transaksi mengelola hal ini: mereka menerima output yang digabungkan dari semua pengolah log dan dapat mengubahnya, menambahkannya, atau memicu efek tambahan di hilir. Di sinilah siklus hidup dua fase muncul. prosesTransaksi Berjalan pada inklusi - kami menghasilkan keadaan sementara. Konfirmasi Proses Dijalankan setelah blok menjadi final - ini biasanya tempat di mana kami menyelesaikan siklus hidup untuk operasi keuangan.
Menghubungkan Catatan Log Kembali ke Panggilan
Ketika pemroses log kami menghasilkan catatan transfer, ia perlu menghubungkan kembali ke panggilan BlockchainCall asal. Catatan log memberitahu kami apa Terjadi—aset dipindahkan dari A ke B. BlockchainCall memberi tahu kita mengapa—ini adalah pengumpulan biaya, pembayaran kepada vendor, atau pengembalian dana. Untuk transaksi sederhana dengan satu panggilan, hal ini cukup mudah. Untuk transaksi batch—di mana kita menggabungkan beberapa operasi menjadi satu transaksi on-chain untuk menghemat gas—hal ini menjadi lebih rumit. Bukti transaksi memberikan daftar datar dari semua log yang dihasilkan selama eksekusi, tanpa indikasi panggilan mana yang menghasilkan log mana. Kami mengatasi hal ini dengan pelacakan bingkai panggilan, yang akan dibahas dalam bagian lanjutan di bawah ini.
Lanjutan: Mengaitkan Catatan Log Berkelompok ke Panggilan Individu
Bagian ini membahas tantangan teknis spesifik terkait transaksi bertahap. Jika Anda tidak bekerja dengan ERC-4337 atau eksekusi bertahap, silakan lanjutkan ke Global USD. Sebelumnya kami telah menyebutkan bahwa menghubungkan log kembali ke BlockchainCall asalnya merupakan hal yang mudah untuk transaksi sederhana. Untuk transaksi yang digabungkan, hal itu tidak demikian.
Masalahnya
Ketika kita menggabungkan beberapa operasi menjadi satu transaksi—misalnya, pembayaran sebesar $500 ditambah biaya $1—kedua operasi tersebut dieksekusi secara atomik. Bukti transaksi memberikan daftar datar dari setiap log yang dihasilkan selama eksekusi:
Kami mendapatkan array datar dari setiap log yang dihasilkan selama eksekusi. Dengan melihat log ini, kami dapat mengidentifikasi dua peristiwa Transfer pada indeks log 1 dan 2 (keduanya berbagi... 0xddf252ad... tanda tangan acara transfer yang kita bahas sebelumnya).
Tapi mana yang merupakan pembayaran dan mana yang merupakan biaya? Kwitansi tidak memberitahu kita—catatan log dikaitkan dengan transaksi tingkat atas, bukan dengan panggilan individu dalam satu batch. Anda mungkin berpikir: cukup cocokkan catatan log dengan panggilan secara berurutan. Tapi itu hanya berlaku jika setiap panggilan menghasilkan tepat satu catatan log. Transfer sederhana menghasilkan satu; pertukaran mungkin menghasilkan lima. Tanpa mengetahui batasannya, Anda tidak dapat memetakan mereka dengan andal.
Pelacakan Bingkai Panggilan
Solusinya ternyata adalah debug_traceTransaksi- Sebuah metode RPC node arsip Geth yang umumnya digunakan orang untuk mendebug transaksi yang gagal. Namun, metode ini juga melakukan hal lain: ia memutar ulang transaksi dan mengembalikan pohon panggilan lengkap, dengan log yang terpasang pada kedalaman yang benar dalam hierarki panggilan.
Hasilnya adalah struktur yang saling bersarang secara rekursif dari bingkai panggilan (disederhanakan untuk kemudahan pembacaan)
Kami meratakan struktur rekursif ini menjadi skema yang mempertahankan hubungan pohon:
Pertimbangkan sebuah UserOp yang diproses secara batch dengan dua transfer USDC: pembayaran sebesar $500 dan biaya sebesar $1.10, yang diwakili oleh jejak eksekusi di atas. Jejak tersebut memberikan informasi sebagai berikut:

Seluruh transaksi kini dapat diwakili sebagai pohon. Hal ini mengubah perspektif masalah secara keseluruhan: alih-alih menyimpulkan struktur dari array log datar, kita merekonstruksi pohon eksekusi—di mana hierarki panggilan secara eksplisit ditampilkan dan log terhubung ke frame yang menghasilkan mereka.
Dari sana, atribusi menjadi jelas. Temukan node yang sesuai dengan jalankanBatch() Panggil, lalu iterasi melalui anak-anaknya pada indeks 0..N-1, dan secara rekursif mengumpulkan log dari setiap subtree. Setiap indeks anak 0..N-1 peta langsung ke panggilan Blockchain yang sesuai indeks dalam batchSekarang kita tahu persis panggilan mana yang menghasilkan log mana.

Karena hampir setiap transaksi memerlukan atribusi ini, kami mengintegrasikannya langsung ke dalam pemroses log kami. Pemroses ini merekonstruksi pohon panggilan lengkap, mencocokkan log dengan bingkai asalnya, dan menyelesaikan semua panggilan Blockchain dalam batch. Setiap pemroses log kemudian menerima konteks panggilan dan bingkai spesifik untuk log yang sedang diprosesnya:
Rantai atribusi lengkap:
Global USD: Proyek Akhir
Jalur keluar dan jalur masuk telah menyelesaikan masalah bagi pelanggan existing kami—perusahaan dengan rekening bank di AS yang ingin berpindah antara mata uang fiat dan kripto. Namun, kami terus menerima masukan dari segmen yang berbeda: perusahaan internasional yang membutuhkan akses ke sistem pembayaran dolar AS tetapi tidak dapat dengan mudah mendapatkannya.
Jika Anda adalah kontraktor perangkat lunak di Argentina, pedagang e-commerce di Nigeria, atau perusahaan SaaS di Asia Tenggara, membuka rekening bank di AS seringkali memerlukan pembentukan entitas di AS—pengacara, agen terdaftar, dan biaya operasional selama berbulan-bulan. Banyak bisnis yang sah secara efektif terhalang dari ekonomi dolar, bukan karena apa yang mereka lakukan, tetapi karena tempat mereka terdaftar.
Stablecoin mengubah hal ini. Saldo USDC adalah saldo dolar. Global USD adalah upaya kami untuk membangun infrastruktur perbankan berdasarkan prinsip tersebut.
Desain Tanpa Penitipan
Kami mengembangkan Global USD sebagai sistem non-custodial. Keputusan ini didorong oleh dua faktor: kompleksitas regulasi dan kepercayaan.
Menyimpan dana pelanggan menimbulkan persyaratan lisensi yang bervariasi tergantung pada yurisdiksi. Arsitektur non-custodial mempermudah proses perizinan kami di banyak pasar tersebut. Dari segi kepercayaan, pelanggan mengontrol kunci mereka sendiri—secara desain, Slash tidak dapat memulai transfer tanpa otorisasi kriptografis dari penandatangan akun.
Primitif inti adalah dompet pintar: Kontrak pintar yang berfungsi sebagai dompet tetapi dilengkapi dengan kontrol akses yang dapat diprogram.
Setiap akun Global USD adalah dompet pintar yang dikelola oleh multi-sig. Setiap anggota yang berwenang dalam bisnis memegang kunci. Transfer memerlukan persetujuan mereka sebelum dieksekusi. Slash dapat siapkan Sebuah transaksi, tetapi kami tidak dapat melaksanakan Tanpa persetujuan penandatangan.
Penandatanganan Tanpa Hak Asuh
Hal ini menimbulkan pertanyaan terkait pengalaman pengguna (UX): jika pengguna mengontrol kunci, bukankah mereka perlu mengelola frasa benih dan menandatangani transaksi secara manual?
Kami menggunakan infrastruktur dompet tertanam dari Privy dan Alchemy. Saat pengguna membuat akun, kunci pribadi dihasilkan di dalam memori yang diisolasi secara hardware (lingkungan eksekusi tepercaya, atau TEE). Kunci tersebut ada, tetapi dirancang agar tidak dapat diakses secara langsung oleh Slash atau pihak lain. Ketika pengguna memulai transfer, mereka menyetujui melalui OTP, yang mengizinkan TEE untuk menandatangani atas nama mereka. Transaksi yang ditandatangani kemudian dikirimkan ke jaringan.
Dari sudut pandang pengguna, prosesnya terasa seperti menyetujui transfer bank. Dari sudut pandang penyimpanan, kami tidak pernah menyentuh kunci pribadi.
Apa yang Dibuka oleh Ini
Sebuah bisnis di Lagos kini dapat menyimpan dolar, menerima pembayaran dari klien AS, dan membayar vendor internasional—semua tanpa perlu memiliki rekening bank di AS, tanpa risiko penitipan, dan dengan jejak audit serta alur kerja kepatuhan yang sama seperti yang kami terapkan untuk pelanggan Slash lainnya.
Itulah sebenarnya yang bisa menjadi stablecoin: bukan hanya sebagai metode pembayaran, tetapi juga infrastruktur dasar untuk sistem keuangan yang lebih mudah diakses.
Apa Selanjutnya
Primitif yang kami bangun tidak hanya untuk memindahkan uang antara fiat dan kripto. Mereka merupakan fondasi untuk semua yang kami bangun di Slash. Kami memperluas penawaran akun global kami—memberikan akses lebih banyak bisnis ke jalur USD, terlepas dari di mana mereka terdaftar. Dan kami sedang mengembangkan kartu global kami: kartu dengan cashback tinggi yang didukung oleh stablecoin, yang memungkinkan pelanggan menghabiskan saldo mereka di mana saja. Keduanya sangat bergantung pada kerangka kerja orkestrasi dan eksekusi yang sama yang telah kami jelaskan di sini. Jika Anda telah membaca sejauh ini dan Anda adalah seorang insinyur yang ingin memecahkan masalah infrastruktur yang kompleks untuk pelanggan nyata di perusahaan yang sedang berkembang pesat, kami sedang merekrut.