Pinocchio Flash Loan

Instruction Introspection ist eine leistungsstarke Funktion, die es einem Blockchain-Programm ermöglicht, andere Anweisungen innerhalb desselben Transaktionsbündels zu untersuchen und zu analysieren. Dies umfasst auch Anweisungen, die noch nicht ausgeführt wurden, wodurch Ihr Programm die Fähigkeit erhält, "vorauszuschauen" und Entscheidungen basierend auf dem zu treffen, was später in der Transaktion passieren wird.
Stellen Sie sich das wie eine Röntgensicht für Transaktionen vor: Ihr Programm kann die gesamte Transaktion durchschauen, um die vollständige Abfolge der Operationen zu verstehen, bevor es entscheidet, wie es fortfahren soll.
Die überzeugendste Anwendung der Instruction Introspection sind Flash Loans. Dies ist eine einzigartige Art von Darlehen, die nur innerhalb der Grenzen einer einzelnen Transaktion existiert.
So funktionieren Flash Loans:
Leihen: Am Anfang einer Transaktion können Sie sofort eine große Menge Kapital mit einer
loanAnweisung ausleihenVerwenden: Sie können dieses geliehene Kapital für Handel, Arbitrage oder andere Operationen innerhalb derselben Transaktion nutzen
Zurückzahlen: Vor dem Ende der Transaktion müssen Sie das Darlehen plus eine kleine Gebühr mit einer
repayAnweisung zurückzahlen
Die zentrale Erkenntnis ist, dass Flash Loans auf der atomaren Natur von Blockchain-Transaktionen basieren. Wenn ein Teil der Transaktion fehlschlägt (einschließlich der Rückzahlung), wird die gesamte Transaktion rückgängig gemacht, als wäre sie nie passiert. Das bedeutet, dass der Kreditgeber kein Risiko hat: Entweder wird er zurückgezahlt, oder das Darlehen ist nie tatsächlich erfolgt.
In dieser Challenge erstellen Sie ein einfaches Flash-Loan-Programm, das Instruction Introspection in Aktion demonstriert. Das Programm wird Anweisungsdaten und Konten über verschiedene Anweisungen innerhalb derselben Transaktion untersuchen, um sicherzustellen, dass die Darlehensbedingungen erfüllt werden.
Wenn du neu im Bereich der Instruktionsintrospektion bist, empfehlen wir dir, mit dem Kurs zur Instruktionsintrospektion zu beginnen, um die grundlegenden Konzepte zu verstehen, die in diesem Programm verwendet werden.
Installation
Bevor du beginnst, stelle sicher, dass Rust und Pinocchio installiert sind. Führe dann Folgendes in deinem Terminal aus:
# create workspace
cargo new blueshift_pinocchio_flash_loan --lib --edition 2021
cd blueshift_pinocchio_flash_loanFüge pinocchio, pinocchio-system und pinocchio-token hinzu:
cargo add pinocchio pinocchio-system pinocchio-tokenDeklariere die Crate-Typen in Cargo.toml, um Deployment-Artefakte in target/deploy zu generieren:
[lib]
crate-type = ["lib", "cdylib"]Du bist jetzt bereit, dein Flash-Loan-Programm zu schreiben.
Vorlage
Diesmal werden wir das Programm in kleine, fokussierte Module aufteilen, anstatt alles in lib.rs zu platzieren. Die Ordnerstruktur wird ungefähr so aussehen:
src
├── instructions
│ ├── helpers.rs
│ ├── loan.rs
│ ├── mod.rs
│ └── repay.rs
├── lib.rsHinweis: Denke daran, die Programm-ID in 22222222222222222222222222222222222222222222 zu ändern, da wir diese im Hintergrund verwenden, um dein Programm zu testen.
Der Einstiegspunkt in lib.rs ist sehr ähnlich zu dem, was wir im Einführungskurs zu Pinocchio behandelt haben.
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)
}
}Hilfsfunktionen
Bevor wir in die Anweisungen loan und repay eintauchen, schauen wir uns helpers.rs an:
#[repr(C, packed)]
pub struct LoanData {
pub protocol_token_account: [u8; 32],
pub balance: u64,
}
pub fn get_token_amount(data: &[u8]) -> u64 {
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());
}
u64::from_le_bytes(data[64..72].try_into().unwrap())
}Diese Datei ist unkompliziert. Sie enthält eine LoanDataStruktur, die wir verwenden werden, um Darlehensdaten vorübergehend in einem Konto zu speichern, bevor das Darlehen zurückgezahlt wird. Sie bietet auch eine Hilfsfunktion get_token_amount(), um den Token-Betrag aus einem Konto zu lesen.