Selami struktur data EVM, tanda terima transaksi, dan log peristiwa

Memahami struktur data yang membentuk blockchain membantu kami memikirkan cara kreatif untuk mengurai data ini.

**Ditulis oleh:**NOXX

Kompilasi: Siram

Menavigasi data on-chain adalah keterampilan penting bagi siapa saja yang ingin memahami ruang Web3. Memahami struktur data yang membentuk blockchain membantu kita memikirkan cara kreatif untuk mengurai data ini. Pada saat yang sama, data on-chain ini merupakan sebagian besar dari data yang tersedia. Posting ini akan mempelajari struktur data utama di EVM, tanda terima transaksi, dan log peristiwa yang terkait.

Mengapa mencatat

Sebelum kita mulai, mari kita bahas secara singkat mengapa kita perlu menggunakan event log sebagai solidity developer:

  • Log peristiwa adalah opsi yang lebih murah untuk penyimpanan data yang tidak perlu diakses oleh kontrak, dan juga dapat merekonstruksi status tersimpan dengan menguji variabel tertentu dalam kontrak pintar, variabel pengindeksan.
  • Log peristiwa adalah cara untuk memicu aplikasi Web3 mendengarkan log peristiwa tertentu.

Node EVM tidak perlu menyimpan log selamanya, dan dapat menghemat ruang dengan menghapus log lama. Kontrak tidak memiliki akses ke penyimpanan log, jadi node tidak memerlukannya untuk mengeksekusi kontrak. Penyimpanan kontrak, di sisi lain, diperlukan untuk eksekusi dan karenanya tidak dapat dihapus.

Akar Merkle Blok Ethereum

Di Bagian 4, kami mempelajari kerangka kerja Ethereum, khususnya bagian root Merkle negara bagian. Akar Negara adalah salah satu dari tiga akar Merkle yang termasuk dalam header blok. Dua lainnya adalah Akar Transaksi dan Akar Penerimaan.

Sebagai masukan untuk membangun kerangka kerja ini, kami akan merujuk ke blok 15001871 di Ethereum, yang berisi 5 transaksi dengan tanda terima terkait dan log peristiwa yang dikirim.

blok tajuk

Kita akan mulai dengan 3 bagian di header blok, Akar Transaksi, Akar Penerimaan, dan Log Bloom (pengenalan singkat tentang header blok dapat diulas di Bagian 4).

Sumber:

Di klien Ethereum di bawah Root Transaksi dan Root Penerimaan, Merkle Patricia Tries berisi semua data transaksi dan data penerimaan di blok. Artikel ini hanya akan berfokus pada semua transaksi dan tanda terima yang dapat diakses oleh sebuah node.

Informasi header blok dari blok 15001871 yang ditemukan melalui node Ethereum adalah sebagai berikut:

LogsBloom di header blok adalah struktur data utama, yang akan disebutkan nanti di artikel ini. Pertama mari kita mulai dengan data yang terletak di bawah Akar Transaksi, Trie Transaksi.

** Trie Transaksi Pohon Transaksi **

Trie Transaksi adalah kumpulan data yang menghasilkan transactionRoot dan merekam vektor permintaan transaksi. Vektor permintaan transaksi adalah potongan informasi yang diperlukan untuk menjalankan transaksi. Bidang data yang terdapat dalam transaksi adalah sebagai berikut:

  • Jenis - jenis transaksi (transaksi tradisional LegacyTxType, pengenalan AccessListTxType EIP-2930, pengenalan DynamicFeeTxType EIP-1559)
  • ChainId - ID rantai EIP155 dari transaksi
  • Data - input data transaksi
  • AccessList - daftar akses untuk transaksi
  • Gas - batas gas transaksi
  • GasPrice - harga gas dari transaksi
  • GasTipCap - premi insentif untuk penambang yang gas unit transaksinya melebihi biaya dasar untuk paket pertama, maxPriorityFeePerGas di Geth ditentukan oleh EIP1559
  • GasFeeCap - batas atas biaya gas per unit transaksi, maxFeePerGas di Geth (GasFeeCap ≥ baseFee + GasTipCap)
  • Nilai - jumlah Ethereum yang diperdagangkan
  • Nonce - nonce dari pencetus akun trading
  • Kepada - Alamat penerima transaksi. Untuk transaksi pembuatan kontrak, Untuk mengembalikan nilai nihil
  • RawSignaturues - Nilai tanda tangan V, R, S dari data transaksi

