๐Ÿš€ Quick Start

Quick Start

Add flash loan verification to your Solana program in 3 steps. Works with Anchor and native programs.

1. Install

Add vaea-flash-ctx to your program's Cargo.toml:

toml
[dependencies]
vaea-flash-ctx = "0.1"

No Anchor dependency required. The crate only depends on solana-program.

2. Add Accounts

Your instruction needs two additional accounts: the FlashState PDA and the instructions sysvar.

rust
#[derive(Accounts)]
pub struct MyFlashAction<'info> {
    #[account(mut)]
    pub user: Signer<'info>,

    /// The VAEA FlashState PDA โ€” read-only
    /// CHECK: Ownership and derivation verified by vaea_flash_ctx::verify()
    pub flash_state: AccountInfo<'info>,

    /// Instructions sysvar for introspection
    /// CHECK: Must be sysvar::instructions::ID
    #[account(address = anchor_lang::solana_program::sysvar::instructions::ID)]
    pub sysvar_instructions: AccountInfo<'info>,

    // ... your other accounts
}

3. Call verify()

In your instruction handler, call verify() with the two accounts. It returns a FlashContext with the loan details:

rust
pub fn my_flash_handler(ctx: Context<MyFlashAction>) -> Result<()> {
    // Verify flash loan โ€” 0 CPI, ~2K CU
    let flash = vaea_flash_ctx::verify(
        &ctx.accounts.flash_state,
        &ctx.accounts.sysvar_instructions,
    )?;

    // Use the verified loan context
    msg!("Borrower: {}", flash.payer);
    msg!("Amount: {} native of {}", flash.amount, flash.token_mint);
    msg!("Fee: {} native", flash.fee);

    // Your protocol logic โ€” full 4-level CPI budget available
    // e.g. withdraw, swap, repay, rebalance...

    Ok(())
}
๐Ÿ’ก Tip
That's it. Your program can now detect and verify flash loans. The flash variable contains everything you need โ€” amount, token, borrower, fee.

Transaction Layout

A flash loan transaction that calls your program looks like this:

text
IX 0:  ComputeBudget.set_limit(400_000)
IX 1:  VAEA.begin_flash(token, amount)         โ† creates FlashState PDA
IX 2:  YourProtocol.my_flash_handler(...)       โ† reads PDA, ZERO CPI
IX 3:  VAEA.end_flash()                         โ† verifies repayment, closes PDA

The user (or their bot) builds this transaction using the VAEA SDK. Your program only needs to call verify() โ€” the SDK handles everything else.

Native Program (No Anchor)

If you're not using Anchor, pass the raw AccountInfo references directly:

rust
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg};
use vaea_flash_ctx;

pub fn process_instruction(accounts: &[AccountInfo]) -> ProgramResult {
    let flash_state = &accounts[0];  // FlashState PDA
    let sysvar_ix = &accounts[1];    // Instructions sysvar

    let flash = vaea_flash_ctx::verify(flash_state, sysvar_ix)?;

    msg!("Flash verified: {} of {}", flash.amount, flash.token_mint);

    // Your logic here...
    Ok(())
}

Test on Devnet

Deploy your program to devnet and use the VAEA SDK to send a flash loan transaction that calls your program:

typescript
import { VaeaFlash } from '@vaea/flash';

const flash = new VaeaFlash({ connection, wallet });

await flash.executeLocal({
  token: 'SOL',
  amount: 10,
  onFunds: async (ixs) => {
    // Add your program's instruction between borrow and repay
    ixs.push(myProtocolInstruction);
    return ixs;
  },
});

If verify() succeeds in the program logs, the integration is working.

โ„น๏ธ Note
Program ID (devnet): HoYiwkNB7a3gmZXEkTqLkborNDc976vKEUAzBm8YpK5E
ALT: DjncKSi9KqtnFx6hFYa7ARmwJ7B4Y7UH3XpR2XEuXNJr
โš ๏ธ Devnet Only
Mainnet โ€” April 2026
๐Ÿ”