Anchor
Pinjaman Kilat Anchor

Pinjaman Kilat Anchor

27 Graduates

Pinjam

Instruksi pinjam adalah bagian pertama dari sistem flash loan kita. Instruksi ini melakukan tiga langkah penting untuk memastikan peminjaman yang aman dan atomik:

  1. Transfer dana: Memindahkan borrow_amount yang diminta dari treasury protokol ke akun peminjam

  2. Verifikasi pembayaran kembali: Menggunakan introspeksi instruksi untuk memastikan bahwa instruksi pembayaran kembali yang valid ada di akhir transaksi

Transfer Dana

Pertama, kita mengimplementasikan transfer dana yang sebenarnya dengan validasi yang tepat:

rust
// Make sure we're not sending in an invalid amount that can crash our Protocol
require!(borrow_amount > 0, ProtocolError::InvalidAmount);

// Derive the Signer Seeds for the Protocol Account
let seeds = &[
    b"protocol".as_ref(),
    &[ctx.bumps.protocol]
];
let signer_seeds = &[&seeds[..]];

// Transfer the funds from the protocol to the borrower
transfer(
    CpiContext::new_with_signer(
        ctx.accounts.token_program.to_account_info(), 
        Transfer {
            from: ctx.accounts.protocol_ata.to_account_info(),
            to: ctx.accounts.borrower_ata.to_account_info(),
            authority: ctx.accounts.protocol.to_account_info(),
        }, 
        signer_seeds
    ), 
    borrow_amount
)?;

Kode ini memastikan kita mentransfer jumlah yang valid dan menggunakan Program Derived Address (PDA) protokol untuk mengotorisasi transfer.

Introspeksi Instruksi

Sekarang bagian yang kritis untuk keamanan: menggunakan introspeksi instruksi untuk memverifikasi struktur transaksi dan memastikan flash loan kita akan dibayar kembali.

Kita mulai dengan mengakses sysvar instructions, yang berisi informasi tentang semua instruksi dalam transaksi saat ini:

rust
/*
    Instruction Introspection

    This is the primary means by which we secure our program,
    enforce atomicity while making a great UX for our users.
*/

let ixs = ctx.accounts.instructions.to_account_info();

Akhirnya, kita melakukan pemeriksaan yang paling penting: memastikan bahwa instruksi terakhir dalam transaksi adalah instruksi pembayaran kembali yang valid:

  • Kita mulai dengan memeriksa posisi instruksi pinjam untuk memastikan itu adalah satu-satunya

  • Kemudian kita memeriksa jumlah instruksi dan memastikan bahwa kita memuat instruksi terakhir dari transaksi

  • Lalu kita memverifikasi bahwa itu adalah instruksi pembayaran kembali dengan memverifikasi ID program dan diskriminator instruksi

  • Kita selesai dengan memverifikasi bahwa ATA yang diteruskan dalam instruksi pembayaran kembali sama dengan yang kita teruskan dalam instruksi Borrow kita

rust
/*
    Repay Instruction Check

    Make sure that the last instruction of this transaction is a repay instruction
*/

// Check if this is the first instruction in the transaction.
let current_index = load_current_index_checked(&ctx.accounts.sysvar_instructions)?;
require_eq!(current_index, 0, ProtocolError::InvalidIx); 

// Check how many instruction we have in this transaction
let instruction_sysvar = ixs.try_borrow_data()?;
let len = u16::from_le_bytes(instruction_sysvar[0..2].try_into().unwrap());

// Ensure we have a repay ix
if let Ok(repay_ix) = load_instruction_at_checked(len as usize - 1, &ixs) {

    // Instruction checks
    require_keys_eq!(repay_ix.program_id, ID, ProtocolError::InvalidProgram);
    require!(repay_ix.data[0..8].eq(instruction::Repay::DISCRIMINATOR), ProtocolError::InvalidIx);

    // We could check the Wallet and Mint separately but by checking the ATA we do this automatically
    require_keys_eq!(repay_ix.accounts.get(3).ok_or(ProtocolError::InvalidBorrowerAta)?.pubkey, ctx.accounts.borrower_ata.key(), ProtocolError::InvalidBorrowerAta);
    require_keys_eq!(repay_ix.accounts.get(4).ok_or(ProtocolError::InvalidProtocolAta)?.pubkey, ctx.accounts.protocol_ata.key(), ProtocolError::InvalidProtocolAta);

} else {
    return Err(ProtocolError::MissingRepayIx.into());
}
Next PageLunaskan
ATAU LANGSUNG KE TANTANGAN
Siap mengambil tantangan?
Daftar Isi
Lihat Sumber
Blueshift © 2025Commit: e573eab