Setelah memahami bidang data di atas, mari kita lihat transaksi pertama blok 15001871

Melalui kueri ethclient Geth, Anda dapat melihat bahwa ChainId dan AccessList memiliki "omitempty", yang berarti bahwa jika bidang kosong, bidang tersebut akan dihilangkan dalam respons untuk mengurangi atau mempersingkat ukuran data serial.

sumber kode:

Transaksi ini mewakili transfer token USDT ke alamat 0xec23e787ea25230f74a3da0f515825c1d820f47a. Alamat Kepada adalah alamat kontrak ERC20 USDT 0xdac17f958d2ee523a2206206994597c13d831ec7. Melalui INPUT DATA, kita dapat melihat bahwa tanda tangan fungsi 0xa9059cbb sesuai dengan fungsi Transfer (Address, UINT256), dan 42.251 USDT (akurasi 6) ke 0x2b279b8 (45251000) ditransfer ke 0xEC23E787EA25230F ke 0xEC23E787EA25230F.74A Alamat 3DA0F515825C1D820F47A.

Anda mungkin memperhatikan bahwa struktur data transaksi ini tidak memberi tahu kami apa pun tentang hasil transaksi, jadi apakah transaksi berhasil? Berapa banyak konsumsi gasnya? Rekaman peristiwa mana yang dipicu? Pada titik ini kami akan memperkenalkan Penerimaan Trie.

Struk Trie

Sama seperti tanda terima belanja yang mencatat hasil transaksi, objek di Trie Tanda Terima melakukan hal yang sama untuk transaksi Ethereum tetapi juga mencatat beberapa detail tambahan. Kembali ke pertanyaan tentang tanda terima transaksi di atas, kami akan fokus pada log yang memicu kejadian berikut.

Permintaan data on-chain 0x311b lagi dan dapatkan tanda terima transaksinya. Saat ini, bidang-bidang berikut akan diperoleh:

sumber kode:

  • Jenis - jenis transaksi (LegacyTxType, AccessListTxType, DynamicFeeTxType)
  • PostState(root) - StateRoot, simpul akar dari pohon status yang dihasilkan setelah menjalankan transaksi, nilai terkait yang ditemukan pada gambar adalah 0x, mungkin karena EIP98
  • CumulativeGasUsed - Kumulatif total Gas yang dikonsumsi oleh transaksi ini dan semua transaksi sebelumnya di blok yang sama
  • Bloom(logsBloom) - Filter Bloom untuk log peristiwa, digunakan untuk mencari dan mengakses log peristiwa kontrak secara efisien di blockchain, memungkinkan node untuk dengan cepat mengambil apakah peristiwa tertentu terjadi di blok tanpa sepenuhnya mengurai blok Semua tanda terima transaksi di blok
  • Log - larik objek log yang berisi entri log yang dihasilkan oleh peristiwa kontrak yang dipicu selama eksekusi transaksi
  • TxHash - hash transaksi yang terkait dengan tanda terima
  • ContractAddress - Jika transaksi adalah untuk membuat kontrak, alamat dimana kontrak dikerahkan. Jika transaksi bukan pembuatan kontrak, tetapi seperti transfer atau interaksi dengan smart contract yang diterapkan, maka bidang ContractAddress akan kosong
  • GasDigunakan - gas yang dikonsumsi oleh transaksi ini
  • BlockNumber - nomor blok dari blok tempat transaksi ini terjadi
  • TransactionIndex - Indeks transaksi di dalam blok, indeks menentukan transaksi mana yang dijalankan terlebih dahulu. Transaksi ini berada di bagian atas blok, jadi indeks 0

Setelah mengetahui komposisi struk transaksi, mari kita lihat lebih dekat logsBloom dan log array log di struk transaksi.

Log Peristiwa

Melalui kode kontrak USDT di mainnet Ethereum, kita dapat melihat bahwa acara Transfer dideklarasikan pada baris 86 kontrak, dan dua parameter input memiliki kata kunci "diindeks".

