Rust
Pinocchio Flash Loan

Pinocchio Flash Loan

Pinocchio Flash Loan

Pinocchio Flash Loan

Pinocchio Flash Loan

A introspecção de instruções é um recurso poderoso que permite a um programa de blockchain examinar e analisar outras instruções dentro do mesmo bundle de transação. Isso inclui instruções que ainda não foram executadas, dando ao seu programa a capacidade de "olhar adiante" e tomar decisões baseadas no que acontecerá mais tarde na transação.

Pense nisso como ter visão de raio-X para transações: seu programa pode ver através de toda a transação para entender a sequência completa de operações antes de decidir como prosseguir.

A aplicação mais interessante da introspecção de instruções são os flash loans. Estes são um tipo único de empréstimo que existe apenas dentro dos limites de uma única transação.

Veja como os flash loans funcionam:

  • Borrow: No início de uma transação, você pode pegar emprestado instantaneamente uma grande quantidade de capital usando uma instrução de loan

  • Use: Você pode usar este capital emprestado para negociação, arbitragem ou outras operações dentro da mesma transação

  • Repay: Antes que a transação termine, você deve devolver o empréstimo mais uma pequena taxa usando uma instrução de repay

O insight fundamental é que os flash loans dependem da natureza atômica das transações em blockchain. Se qualquer parte da transação falhar (incluindo o reembolso), toda a transação é revertida como se nunca tivesse acontecido. Isso significa que o credor tem risco zero: ou recebe o reembolso, ou o empréstimo nunca aconteceu de fato.

Neste desafio, você criará um programa simples de flash loan que demonstra a introspecção de instruções em ação. O programa examinará dados e contas de instruções em diferentes instruções dentro da mesma transação para garantir que os termos do empréstimo sejam cumpridos.

Se você é novo em introspecção de instruções, recomendamos começar com o Curso de Instruction Introspection para entender os conceitos fundamentais usados neste programa.

Instalação

Antes de começar, certifique-se de que Rust e Pinocchio estejam instalados. Então, execute o seguinte no seu terminal:

# criar workspace
cargo new blueshift_pinocchio_flash_loan --lib --edition 2021
cd blueshift_pinocchio_flash_loan

Adicione pinocchio, pinocchio-system e pinocchio-token:

cargo add pinocchio pinocchio-system pinocchio-token

Declare os tipos de crate no Cargo.toml para gerar artefatos de deploy em target/deploy:

toml
[lib]
crate-type = ["lib", "cdylib"]

Agora você está pronto para escrever seu programa de flash loan.

Template

Desta vez, vamos dividir o programa em pequenos módulos focados em vez de colocar tudo no lib.rs. A árvore de pastas ficará mais ou menos assim:

text
src
├── instructions
│       ├── helpers.rs
│       ├── loan.rs
│       ├── mod.rs
│       └── repay.rs
├── lib.rs

Nota: Lembre-se de alterar o program ID para 22222222222222222222222222222222222222222222 já que usamos isso internamente para testar seu programa.

O entrypoint no lib.rs é muito parecido com o que cobrimos no Curso de Introdução ao Pinocchio.

rust
use pinocchio::{account_info::AccountInfo, entrypoint, program_error::ProgramError, pubkey::Pubkey, ProgramResult};
entrypoint!(process_instruction);

pub mod instructions;
pub use instructions::*;

// 22222222222222222222222222222222222222222222
pub const ID: Pubkey = [
    0x0f, 0x1e, 0x6b, 0x14, 0x21, 0xc0, 0x4a, 0x07, 
    0x04, 0x31, 0x26, 0x5c, 0x19, 0xc5, 0xbb, 0xee, 
    0x19, 0x92, 0xba, 0xe8, 0xaf, 0xd1, 0xcd, 0x07, 
    0x8e, 0xf8, 0xaf, 0x70, 0x47, 0xdc, 0x11, 0xf7, 
];

fn process_instruction(
    _program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    match instruction_data.split_first() {
        Some((Loan::DISCRIMINATOR, data)) => Loan::try_from((data, accounts))?.process(),
        Some((Repay::DISCRIMINATOR, _)) => Repay::try_from(accounts)?.process(),
        _ => Err(ProgramError::InvalidInstructionData)
    }
}

Helpers

Antes de mergulhar nas instruções loan e repay, vamos examinar o helpers.rs:

rust
#[repr(C, packed)]
pub struct LoanData {
    pub protocol_token_account: [u8; 32],
    pub balance: u64,
}

pub fn get_token_amount(data: &[u8], account: &AccountInfo) ->  Result<u64, ProgramError> {
    if !account.is_owned_by(&pinocchio_token::ID) {
        return Err(PinocchioError::InvalidOwner.into());
    }

    if account.data_len().ne(&pinocchio_token::state::TokenAccount::LEN) {
        return Err(PinocchioError::InvalidAccountData.into());
    }

    if data.len() != pinocchio_token::state::TokenAccount::LEN {
        return Err(ProgramError::InvalidAccountData);
    }

    Ok(u64::from_le_bytes(data[64..72].try_into().unwrap()))
}

Este arquivo é direto. Contém uma struct LoanData, que usaremos para armazenar temporariamente dados de empréstimo em uma conta antes que o empréstimo seja devolvido. Também fornece uma função helper get_token_amount() para ler a quantidade de tokens de uma conta.

Blueshift © 2026Commit: 1b88646