Rust
Prêt Flash avec Pinocchio

Prêt Flash avec Pinocchio

14 Graduates

Prêt Flash avec Pinocchio

Flash Loan avec Pinocchio

Pinocchio Flash Loan

L'introspection des instructions est une fonctionnalité puissante qui permet à un programme d'examiner et d'analyser d'autres instructions au sein de la même transactions. Cela inclut les instructions qui n'ont pas encore été exécutées, donnant à votre programme la possibilité de "regarder dans le futur" et de prendre des décisions basées sur ce qui se passera plus tard dans la transaction.

C'est un peu comme si vous aviez une vision à rayons X pour les transactions : votre programme peut voir l'ensemble de la transaction pour comprendre la séquence complète des opérations avant de décider de la marche à suivre.

L'application la plus pertinente de l'introspection des instructions est le prêt flash. Il s'agit d'un type de prêt unique qui intervient au sein d'une seule et même transaction.

Voici comment fonctionnent les prêts flash :

  • Emprunt (Borrow): Au début d'une transaction, vous pouvez instantanément emprunter un montant important de capital en utilisant l'instruction loan

  • Utilisation (Use): Vous pouvez utiliser ce capital emprunté pour le trading, l'arbitrage ou d'autres opérations au sein de la même transaction

  • Remboursement (Repay): Avant la fin de la transaction, vous devez rembourser le prêt ainsi que des frais faibles à l'aide de l'instruction repay

L'idée clé est que les prêts flash reposent sur la nature atomique des transactions. Si une partie de la transaction échoue (y compris le remboursement), la totalité de la transaction est annulée comme si elle n'avait jamais eu lieu. Cela signifie que le risque du prêteur est nul : soit il est remboursé, soit le prêt n'a jamais eu lieu.

Dans ce challenge, vous créerez un programme simple de prêt flash qui illustrera l'introspection des instructions. Le programme examinera les données et les comptes des différentes instructions d'une même transaction afin de s'assurer que les conditions du prêt sont respectées.

Si vous êtes novice en matière d'introspection des instructions, nous vous recommandons de commencer par le Cours sur l'introspection des instructions pour comprendre les concepts fondamentaux utilisés dans ce programme.

Installation

Avant de commencer, assurez-vous que Rust et Pinocchio sont installés. Ensuite, exécutez la commande suivante dans votre terminal :

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

Ajoutez pinocchio, pinocchio-system, et pinocchio-token:

cargo add pinocchio pinocchio-system pinocchio-token

Déclarez les types de crate dans Cargo.toml pour générer les artefacts de déploiement dans target/deploy :

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

Vous êtes maintenant prêt à écrire votre programme de prêt flash.

Modèle

Cette fois, nous allons diviser le programme en petits modules dédiés au lieu de tout mettre dans le lib.rs. L'arborescence des dossiers se présente sensiblement comme suit :

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

Remarque : n'oubliez pas de changer l'ID du programme en 22222222222222222222222222222222222222222222 puisque nous l'utilisons pour tester votre programme.

Le point d'entrée de lib.rs est très similaire à ce que nous avons abordé dans le Cours d'Introduction à 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)
    }
}

Fonctions d'Aide

Avant de plonger dans les instructions loan et repay, intéressons-nous à 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]) ->  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());
    }

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

Ce dossier est simple. Il contient une structure LoanData que nous utiliserons pour stocker temporairement les données du prêt dans un compte avant qu'il ne soit remboursé. Il fournit également une fonction d'aide get_token_amount() qui permet de lire le nombre de jetons d'un compte.

Next PageEmprunter
OU PASSER AU CHALLENGE
Prêt à relever le challenge ?
Blueshift © 2025Commit: e573eab