(sumber kode:

Saat input peristiwa "diindeks", ini memungkinkan kita menemukan log dengan cepat melalui input tersebut. Misalnya, saat menggunakan indeks "dari" di atas, dimungkinkan untuk mendapatkan semua log peristiwa bertipe Transfer dengan alamat "dari" 0x5041ed759dd4afc3a72b8192c143f72f4724081a antara blok X dan Y. Kita juga dapat melihat bahwa ketika fungsi transfer dipanggil pada baris 138, log peristiwa diaktifkan. Perlu dicatat bahwa kontrak saat ini menggunakan soliditas versi sebelumnya, sehingga kata kunci emit hilang.

Kembali ke data on-chain yang diperoleh:

sumber kode:

Mari gali lebih dalam bidang alamat, topik, dan data.

Topik Tema

Topik adalah nilai indeks. Dari gambar di atas, kita dapat melihat bahwa ada 3 parameter indeks topik dalam data kueri pada rantai, sedangkan peristiwa Transfer hanya memiliki 2 parameter indeks (dari dan ke). Ini karena topik pertama selalu hash tanda tangan fungsi acara. Tanda tangan fungsi acara dalam contoh saat ini adalah Transfer(alamat, alamat, uint256). Dengan melakukan hashing dengan keccak256, kita mendapatkan hasil ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.

(Alat daring:

Saat kami menanyakan bidang dari seperti yang disebutkan di atas, tetapi pada saat yang sama ingin membatasi jenis log peristiwa kueri hanya untuk log peristiwa jenis Transfer, kami perlu memfilter berdasarkan jenis peristiwa dengan mengindeks tanda tangan peristiwa.

Kita dapat memiliki hingga 4 topik, setiap topik memiliki ukuran 32 byte (jika jenis parameter indeks lebih besar dari 32 byte (yaitu string dan byte), data sebenarnya tidak disimpan, tetapi intisari data keccak256 disimpan). Kita dapat mendeklarasikan 3 parameter indeks karena parameter pertama diambil oleh event signature. Namun ada situasi di mana topik pertama bukanlah tanda tangan acara hash. Ini adalah kasus saat mendeklarasikan acara anonim. Ini membuka kemungkinan untuk menggunakan 4 parameter indeks alih-alih 3 parameter sebelumnya, tetapi kehilangan kemampuan untuk mengindeks nama peristiwa. Keuntungan lain dari acara anonim adalah lebih murah untuk diterapkan karena tidak menerapkan topik tambahan. Topik lainnya adalah nilai indeks "dari" dan "ke" dari acara Transfer.

DataData

Bagian data berisi parameter yang tersisa (tidak diindeks) dari log peristiwa. Dalam contoh di atas, ada nilai 0x00000000000000000000000000000000000000000000000000000000002b279b8, yaitu 45251000 dalam desimal, yaitu jumlah $45,251 yang disebutkan di atas. Jika ada lebih banyak parameter seperti itu, mereka akan ditambahkan ke item data. Contoh di bawah ini akan menunjukkan kasus lebih dari 1 parameter yang tidak diindeks.

Contoh saat ini menambahkan bidang "pajak" tambahan ke acara Transfer. Misalkan pajak yang ditetapkan adalah 20%, maka nilai pajaknya harus 45251000 * 20% = 9050200, nilai heksadesimalnya adalah 0x8a1858, karena jenis angka ini adalah uint256, dan jenis datanya adalah 32 byte, Anda perlu nilai heksadesimal diisi dengan 32 byte, dan hasil item datanya adalah 0x00000000000000000000000000000000000000000000000000000000000002b279b80000000000000000000000000000000000000000000000 0000 00000000000000000000008a1858.

Alamat

Field alamat adalah alamat kontrak yang mengeluarkan event, catatan penting tentang field ini adalah akan diindeks meskipun tidak termasuk dalam bagian topik. Alasannya adalah peristiwa Transfer adalah bagian dari standar ERC20, yang berarti bahwa jika diperlukan untuk memfilter log peristiwa transfer ERC20, peristiwa transfer akan diperoleh dari semua kontrak ERC20. Dan dengan mengindeks alamat kontrak, pencarian dapat dipersempit ke kontrak/token tertentu, seperti contoh USDT.

Opcode Opcode

Akhirnya ada opcode LOG. Mulai dari LOG0 saat tidak ada topik hingga LOG4 saat ada 4 topik. LOG3 adalah apa yang kami gunakan dalam contoh kami. Berisi berikut ini:

  • offset - offset memori, menunjukkan posisi awal input bidang data
  • panjang - panjang data untuk dibaca dari memori
  • topik x(0 - 4) - nilai topik x

(Sumber:

offset dan panjang menentukan di mana data berada di bagian data di memori.

Setelah memahami struktur log dan bagaimana topik diindeks, mari kita pahami bagaimana item indeks dicari.

** Filter Mekar Filter Mekar **

Rahasia untuk mengindeks item yang dicari lebih cepat adalah filter Bloom.

Artikel Llimllib memiliki definisi dan penjelasan yang baik tentang struktur data ini.

"Filter Bloom adalah struktur data yang dapat digunakan untuk menentukan apakah suatu elemen ada dalam koleksi. Ini memiliki karakteristik operasi cepat dan jejak memori kecil. Biaya penyisipan dan kueri yang efisien adalah bahwa Filter Bloom adalah data berbasis probabilitas struktur: Ini hanya dapat memberi tahu kita bahwa suatu elemen pasti tidak ada di set atau mungkin di set. Struktur data yang mendasari filter Bloom adalah vektor bit.

Di bawah ini adalah contoh vektor bit. Sel putih mewakili bit dengan nilai 0, dan sel hijau mewakili bit dengan nilai 1.

Bit-bit ini disetel ke 1 dengan mengambil beberapa input dan hashing, nilai hash yang dihasilkan digunakan sebagai indeks bit di mana bit harus diperbarui. Vektor bit di atas adalah hasil penerapan 2 hash berbeda pada nilai "ethereum" untuk mendapatkan indeks 2 bit. Hash mewakili angka heksadesimal, dan untuk mendapatkan indeks, Anda mengambil angka dan mengubahnya menjadi nilai antara 0 dan 14. Ada banyak cara untuk melakukan ini, seperti mod 14.

Tinjauan

Dengan filter Bloom untuk transaksi, yaitu vektor bit, dapat di-hash di Ethereum untuk menentukan bit mana dalam vektor bit yang akan diperbarui Inputnya adalah bidang alamat dan topik log peristiwa. Mari tinjau logBloom di tanda terima transaksi, yang merupakan filter Bloom khusus transaksi. Suatu transaksi dapat memiliki banyak log, yang berisi alamat/topik dari semua log.

Jika Anda melihat kembali ke header blok, Anda akan menemukan logsBloom lainnya. Ini adalah filter Bloom untuk semua transaksi di dalam blok. Yang berisi semua alamat/topik di setiap log untuk setiap transaksi.

Filter Bloom ini diekspresikan dalam heksadesimal, bukan biner. Panjangnya 256 byte dan mewakili vektor 2048-bit. Jika kita mengacu pada contoh Llimllib di atas, panjang vektor bit kita adalah 15, dan indeks bit 2 dan 13 dibalik menjadi 1. Mari kita lihat apa yang kita dapatkan saat kita mengubahnya menjadi hex.

Meskipun representasi heksadesimal tidak terlihat seperti vektor bit, ia melakukannya di logsBloom.

Permintaan Kueri

Sebuah kueri telah disebutkan sebelumnya, "Temukan semua log peristiwa dari jenis Transfer yang alamat "dari"-nya adalah 0x5041ed759dd4afc3a72b8192c143f72f4724081a antara blok X dan Y". Kita bisa mendapatkan topik tanda tangan acara, yang merepresentasikan topik bertipe Transfer dan dari nilai (0x5041…), dan menentukan indeks bit mana di filter Bloom yang harus disetel ke 1.

Jika Anda menggunakan logsBloom di header blok, Anda dapat memeriksa untuk melihat apakah bit ini tidak disetel ke 1. Jika tidak, dapat ditentukan bahwa tidak ada log yang cocok dengan kondisi di blok tersebut. Dan jika bit-bit itu ditemukan disetel, kita tahu bahwa log yang cocok mungkin ada di blok. Tapi tidak sepenuhnya yakin, karena blok header logsBloom terdiri dari beberapa alamat dan topik. Log peristiwa lain mungkin memiliki bit kecocokan yang disetel. Inilah sebabnya mengapa filter Bloom adalah struktur data probabilistik. Semakin besar vektor bit, semakin kecil kemungkinan tabrakan indeks bit akan terjadi dengan log lainnya. Setelah Anda memiliki filter Bloom yang cocok, Anda dapat menggunakan metode yang sama untuk meminta logBloom untuk setiap tanda terima. Ketika kecocokan diperoleh, entri log aktual dapat dilihat untuk mengambil objek.

Jalankan operasi di atas pada blok X ke Y untuk menemukan dan mengambil semua log yang memenuhi kriteria dengan cepat. Beginilah cara kerja filter Bloom secara konseptual.

Sekarang mari kita lihat implementasi yang digunakan di Ethereum.

Penerapan geth - Filter Bloom

Sekarang setelah kita mengetahui cara kerja filter Bloom, mari kita pelajari bagaimana filter Bloom menyelesaikan penyaringan langkah demi langkah dari alamat / topik ke logBloom di blok yang sebenarnya.

Pertama-tama, dari definisi Ethereum Yellow Paper:

Sumber:

"Kami mendefinisikan fungsi filter Bloom M yang mengurangi entri log menjadi hash 256-byte tunggal:

di dalam adalah filter Bloom khusus yang menetapkan tiga bit pada 2048 dengan urutan byte yang berubah-ubah. Hal ini dilakukan dengan mengambil 11 bit yang lebih rendah dari masing-masing tiga pasang byte pertama dalam hash Keccak-256 dari urutan byte. "

Contoh dan referensi untuk implementasi klien Geth disediakan di bawah ini untuk menyederhanakan pemahaman definisi di atas.

Ini log transaksi yang kami lihat di Etherscan.

Topik pertama adalah tanda tangan peristiwa 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef dan mengubah nilai ini menjadi indeks bit yang harus diperbarui.

Di bawah ini adalah fungsi bloomValues dari basis kode Geth.

Fungsi ini menerima topik tanda tangan acara, seperti: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef dan data lainnya, serta mengembalikan indeks bit yang perlu diperbarui di filter Bloom.

sumber kode:

  1. Fungsi bloomValues menerima input topik (tanda tangan acara dalam contoh) dan hashbuf (array byte kosong dengan panjang 6).
  1. Lihat potongan Yellow Paper, "Tiga pasang byte pertama dalam hash Keccak-256 dari urutan byte". Tiga pasang byte ini adalah 6 byte, yang merupakan panjang hashbuf.

  2. Contoh data: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.

  1. Perintah sha antara baris 140 - 144 meng-hash data input dan memuat output ke hashbuf.
  1. Hasil heksadesimal dari output sha menggunakan keccak256 adalah (saat menggunakan keccak 256 sebagai tanda tangan fungsi, inputnya adalah tipe teks, tetapi di sini adalah tipe heksadesimal): ada389e1fc24a8587c776340efb91b36e675792ab631816100d55df0b5cf3cbc.

  1. Isi hasbuf saat ini [ad, a3, 89, e1, fc, 24] (heksadesimal). Setiap karakter heksadesimal mewakili 4 bit.

3 Hitung v1.

1)hashbuf [1] = 0xa3 = 10100011 untuk bitwise DAN dengan 0x7. 0x7 = 00000111.

  1. Sebuah byte terdiri dari 8 bit, jika Anda ingin mendapatkan indeks bit, Anda perlu memastikan bahwa nilai yang diperoleh antara 0 dan 7 dari array indeks nol. Gunakan bitwise DAN untuk hashbuf [1] Dibatasi untuk nilai antara 0 dan 7. Dihitung dalam contoh, 10100011 & 00000111 = 00000011 = 3.

  2. Nilai bit index ini digunakan dengan operator bit shift, yaitu digeser 3 bit ke kiri, menghasilkan 8 bit byte index 00001000, untuk membuat flipped bit.

  3. v1 adalah seluruh byte daripada indeks bit yang sebenarnya, karena nilai ini akan di-ORed bitwise pada filter Bloom nanti. Operasi ATAU akan memastikan bahwa semua bit yang sesuai dalam filter Bloom juga dibalik.

  1. Kami sekarang memiliki nilai byte, tetapi kami masih membutuhkan indeks byte. Filter Bloom memiliki panjang 256 byte (2048 bit), jadi kita perlu mengetahui byte mana untuk menjalankan bitwise OR. Nilai i1 mewakili indeks byte ini.
  1. Masukkan hashbuf melalui urutan byte uint16 big-endian, yang membuatnya membatasi 2 byte pertama dari bit array, yaitu 0xada3 = 1010110110100011 dalam contoh.

  2. Bitwise DAN nilai ini dengan 0x7ff = 0000011111111111. Ada 11 bit di mana 0x7ff diatur ke 1. Seperti disebutkan dalam kertas kuning, "ini dilakukan dengan mengambil 11 bit lebih rendah dari masing-masing dari tiga pasang pertama". Ini akan menghasilkan nilai 0000010110100011 yaitu 1010110110100011 & 0000011111111111.

  3. Kemudian geser nilainya ke kanan sebanyak 3 bit. Ini mengubah angka 11 digit menjadi angka 8 digit. Kami menginginkan indeks byte, dan panjang byte filter Bloom adalah 256, sehingga nilai indeks byte harus berada dalam kisaran ini. Dan angka 8-bit dapat berupa nilai antara 0 dan 255. Dalam contoh kita, nilai ini adalah 0000010110100011 digeser ke kanan sebanyak 3 bit 10110100 = 180.

  4. Hitung indeks byte kami dengan BloomByteLength, mengetahui itu adalah 256 dikurangi 180 yang dihitung, dikurangi 1. Kurangi 1 untuk mempertahankan hasil antara 0 dan 255. Ini memberi kami indeks byte untuk diperbarui, yang dalam hal ini ternyata adalah byte 75, yang merupakan cara kami menghitung i1.

  1. Perbarui indeks bit 3 pada byte ke-75 dari filter Bloom (0 adalah indeks sehingga bit ke-4), yang dapat dilakukan dengan melakukan operasi bitwise OR dari v1 pada byte ke-75 pada filter Bloom.
  1. Kami hanya membahas pasangan byte pertama 0xada3, yang dilakukan lagi untuk pasangan byte 2 dan 3. Setiap alamat/topik akan memperbarui 3 bit dalam vektor 2048 bit. Seperti disebutkan dalam Yellow Paper, "Filter Bloom menetapkan tiga bit pada 2048 dengan urutan byte yang berubah-ubah".

  2. Byte pair 2 memperbarui status indeks bit 1 dalam byte 195 (dijalankan sesuai dengan prosedur 3 dan 4, hasilnya ditunjukkan pada gambar).

  3. Pasangan byte 3 pembaruan status indeks bit 4 dalam byte 123.

  4. Jika bit yang akan diperbarui sudah dibalik oleh topik lain, maka akan tetap seperti itu. Akan berubah menjadi 1 jika tidak.

Melalui proses operasi di atas, dapat ditentukan bahwa topik tanda tangan acara akan membalikkan bit-bit berikut dalam filter Bloom:

  • Bit indeks 3 dalam byte 75
  • bit indeks 1 dalam byte 195
  • bit indeks 4 dalam byte 123

Melihat logBlooms dalam tanda terima transaksi, dikonversi ke biner, memverifikasi bahwa indeks bit ini telah ditetapkan.

Sementara itu, bagi para pembaca yang tertarik mempelajari lebih lanjut tentang penerapan log search dan Bloom filter, dapat merujuk pada artikel BloomBits Trie.

Pada titik ini, diskusi mendalam kami tentang seri artikel EVM telah berakhir, dan kami akan membawakan Anda lebih banyak artikel teknis berkualitas tinggi di masa mendatang.

Lihat Asli
Konten ini hanya untuk referensi, bukan ajakan atau tawaran. Tidak ada nasihat investasi, pajak, atau hukum yang diberikan. Lihat Penafian untuk pengungkapan risiko lebih lanjut.
  • Hadiah
  • Komentar
  • Bagikan
Komentar
0/400
Tidak ada komentar
  • Sematkan
Perdagangkan Kripto Di Mana Saja Kapan Saja
qrCode
Pindai untuk mengunduh aplikasi Gate.io
Komunitas
Indonesia
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • ไทย
  • Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)