
Assembly Slippage
Dalam unit ini kita akan menggunakan sBPF Assembly untuk membuat instruksi pemeriksaan slippage dasar. Dengan menyertakan instruksi tersebut pada indeks terakhir dalam array instruksi kita, kita dapat membuat perlindungan tambahan sebagai pertahanan terakhir terhadap bug kontrak pintar, atau kontrak bit flip yang berbahaya.
Ada beberapa properti pemeriksaan slippage yang menjadikannya kandidat ideal untuk assembly:
Kasus penggunaan tunggal dan terbatas
Tidak perlu melakukan pemeriksaan penandatangan/akun
Hanya dapat meningkatkan keamanan
Jika Anda belum familiar dengan cara menulis program assembly, ikuti kursus pengantar Assembly
Desain Program
Program kita mengimplementasikan operasi sederhana namun penting: memvalidasi bahwa akun token memiliki saldo yang cukup sebelum melanjutkan transaksi. Pola ini muncul di mana-mana dalam DeFi—dari pertukaran AMM hingga protokol peminjaman.
Program ini mengharapkan:
Satu akun SPL token dalam array akun
Jumlah 8-byte dalam data instruksi
Mengembalikan sukses jika saldo ≥ jumlah, error jika tidak
Offset Memori
Program sBPF menerima data akun sebagai region memori yang berdekatan. Konstanta ini mendefinisikan offset byte. Dengan mengasumsikan bahwa program kita hanya akan menerima satu akun, dan itu akan menjadi Akun Token SPL, dimungkinkan untuk secara statis menurunkan offset ini sebagai:
.equ TOKEN_ACCOUNT_BALANCE, 0x00a0
.equ MINIMUM_BALANCE, 0x2918TOKEN_ACCOUNT_BALANCE (0x00a0): menunjuk ke field saldo dalam data akun SPL Token. Akun token mengikuti tata letak standar di mana saldo (8 byte, little-endian) berada pada offset 160.MINIMUM_BALANCE (0x2918): menentukan lokasi di mana Solana menempatkan payload data instruksi Anda. Offset ini adalah bagian dari struktur info akun runtime.
Tidak seperti bahasa tingkat tinggi yang mengabstraksi tata letak memori, assembly mengharuskan Anda mengetahui persis di mana setiap bagian data berada.
Entrypoint dan Validasi Awal
.globl entrypoint
entrypoint:
ldxdw r3, [r1+MINIMUM_BALANCE] // Get amount from IX data
ldxdw r4, [r1+TOKEN_ACCOUNT_BALANCE] // Get balance from token accountSetiap program sBPF dimulai pada simbol global .entrypoint. Runtime Solana menyediakan data akun dan instruksi melalui register r1.
Instruksi ldxdw memuat (ldx) nilai 8-byte (double word, dx) dari memori ke dalam register. Berikut yang terjadi:
ldxdw r3, [r1+MINIMUM_BALANCE]: menghitung alamat memori yang berisi jumlah yang kita butuhkan. Nilai tersebut dimuat ke dalamr3.ldxdw r4, [r1+TOKEN_ACCOUNT_BALANCE]: menunjuk ke bidang saldo akun token. Nilai 64-bit ini masuk ker4.
Kedua operasi tersebut adalah zero-copy: kita membaca langsung dari data akun tanpa overhead deserialisasi.
Logika Kondisional dan Percabangan
jge r3, r4, end // Skip to exit if balance is validInstruksi jge (jump if greater or equal) membandingkan r3 (jumlah yang dibutuhkan) dengan r4 (saldo yang tersedia). Jika r3 >= r4, kita melompat ke label end; seperti early return.
Jika kondisi gagal, eksekusi berlanjut ke jalur penanganan kesalahan. Pola branch-on-condition ini adalah cara assembly mengimplementasikan logika if/else.
Penanganan Kesalahan dan Logging
lddw r1, e // Load error message address
lddw r2, 17 // Load length of error message
call sol_log_ // Log out error message
lddw r0, 1 // Return error code 1Ketika validasi gagal, kita mencatat pesan kesalahan yang dapat dibaca manusia sebelum mengakhiri:
lddwmemuat nilai langsung, dalam hal ini alamat string kesalahan kita, yang berada di bagian.rodata, dan panjangnya (17 byte untuk "Slippage exceeded").call sol_log_memanggil syscall logging Solana. Runtime membaca pesan dari memori dan menambahkannya ke log transaksi.Kemudian kita memuat
1ke dalamr0untuk menandakan kegagalan program. Runtime akan membatalkan transaksi dan mengembalikan kode kesalahan ini.
Program Termination
end:
exitInstruksi exit menghentikan eksekusi program dan mengembalikan kontrol ke runtime Solana. Nilai dalam r0 menjadi kode keluar program (0 untuk sukses, bukan nol untuk kesalahan).
Tidak seperti bahasa tingkat tinggi dengan pembersihan otomatis, program assembly harus keluar secara eksplisit. Jatuh dari akhir kode Anda adalah perilaku yang tidak terdefinisi.
Data hanya-baca
.rodata
e: .ascii "Slippage exceeded"Bagian .rodata (data hanya-baca) berisi string pesan kesalahan kita.
Conclusion
Program kecil ini menyelesaikan apa yang mungkin membutuhkan puluhan CU dengan Rust hanya dengan 4 CUs dalam kasus berhasil, 6 CUs dalam kasus gagal, atau 106 CUs dalam kasus gagal yang mencatat pesan kesalahan.
Timbal baliknya adalah kita harus memahami tata letak memori, konvensi pemanggilan, dan penanganan kesalahan pada tingkat terendah. Tetapi untuk operasi yang kritis terhadap kinerja, manfaatnya sering kali membenarkan upaya tersebut.