Anchor Flash Loan

Introspeksi instruksi adalah fitur yang kuat yang memungkinkan program blockchain untuk memeriksa dan menganalisis instruksi lain dalam bundel transaksi yang sama. Ini termasuk instruksi yang belum dieksekusi, memberikan program Anda kemampuan untuk "melihat ke depan" dan membuat keputusan berdasarkan apa yang akan terjadi nanti dalam transaksi.
Bayangkan seperti memiliki penglihatan sinar-X untuk transaksi: program Anda dapat melihat melalui seluruh transaksi untuk memahami urutan operasi yang lengkap sebelum memutuskan bagaimana melanjutkan.
Aplikasi paling menarik dari introspeksi instruksi adalah flash loan. Ini adalah jenis pinjaman unik yang hanya ada dalam batas-batas transaksi tunggal.
Begini cara kerja flash loan:
Pinjam: Pada awal transaksi, Anda dapat langsung meminjam sejumlah besar modal menggunakan instruksi
loanGunakan: Anda dapat menggunakan modal pinjaman ini untuk trading, arbitrase, atau operasi lain dalam transaksi yang sama
Bayar kembali: Sebelum transaksi berakhir, Anda harus membayar kembali pinjaman plus sedikit biaya menggunakan instruksi
repay
Wawasan utamanya adalah bahwa flash loan bergantung pada sifat atomik transaksi blockchain. Jika ada bagian dari transaksi yang gagal (termasuk pembayaran kembali), seluruh transaksi akan dibatalkan seolah-olah tidak pernah terjadi. Ini berarti pemberi pinjaman tidak memiliki risiko sama sekali: mereka mendapatkan pembayaran kembali, atau pinjaman tidak pernah benar-benar terjadi.
Dalam tantangan ini, Anda akan membuat program flash loan sederhana yang mendemonstrasikan introspeksi instruksi dalam tindakan. Program akan memeriksa data instruksi dan akun di berbagai instruksi dalam transaksi yang sama untuk memastikan persyaratan pinjaman terpenuhi.
Jika Anda baru mengenal introspeksi instruksi, kami menyarankan untuk memulai dengan Kursus Introspeksi Instruksi untuk memahami konsep dasar yang digunakan dalam program ini.
Installation
Sebelum memulai, pastikan Anda telah menginstal Rust dan Anchor. Jika Anda membutuhkan petunjuk pengaturan, lihat dokumentasi resmi anchor. Kemudian di terminal Anda jalankan:
anchor init blueshift_anchor_flash_loanTambahkan dependensi yang diperlukan:
anchor-spl: Menyediakan utilitas untuk bekerja dengan token SPL (standar token Solana)
cd blueshift_anchor_flash_loan
cargo add anchor-splSekarang Anda siap untuk mulai membangun program flash loan Anda!
Template
Mari kita bangun dasar program flash loan kita dengan menyiapkan struktur dasar, akun, dan penanganan kesalahan yang akan digunakan oleh instruksi peminjaman dan pembayaran kembali.
Kita akan mengimplementasikan semuanya di lib.rs karena kita hanya memiliki dua instruksi yang berbagi struktur akun yang sama. Berikut adalah template awal kita dengan semua komponen penting:
use anchor_lang::prelude::*;
use anchor_spl::{
token::{Token, TokenAccount, Mint, Transfer, transfer},
associated_token::AssociatedToken
};
use anchor_lang::{
Discriminator,
solana_program::sysvar::instructions::{
ID as INSTRUCTIONS_SYSVAR_ID,
load_instruction_at_checked
}
};
declare_id!("22222222222222222222222222222222222222222222");
#[program]
pub mod blueshift_anchor_flash_loan {
use super::*;
pub fn borrow(ctx: Context<Loan>, borrow_amount: u64) -> Result<()> {
// borrow logic...
Ok(())
}
pub fn repay(ctx: Context<Loan>) -> Result<()> {
// repay logic...
Ok(())
}
}
#[derive(Accounts)]
pub struct Loan<'info> {
// loan accounts...
}
#[error_code]
pub enum ProtocolError {
// error enum..
}Catatan: ingat untuk mengubah ID program menjadi 22222222222222222222222222222222222222222222 karena kita menggunakan ini di balik layar untuk menguji program Anda.
Accounts
Karena instruksi borrow dan repay bekerja dengan akun yang sama, kita dapat membuat satu konteks Loan yang melayani kedua fungsi tersebut. Ini membuat kode kita lebih mudah dikelola dan dipahami.
Struct akun Loan kita membutuhkan komponen-komponen berikut:
borrower: pengguna yang meminta flash loan.protocol: Program Derived Address (PDA) yang memiliki pool likuiditas protokol.mint: token spesifik yang dipinjam.borrower_ata: Associated Token Account peminjam yang akan menerima token yang dipinjam.protocol_ata: Associated Token Account protokol yang akan menyediakan token yang dipinjam.instructions: akun Instructions Sysvar untuk introspeksi.token_program,associated_token_program, dansystem_program: program yang diperlukan untuk program.
Berikut cara kami mendefinisikan struct akun:
#[derive(Accounts)]
pub struct Loan<'info> {
#[account(mut)]
pub borrower: Signer<'info>,
#[account(
seeds = [b"protocol".as_ref()],
bump,
)]
pub protocol: SystemAccount<'info>,
pub mint: Account<'info, Mint>,
#[account(
init_if_needed,
payer = borrower,
associated_token::mint = mint,
associated_token::authority = borrower,
)]
pub borrower_ata: Account<'info, TokenAccount>,
#[account(
mut,
associated_token::mint = mint,
associated_token::authority = protocol,
)]
pub protocol_ata: Account<'info, TokenAccount>,
#[account(address = INSTRUCTIONS_SYSVAR_ID)]
/// CHECK: InstructionsSysvar account
instructions: UncheckedAccount<'info>,
pub token_program: Program<'info, Token>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub system_program: Program<'info, System>
}Seperti yang Anda lihat, akun yang diperlukan untuk instruksi ini dan batasannya cukup sederhana:
protocol: menggunakanseeds = [b"protocol".as_ref()]untuk membuat alamat deterministik yang memiliki semua likuiditas protokol. Ini memastikan hanya program kita yang dapat mengontrol dana tersebut.borrower_ata: menggunakaninit_if_neededkarena peminjam mungkin belum memiliki akun token terkait untuk token spesifik ini. Batasan ini secara otomatis membuat akun jika diperlukan.protocol_ata: harus sudah ada dan dapat diubah karena kita akan mentransfer token darinya. Batasanassociated_token::authority = protocolmemastikan hanya PDA protokol yang dapat mengotorisasi transfer.instructions: menggunakan batasanaddressuntuk memverifikasi bahwa kita mengakses akun sistem yang benar yang berisi data instruksi transaksi.
Errors
Flash loan memerlukan validasi yang tepat pada beberapa tahap, jadi kita membutuhkan penanganan kesalahan yang komprehensif. Berikut enum kesalahan lengkap kita:
#[error_code]
pub enum ProtocolError {
#[msg("Invalid instruction")]
InvalidIx,
#[msg("Invalid instruction index")]
InvalidInstructionIndex,
#[msg("Invalid amount")]
InvalidAmount,
#[msg("Not enough funds")]
NotEnoughFunds,
#[msg("Program Mismatch")]
ProgramMismatch,
#[msg("Invalid program")]
InvalidProgram,
#[msg("Invalid borrower ATA")]
InvalidBorrowerAta,
#[msg("Invalid protocol ATA")]
InvalidProtocolAta,
#[msg("Missing repay instruction")]
MissingRepayIx,
#[msg("Missing borrow instruction")]
MissingBorrowIx,
#[msg("Overflow")]
Overflow,
}Dengan dasar ini, kita siap untuk mengimplementasikan logika inti untuk instruksi flash loan kita. Struktur akun memastikan penanganan token yang tepat, sementara sistem kesalahan memberikan umpan balik yang jelas untuk debugging dan validasi keamanan.