### Rust Program Entrypoint Example Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md This example demonstrates how to set up a program's entrypoint using `process_entrypoint`. It includes necessary imports, allocator and panic handler setup, and the `entrypoint` function which handles deserialization and calls the `process_instruction` handler. The `entrypoint` function checks for zero accounts as a fast path. ```rust use pinocchio:: AccountView, Address, entrypoint::process_entrypoint, MAX_TX_ACCOUNTS, ProgramResult, }; no_allocator!(); default_panic_handler!(); #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { let num_accounts = unsafe { *(input as *const u64) }; // Fast path if num_accounts == 0 { return 0; // success } // Standard deserialization unsafe { process_entrypoint::(input, process_instruction) } } pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { Ok(()) } ``` -------------------------------- ### Example of Expanding Account Data Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/account-resizing.md Demonstrates how to use the `resize` method to expand an account's data. This example checks the current size, resizes the account, and confirms the new size with zero-filled bytes. ```rust use pinocchio::{AccountView, Resize}; fn expand_account(account: &mut AccountView, new_size: usize) -> Result<(), ProgramError> { // Check current size let current = account.data_len(); // Resize to new size account.resize(new_size)?; // Now account.data_len() == new_size, with new bytes zeroed Ok(()) } ``` -------------------------------- ### Project Structure Example Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Illustrates a typical file organization for a Pinocchio program, including source files and the Cargo.toml manifest. ```text my_program/ ├── Cargo.toml └── src/ ├── lib.rs # Re-export public items ├── entrypoint.rs # #[cfg(feature = "bpf-entrypoint")] ├── instructions.rs # Instruction dispatch ├── state.rs # Data structures ├── errors.rs # Custom error types └── utils.rs # Helper functions ``` -------------------------------- ### Instruction Dispatch Example Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/README.md Handles incoming program instructions by matching the first byte of instruction data to a specific function. Ensure your instruction data starts with a defined byte for dispatch. ```rust entrypoint!(process_instruction); pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { match instruction_data.first() { Some(0) => initialize(program_id, accounts), Some(1) => update(program_id, accounts, instruction_data), _ => Err(ProgramError::InvalidInstructionData), } } ``` -------------------------------- ### Implement Custom Program Entrypoint Source: https://github.com/anza-xyz/pinocchio/blob/main/README.md Use `process_entrypoint` for custom entrypoint logic, allowing for fast-path optimizations or pre-processing. This example demonstrates a custom entrypoint with a fast path for zero accounts and delegates to standard processing otherwise. Requires `no_allocator!` and `default_panic_handler!` if not using `std`. ```rust use pinocchio::{ AccountView, Address, default_panic_handler, entrypoint::process_entrypoint, MAX_TX_ACCOUNTS, no_allocator, ProgramResult, }; use solana_program_log::log; no_allocator!(); default_panic_handler!(); #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { // Fast path: check the number of accounts let num_accounts = unsafe { *(input as *const u64) }; if num_accounts == 0 { log("Fast path - no accounts!"); return 0; } // Standard path: delegate to `process_entrypoint` unsafe { process_entrypoint::(input, process_instruction) } } pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { log("Standard path"); Ok(()) } ``` -------------------------------- ### Define Standard Program Entrypoint Source: https://github.com/anza-xyz/pinocchio/blob/main/README.md Use the `entrypoint!` macro for a standard Solana program setup. It handles boilerplate for the program entrypoint, global allocator, and panic handler. Ensure necessary imports are included. ```rust use pinocchio::{ AccountView, Address, entrypoint, ProgramResult }; use solana_program_log::log; entrypoint!(process_instruction); pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { log("Hello from my pinocchio program!"); Ok(()) } ``` -------------------------------- ### Use Entrypoint Macro Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-macros.md Example of using the entrypoint macro to declare the program's main instruction processing function. Ensure necessary imports are included. ```rust use pinocchio::{ AccountView, Address, entrypoint, ProgramResult }; entrypoint!(process_instruction); pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { Ok(()) } ``` -------------------------------- ### Basic Pinocchio Program Entrypoint Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md The simplest Pinocchio program structure using the `entrypoint!` macro for automatic setup of the C-compatible entrypoint, bump allocator, panic handler, and input buffer deserialization. ```rust #![no_std] use pinocchio::{ AccountView, Address, entrypoint, ProgramResult, }; entrypoint!(process_instruction); pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { // Program logic here Ok(()) } ``` -------------------------------- ### Example Usage of Unsafe Resize Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/account-resizing.md Demonstrates how to use the unsafe resize method. The caller is responsible for ensuring all safety requirements are met before calling this method. ```rust use pinocchio::{AccountView, UnsafeResize}; fn expand_account_unsafe(account: &mut AccountView, new_size: usize) { // Caller must validate: // 1. original_size + new_size - original_size <= MAX_PERMITTED_DATA_INCREASE // 2. No other references to account.data are active unsafe { account.resize(new_size); } } ``` -------------------------------- ### Define Program Entrypoint Macro Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-macros.md Declares the program entrypoint with automatic setup of global allocator and panic handler. It accepts the instruction processing function and an optional maximum account limit. ```rust #[macro_export] macro_rules! entrypoint { ( $process_instruction:expr ) => { ... }; ( $process_instruction:expr, $maximum:expr ) => { ... }; } ``` -------------------------------- ### Get Instruction Data Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Retrieves the instruction data after all accounts have been consumed. Returns an error if accounts still remain to be parsed. ```rust pub fn instruction_data(&self) -> Result<&[u8], ProgramError> ``` -------------------------------- ### BumpAllocator Entrypoint Structure Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/types.md Defines the BumpAllocator structure, a forward bump allocator for the heap, managing start and end points. ```rust pub struct BumpAllocator { start: usize, end: usize, } ``` -------------------------------- ### Get Number of Instructions Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves the total count of instructions in the current transaction by reading the first two bytes as a little-endian u16. ```rust pub fn num_instructions(&self) -> usize ``` -------------------------------- ### Account Validation Example Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/README.md Validates the number and ownership of accounts required for a program. This ensures that the correct accounts are provided and owned by the program before proceeding. ```rust pub fn validate_accounts(accounts: &[AccountView]) -> ProgramResult { if accounts.len() < 3 { return Err(ProgramError::NotEnoughAccountKeys); } if accounts[0].owner() != &my_program_id { return Err(ProgramError::InvalidArgument); } Ok(()) } ``` -------------------------------- ### Get Number of Account Metas Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves the count of accounts referenced by this instruction. It reads the first 2 bytes as a little-endian u16. ```rust pub fn num_account_metas(&self) -> usize ``` -------------------------------- ### Use Compiler Hints for Optimization Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Utilize `likely` and `unlikely` hints to guide the compiler's optimization efforts for specific code paths. This can improve performance by informing the compiler about expected execution frequencies. ```rust use pinocchio::hint::{likely, unlikely}; pub fn process_with_hints(value: u64) -> Result { // Mark error condition as unlikely if unlikely(value == 0) { return Err(ProgramError::InvalidArgument); } // Mark happy path as likely if likely(value > 1000) { // Fast path with most traffic Ok(value * 2) } else { // Less common case Ok(value) } } ``` -------------------------------- ### Basic Program Entrypoint Usage Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-macros.md Demonstrates how to use the program_entrypoint! macro with default allocator and panic handler. This is suitable for standard program execution. ```rust use pinocchio::{ AccountView, Address, program_entrypoint, default_allocator, default_panic_handler, ProgramResult }; program_entrypoint!(process_instruction); default_allocator!(); default_panic_handler!(); pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { Ok(()) } ``` -------------------------------- ### Get Remaining Accounts Count Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Retrieves the number of accounts that still need to be parsed from the input buffer. ```rust pub fn remaining(&self) -> u64 ``` -------------------------------- ### Get SlotHash Entry by Index Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves a specific SlotHashEntry by its index. Returns None if the index is out of bounds. ```rust pub fn get_entry(&self, index: usize) -> Option<&SlotHashEntry> ``` -------------------------------- ### Getting Account Data Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Retrieves a read-only slice of an account's data using `AccountView::try_borrow()`. ```rust use pinocchio::{ AccountView, ProgramResult, error::ProgramError, }; pub fn get_account_data(account: &AccountView) -> Result<&[u8], ProgramError> { account.try_borrow() .map(|ref_| ref_.as_ref()) } ``` -------------------------------- ### Create Instructions from AccountView Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Creates an Instructions wrapper from an AccountView. Returns an error if the account address does not match INSTRUCTIONS_ID. ```rust impl<'a> TryFrom<&'a AccountView> for Instructions> { type Error = ProgramError; fn try_from(account_view: &'a AccountView) -> Result } ``` -------------------------------- ### Get Instruction Data Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves the raw instruction data bytes. The data is located after the program ID. ```rust pub fn get_instruction_data(&self) -> &[u8] ``` -------------------------------- ### Build with Features Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/README.md Builds the program for the Standard BPF target with specified features enabled. ```bash cargo build-sbf --features "cpi,account-resize" ``` -------------------------------- ### Get Program ID Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves the program ID for this instruction. The program ID is located after all account entries. ```rust pub fn get_program_id(&self) -> &Address ``` -------------------------------- ### Build Program with BPF Entrypoint Feature Source: https://github.com/anza-xyz/pinocchio/blob/main/README.md When building your program binary, ensure the `bpf-entrypoint` feature is enabled using the `cargo build-sbf` command. ```bash cargo build-sbf --features bpf-entrypoint ``` -------------------------------- ### Get Number of SlotHashes Entries Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Returns the total number of slot hash entries stored in the SlotHashes sysvar. ```rust pub fn len(&self) -> usize ``` -------------------------------- ### Get Instruction Account by Index Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves an instruction account by its index. Returns ProgramError::InvalidArgument if the index is out of bounds. ```rust pub fn get_instruction_account_at( &self, index: usize, ) -> Result<&IntrospectedInstructionAccount, ProgramError> ``` -------------------------------- ### Standard BPF Build Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/README.md Builds the program for the Standard BPF target. ```bash cargo build-sbf ``` -------------------------------- ### Initialize Mint Account with Token-2022 Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/token-2022/README.md Use this to initialize a mint account. Assumes the `mint` account is writable and `authority` is an `Address`. The SPL Token program is invoked. ```rust InitializeMint { mint, rent_sysvar, decimals: 9, mint_authority: authority, freeze_authority: Some(authority), token_program: Address::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") }.invoke()?; ``` -------------------------------- ### Get Program ID (Unchecked) Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Retrieves the program ID without validation. The caller must guarantee that all accounts have been read. ```rust pub unsafe fn program_id_unchecked(&self) -> &Address ``` -------------------------------- ### Release Build Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/README.md Builds the program for the Standard BPF target in release mode for optimized performance. ```bash cargo build-sbf --release ``` -------------------------------- ### Get Program ID Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Retrieves the program ID after all accounts have been consumed. Returns an error if accounts still remain to be parsed. ```rust pub fn program_id(&self) -> Result<&Address, ProgramError> ``` -------------------------------- ### Create Instructions Wrapper Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Creates a new Instructions wrapper from raw data. The caller must ensure the data is valid. ```rust pub unsafe fn new_unchecked(data: T) -> Self ``` -------------------------------- ### Get Instruction Data (Unchecked) Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Retrieves the instruction data without validation. The caller must guarantee that all accounts have been read. ```rust pub unsafe fn instruction_data_unchecked(&self) -> &[u8] ``` -------------------------------- ### Clock Sysvar Implementation of Sysvar Trait Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Implementation of the `get` method for the Clock sysvar, allowing it to be loaded directly from the runtime. ```rust impl Sysvar for Clock { fn get() -> Result { ... } } ``` -------------------------------- ### deserialize Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Parses the arguments from the runtime input buffer, returning the program ID, instruction data, and a populated accounts array. This is a lower-level function than `process_entrypoint`. ```APIDOC ## deserialize ### Description Parses the arguments from the runtime input buffer, returning the program ID, instruction data, and a populated accounts array. This is a lower-level function than `process_entrypoint`. ### Method Unsafe Rust function ### Signature ```rust pub unsafe fn deserialize( mut input: *mut u8, accounts: &mut [MaybeUninit; MAX_ACCOUNTS], ) -> (&'static Address, usize, &'static [u8]) ``` ### Parameters #### Input Parameters - **input** (`*mut u8`) - Required - Pointer to the program input buffer from the SVM loader. - **accounts** (`&mut [MaybeUninit; MAX_ACCOUNTS]`) - Required - Uninitialized array to populate with AccountView instances. #### Generic Parameters - **MAX_ACCOUNTS** (`usize`) - Required - Maximum number of accounts to parse; must be > 0 and ≤ `MAX_TX_ACCOUNTS`. ### Returns A tuple containing: - `&'static Address` — The program ID. - `usize` — The actual number of accounts parsed (≤ `MAX_ACCOUNTS`). - `&'static [u8]` — The instruction data. ### Safety The caller must ensure that: 1. `input` is a valid pointer to the program input buffer serialized by the SVM loader. 2. `input` remains valid for the lifetime of the program execution. 3. `accounts` array has the capacity specified by `MAX_ACCOUNTS`. ### Details This function validates `MAX_ACCOUNTS` at compile time, reads the account count from the input buffer, limits the returned count to `MAX_ACCOUNTS`, initializes the `accounts` array with valid `AccountView` instances, advances the input pointer to the instruction data, and returns pointers to the instruction data and program ID. If the input contains more accounts than `MAX_ACCOUNTS`, the excess accounts are still deserialized but not stored in the returned `accounts` array. ``` -------------------------------- ### process_entrypoint Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Deserializes the program input buffer and calls the instruction handler. This is a core function used by the `program_entrypoint!` macro for efficient deserialization. ```APIDOC ## process_entrypoint ### Description Deserialize the program input buffer and call the instruction handler. ### Signature ```rust pub unsafe fn process_entrypoint( input: *mut u8, process_instruction: fn(&Address, &mut [AccountView], &[u8]) -> ProgramResult, ) -> u64 ``` ### Parameters #### Parameters - **input** (`*mut u8`) - Pointer to the program input buffer from the SVM loader. - **process_instruction** (`fn(&Address, &mut [AccountView], &[u8]) -> ProgramResult`) - Function to call to process the instruction. #### Generic Parameters - **MAX_ACCOUNTS** (`usize`) - Maximum number of accounts to parse (must be ≤ `MAX_TX_ACCOUNTS`). ### Returns `u64` - 0 for success, or the error code from `ProgramError`. ### Safety The caller must ensure that: 1. `input` is a valid pointer to the program input buffer serialized by the SVM loader 2. `input` remains valid for the lifetime of the program execution 3. The input buffer follows the exact format specified in the entrypoint module documentation ### Details This is the core deserialization function used by the `program_entrypoint!` macro. It reads the number of accounts, deserializes each account, extracts instruction data and program ID, calls the provided instruction handler, and converts the result to a u64 return code. The function inlines all deserialization logic for efficiency. ### Example ```rust use pinocchio:: AccountView, Address, entrypoint::process_entrypoint, MAX_TX_ACCOUNTS, ProgramResult, ; no_allocator!(); default_panic_handler!(); #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { let num_accounts = unsafe { *(input as *const u64) }; // Fast path if num_accounts == 0 { return 0; // success } // Standard deserialization unsafe { process_entrypoint::(input, process_instruction) } } pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { Ok(()) } ``` ``` -------------------------------- ### Get All SlotHash Entries Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Returns a slice containing all SlotHashEntry items. This provides zero-copy access and is efficient for accessing multiple entries. ```rust pub fn entries(&self) -> &[SlotHashEntry] ``` -------------------------------- ### Create Associated Token Account Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/associated-token-account/README.md Use the `Create` instruction to create a new associated token account. This requires funding, account, wallet, mint, system program, and token program accounts. ```rust Create { funding_account, account, wallet, mint, system_program, token_program, }.invoke()?; ``` -------------------------------- ### Equivalent Macros for Entrypoint Source: https://github.com/anza-xyz/pinocchio/blob/main/README.md The `entrypoint!` macro is a convenience that expands to `program_entrypoint!`, `default_allocator!`, and `default_panic_handler!`. These can be used individually if custom implementations are needed. ```rust program_entrypoint!(process_instruction); default_allocator!(); default_panic_handler!(); ``` -------------------------------- ### Get Current Instruction Index Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves the index of the currently executing instruction by reading the last two bytes of the sysvar data. ```rust pub fn load_current_index(&self) -> u16 ``` -------------------------------- ### Fees::new Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Initializes a new Fees instance with provided FeeCalculator and FeeRateGovernor. ```APIDOC ## Fees::new ### Description Create a new Fees instance. ### Signature ```rust pub fn new(fee_calculator: FeeCalculator, fee_rate_governor: FeeRateGovernor) -> Self ``` ``` -------------------------------- ### Sysvar Trait Definition Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/types.md Defines the Sysvar trait for system variables. It includes a default `get` method that returns an UnsupportedSysvar error. ```rust pub trait Sysvar: Sized { fn get() -> Result { Err(ProgramError::UnsupportedSysvar) } } ``` -------------------------------- ### Create Associated Token Account (Idempotent) Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/associated-token-account/README.md Use the `CreateIdempotent` instruction to create an associated token account if it does not already exist. This requires the same accounts as the `Create` instruction. ```rust CreateIdempotent { funding_account, account, wallet, mint, system_program, token_program, }.invoke()?; ``` -------------------------------- ### Lazy Program Entrypoint Usage Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-macros.md Shows how to use lazy_program_entrypoint! with default allocator and panic handler for on-demand input parsing. This is efficient for programs with few instructions or custom parsing. ```rust use pinocchio::{ default_allocator, default_panic_handler, entrypoint::InstructionContext, lazy_program_entrypoint, ProgramResult }; lazy_program_entrypoint!(process_instruction); default_allocator!(); default_panic_handler!(); pub fn process_instruction( mut context: InstructionContext ) -> ProgramResult { while context.remaining() > 0 { let account = context.next_account()?; // Process account } let data = context.instruction_data()?; Ok(()) } ``` -------------------------------- ### Build for Host Target Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/README.md Builds the program for the host target, typically used for local testing without syscalls. ```bash cargo build --target x86_64-unknown-linux-gnu ``` -------------------------------- ### Get SlotHash Entry Unchecked Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves a specific SlotHashEntry by its index without bounds checking. The caller must ensure the index is valid. ```rust pub unsafe fn get_entry_unchecked(&self, index: usize) -> &SlotHashEntry ``` -------------------------------- ### Configure Documentation Generation Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md Configure the crate for `docs.rs` to generate documentation with all features enabled on a host target. This involves setting metadata in `Cargo.toml`. ```toml [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] all-features = true rustdoc-args = ["--cfg=docsrs"] ``` -------------------------------- ### Get Clock Sysvar from AccountView Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Loads the `Clock` system variable from an `AccountView`. This is an alternative to `Clock::get()` when the clock data is provided via an account. ```rust use pinocchio::{AccountView, sysvars::Clock, ProgramResult}; pub fn get_slot_from_account(clock_account: &AccountView) -> ProgramResult { let clock = Clock::from_account_view(clock_account)?; // clock is Ref Ok(()) } ``` -------------------------------- ### Initialize SPL Token Mint Account Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/token/README.md Use this snippet to initialize a new SPL Token mint account. Ensure the `mint` account is writable and `authority` is a valid Address. The `rent_sysvar` is required for rent exemption. ```rust InitializeMint { mint, rent_syssysvar, decimals: 9, mint_authority: authority, freeze_authority: Some(authority), }.invoke()?; ``` -------------------------------- ### Maximum Efficiency Pinocchio Configuration Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md This configuration provides the smallest binary while enabling manual account resizing and CPI. It includes Copy trait derivations, unsafe account resizing, and CPI. ```toml pinocchio = { version = "0.11", default-features = false, features = [ "copy", "unsafe-account-resize", "cpi" ]} ``` -------------------------------- ### Get Instruction Account Unchecked Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves an instruction account without performing bounds checking. The caller must ensure the index is within the valid range. ```rust pub unsafe fn get_instruction_account_at_unchecked( &self, index: usize, ) -> &IntrospectedInstructionAccount ``` -------------------------------- ### Rent::try_minimum_balance Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Calculates the minimum lamports required for rent exemption, returning an error if the calculation would overflow. ```APIDOC ## Rent::try_minimum_balance ### Description Calculate the minimum lamports required for rent exemption. ### Method ```rust pub fn try_minimum_balance(&self, data_len: usize) -> Result ``` ### Parameters #### Path Parameters - **data_len** (usize) - Account data size in bytes ### Returns Minimum lamports for exemption, or error if calculation would overflow. ### Errors - `ProgramError::InvalidArgument` if `data_len` exceeds `MAX_PERMITTED_DATA_LENGTH` or lamports per byte is too large. ### Details Avois floating-point arithmetic. ``` -------------------------------- ### Sysvar Access Example Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/README.md Retrieves system variables, such as the current clock, using the Sysvar trait. This pattern is useful for accessing time-sensitive or system-level information within your program. ```rust use pinocchio::sysvars::{Clock, Sysvar}; pub fn get_current_time() -> ProgramResult { let clock = Clock::get()?; // Use clock.slot, clock.unix_timestamp, etc. Ok(()) } ``` -------------------------------- ### Get Slot Hash for a Specific Slot Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Retrieves the transaction hash for a given slot using the `SlotHashes` system variable. This is useful for verifying historical transaction data. ```rust use pinocchio::{AccountView, sysvars::slot_hashes::SlotHashes, ProgramResult}; pub fn get_hash_for_slot(slot_hashes_account: &AccountView, slot: u64) -> ProgramResult { let slot_hashes = SlotHashes::from_account_view(slot_hashes_account)?; if let Some(hash) = slot_hashes.get_hash(slot) { // Found hash for slot Ok(()) } else { // Slot not found (older than oldest hash in sysvar) Err(ProgramError::InvalidArgument) } } ``` -------------------------------- ### Create and Invoke SPL Memo Instruction Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/memo/README.md Construct a Memo instruction with required signers and memo content, then invoke it. Ensure all specified accounts are signers. ```rust // Both accounts should be signers Memo { signers: &[&accounts[0], &accounts[1]], memo: "hello", } .invoke()?; ``` -------------------------------- ### Standard Pinocchio Configuration (Default) Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md This is the default configuration and is suitable for most programs. It includes the allocator, Copy trait derivations, and SHA2 support. ```toml pinocchio = { version = "0.11" } ``` -------------------------------- ### Get Current Slot and Timestamp using Clock Sysvar Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Retrieves the current slot and Unix timestamp using the `Clock` system variable. This is useful for time-sensitive operations or logging. ```rust use pinocchio::sysvars::{Clock, Sysvar}; use pinocchio::ProgramResult; pub fn get_current_slot() -> ProgramResult { let clock = Clock::get()?; // Use clock.slot, clock.unix_timestamp, etc. Ok(()) } ``` -------------------------------- ### Cargo.toml Dependencies and Features Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Shows how to define package metadata, dependencies, and features in a Pinocchio project's Cargo.toml file. ```toml [package] name = "my_program" version = "0.1.0" [dependencies] pinocchio = "0.11" [features] default = [] bpf-entrypoint = [] cpi = ["pinocchio/cpi"] ``` -------------------------------- ### Get Instruction Relative to Current Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Retrieves an instruction relative to the current instruction. Negative indices go backward, positive indices go forward. Errors if the index is out of bounds or negative. ```rust pub fn get_instruction_relative( &self, index_relative_to_current: i64, ) -> Result, ProgramError> ``` -------------------------------- ### Conditional Entrypoint for Library and Program Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md A Pinocchio program structure that can also be used as a library, utilizing a feature flag (`bpf-entrypoint`) to conditionally compile the program entrypoint. Build with `cargo build-sbf --features bpf-entrypoint`. ```rust #![no_std] pub mod instructions; pub mod state; #[cfg(feature = "bpf-entrypoint")] pub mod entrypoint { use pinocchio::{ AccountView, Address, entrypoint, ProgramResult, }; use crate::instructions; entrypoint!(process_instruction); pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { instructions::dispatch(program_id, accounts, instruction_data) } } pub fn lib_function() { // Library logic } ``` -------------------------------- ### Define Program Entrypoint with No Allocator Source: https://github.com/anza-xyz/pinocchio/blob/main/README.md Use `program_entrypoint!` with `no_allocator!` to prevent memory allocations. This is suitable for programs that do not require dynamic memory. A panic handler must still be set. ```rust use pinocchio:: AccountView; default_panic_handler!(); no_allocator; program_entrypoint; ProgramResult; Address; program_entrypoint!(process_instruction); default_panic_handler!(); no_allocator!(); pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { Ok(()) } ``` -------------------------------- ### Custom Entrypoint for Maximum Control Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Provides maximum control over deserialization. Use this when you need to manage the entrypoint logic manually. ```rust #![no_std] use pinocchio::{ AccountView, Address, default_panic_handler, entrypoint::process_entrypoint, MAX_TX_ACCOUNTS, no_allocator, ProgramResult, }; no_allocator!(); default_panic_handler!(); #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 { // Fast path: check for empty accounts let num_accounts = unsafe { *(input as *const u64) }; if num_accounts == 0 { return 0; // Success with no accounts } // Standard deserialization unsafe { process_entrypoint::(input, process_instruction) } } pub fn process_instruction( program_id: &Address, accounts: &mut [AccountView], instruction_data: &[u8], ) -> ProgramResult { Ok(()) } ``` -------------------------------- ### Define Lazy Program Entrypoint Source: https://github.com/anza-xyz/pinocchio/blob/main/README.md Use `lazy_program_entrypoint!` for programs with few instructions to parse input on demand. Ensure a global allocator and panic handler are explicitly set up. ```rust use pinocchio:: default_allocator; default_panic_handler!(); entrypoint::InstructionContext; lazy_program_entrypoint; ProgramResult; lazy_program_entrypoint!(process_instruction); default_allocator!(); default_panic_handler!(); pub fn process_instruction( mut context: InstructionContext ) -> ProgramResult { Ok(()) } ``` -------------------------------- ### BPF Target Syscall Configuration Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md When compiling for the BPF target, use `solana-define-syscall` with the `unstable-static-syscalls` feature to enable explicit static syscalls, as the standard library is not available. ```toml [dependencies] solana-define-syscall = { version = "5.0", features = ["unstable-static-syscalls"] } ``` -------------------------------- ### Clock Sysvar Structure Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Defines the structure of the Clock sysvar, which holds information about the network's clock, slots, and time. It includes fields like slot, epoch start timestamp, epoch, leader schedule epoch, and Unix timestamp. ```rust pub const CLOCK_ID: Address = /* ... */; #[repr(C)] pub struct Clock { pub slot: Slot, pub epoch_start_timestamp: UnixTimestamp, pub epoch: Epoch, pub leader_schedule_epoch: Epoch, pub unix_timestamp: UnixTimestamp, } ``` -------------------------------- ### Create Account CPI Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/system/README.md Use this snippet to create a new account via a cross-program invocation. Ensure the `payer` account is writable and a signer, and `new_account` is also provided. ```rust CreateAccount { from: payer, to: new_account, lamports: 1_000_000_000, // 1 SOL space: 200, // 200 bytes owner: &spl_token::ID, }.invoke()?; ``` -------------------------------- ### Rent::minimum_balance (deprecated) Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Calculates the minimum balance for rent exemption, panicking on overflow. Use `try_minimum_balance` instead. ```APIDOC ## Rent::minimum_balance (deprecated) ### Description Calculate minimum balance, panicking on overflow. ### Method ```rust #[deprecated(since = "0.10.0", note = "Use `try_minimum_balance` instead")] pub fn minimum_balance(&self, data_len: usize) -> u64 ``` ``` -------------------------------- ### Instructions Sysvar Methods Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Provides methods to interact with the Instructions Sysvar, enabling retrieval of transaction instruction details. ```APIDOC ## Instructions Sysvar Introspect instructions in the current transaction. ### Methods #### `new_unchecked` ```rust pub unsafe fn new_unchecked(data: T) -> Self ``` Create a new Instructions wrapper. **Safety:** Caller must ensure `data` contains valid Instructions sysvar data. #### `num_instructions` ```rust pub fn num_instructions(&self) -> usize ``` Get the total number of instructions in the current transaction. **Details:** Reads the first 2 bytes as a little-endian `u16`. #### `load_current_index` ```rust pub fn load_current_index(&self) -> u16 ``` Get the index of the currently executing instruction. **Details:** Reads the last 2 bytes of the sysvar data. #### `deserialize_instruction_unchecked` ```rust pub unsafe fn deserialize_instruction_unchecked(&self, index: usize) -> IntrospectedInstruction<'_> ``` Get an instruction at the specified index without bounds checking. **Safety:** Caller must guarantee `index < num_instructions()`. #### `load_instruction_at` ```rust pub fn load_instruction_at(&self, index: usize) -> Result, ProgramError> ``` Get an instruction at the specified index. **Errors:** `ProgramError::InvalidInstructionData` if index is out of bounds. #### `get_instruction_relative` ```rust pub fn get_instruction_relative(&self, index_relative_to_current: i64) -> Result, ProgramError> ``` Get an instruction relative to the current instruction. **Parameters:** - `index_relative_to_current` (i64) - Relative index; negative goes backward, positive forward **Errors:** `ProgramError::InvalidInstructionData` if index is out of bounds or negative. #### `TryFrom<&AccountView>` ```rust impl<'a> TryFrom<&'a AccountView> for Instructions> { type Error = ProgramError; fn try_from(account_view: &'a AccountView) -> Result } ``` Create Instructions from an account view. **Errors:** `ProgramError::UnsupportedSysvar` if account address is not `INSTRUCTIONS_ID`. ``` -------------------------------- ### Safe Account Resizing with Error Handling Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/account-resizing.md Demonstrates a safe approach to resizing an account, handling potential `AccountBorrowFailed` and `InvalidRealloc` errors by retrying or resizing to the maximum permitted size. ```rust use pinocchio::{AccountView, ProgramResult, Resize, error::ProgramError}; pub fn safe_resize(account: &mut AccountView, new_size: usize) -> ProgramResult { match account.resize(new_size) { Ok(()) => Ok(()), Err(ProgramError::AccountBorrowFailed) => { // Drop borrows and try again drop(account.try_borrow_mut()?); account.resize(new_size) }, Err(ProgramError::InvalidRealloc) => { // Size too large; resize to maximum instead let original_size = account.data_len(); let max_size = original_size + pinocchio::account::MAX_PERMITTED_DATA_INCREASE; account.resize(max_size) }, Err(e) => Err(e), } } ``` -------------------------------- ### Configure Rust Toolchains Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md Define specific Rust toolchain versions for build, format, and linting. Nightly versions are recommended for formatting and linting. ```toml [workspace.metadata.toolchains] build = "1.89.0" format = "nightly-2026-01-22" lint = "nightly-2026-01-22" test = "1.89.0" ``` -------------------------------- ### Minimal Pinocchio Configuration Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md Use this configuration for the smallest possible binary without dynamic allocation. It excludes the allocator, Copy trait derivations, SHA2 support, and CPI. ```toml pinocchio = { version = "0.11", default-features = false, features = [] } ``` -------------------------------- ### Enable Static Syscalls in Cargo.toml Source: https://github.com/anza-xyz/pinocchio/blob/main/README.md To enable static syscalls for the BPF target, add the `unstable-static-syscalls` feature to the `solana-define-syscall` dependency in your program's Cargo.toml. ```toml [dependencies] # Enable static syscalls for BPF target solana-define-syscall = { version = "5.0", features = ["unstable-static-syscalls"] } ``` -------------------------------- ### Calculate Minimum Rent Balance (Deprecated) Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md A deprecated method for calculating minimum balance, which panics on overflow. It is recommended to use `try_minimum_balance` instead for safer error handling. ```rust #[deprecated(since = "0.10.0", note = "Use `try_minimum_balance` instead")] pub fn minimum_balance(&self, data_len: usize) -> u64 ``` -------------------------------- ### Rust `process_entrypoint` Function Signature Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md This is the core deserialization function used by the `program_entrypoint!` macro. It reads account information, instruction data, and program ID from the input buffer before calling the provided instruction handler. Ensure the input buffer format is correct and the pointer remains valid. ```rust pub unsafe fn process_entrypoint( input: *mut u8, process_instruction: fn(&Address, &mut [AccountView], &[u8]) -> ProgramResult, ) -> u64 ``` -------------------------------- ### Static Memory Allocation with no_allocator! Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Demonstrates static memory allocation using the `no_allocator!` macro for environments without a standard allocator. Ensure allocated regions do not overlap. ```rust #![no_std] use pinocchio::no_allocator; no_allocator!(); pub fn static_allocation() { // Allocate 64 bytes at offset 0 let buffer: &mut [u8; 64] = unsafe { allocate_unchecked(0) }; // Allocate a u64 at offset 64 let counter: &mut u64 = unsafe { allocate_unchecked(64) }; // Allocate a [u32; 8] at offset 72 let flags: &mut [u32; 8] = unsafe { allocate_unchecked(72) }; } ``` -------------------------------- ### FeeCalculator::new Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Creates a new fee calculator instance with a specified lamports per signature. ```rust pub fn new(lamports_per_signature: u64) -> Self ``` -------------------------------- ### InstructionContext::next_account Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Parses and returns the next account from the instruction data. It decrements the remaining account count and can return either a valid account or a duplicated account index. ```APIDOC ## next_account ### Description Parse and return the next account. **Errors:** Returns `ProgramError::NotEnoughAccountKeys` if no accounts remain. **Details:** Decrements the `remaining` count and may return either a `MaybeAccount::Account` containing an `AccountView`, or `MaybeAccount::Duplicated(index)` indicating a reference to a previous account. ### Signature ```rust pub fn next_account(&mut self) -> Result ``` ``` -------------------------------- ### Fees::new Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Constructs a new Fees instance using provided FeeCalculator and FeeRateGovernor. ```rust pub fn new(fee_calculator: FeeCalculator, fee_rate_governor: FeeRateGovernor) -> Self ``` -------------------------------- ### Add pinocchio-associated-token-account Dependency Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/associated-token-account/README.md Add the pinocchio-associated-token-account crate to your project's Cargo.toml file to include its functionality. ```bash cargo add pinocchio-associated-token-account ``` -------------------------------- ### Program Entrypoint Macro Definition Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-macros.md Defines the program_entrypoint! macro with two variants for processing instructions. ```rust #[macro_export] macro_rules! program_entrypoint { ( $process_instruction:expr ) => { ... }; ( $process_instruction:expr, $maximum:expr ) => { ... }; } ``` -------------------------------- ### FeeRateGovernor::create_fee_calculator Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Generates a FeeCalculator based on the current parameters of the FeeRateGovernor. ```rust pub fn create_fee_calculator(&self) -> FeeCalculator ``` -------------------------------- ### FeeCalculator::new Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Creates a new fee calculator with a specified lamports per signature value. ```APIDOC ## FeeCalculator::new ### Description Create a new fee calculator. ### Signature ```rust pub fn new(lamports_per_signature: u64) -> Self ``` ``` -------------------------------- ### Lazy Program Entrypoint Definition Source: https://github.com/anza-xyz/pinocchio/blob/main/sdk/README.md Use `lazy_program_entrypoint!` for programs where on-demand input parsing is desired. This macro defers parsing of program ID, accounts, and instruction data until explicitly requested via methods on `InstructionContext`. Remember to set up a global allocator and panic handler separately. ```rust use pinocchio::{ default_allocator, default_panic_handler, entrypoint::InstructionContext, lazy_program_entrypoint, ProgramResult }; lazy_program_entrypoint!(process_instruction); default_allocator!(); default_panic_handler!(); pub fn process_instruction( mut context: InstructionContext ) -> ProgramResult { Ok(()) } ``` -------------------------------- ### Define Compiler Hints Module Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/compiler-hints.md Defines the module for compiler hints, including cold_path, likely, and unlikely functions. ```rust pub mod hint { pub const fn cold_path() { ... } pub const fn likely(b: bool) -> bool { ... } pub const fn unlikely(b: bool) -> bool { ... } } ``` -------------------------------- ### Add pinocchio-memo Dependency Source: https://github.com/anza-xyz/pinocchio/blob/main/programs/memo/README.md Add the pinocchio-memo dependency to your Cargo.toml file using the cargo add command. ```bash cargo add pinocchio-memo ``` -------------------------------- ### Calculate Minimum Rent Balance with Validation Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Calculates the minimum lamports required for rent exemption for a given data length. It includes validation to prevent overflows and checks against maximum data length. ```rust pub fn try_minimum_balance(&self, data_len: usize) -> Result ``` -------------------------------- ### Compile Error: Mutually Exclusive Account Resize Features Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md Attempting to enable both `account-resize` and `unsafe-account-resize` features for Pinocchio will result in a compilation error, as these features are mutually exclusive. ```toml # This will NOT compile [dependencies] pinocchio = { version = "0.11", features = ["account-resize", "unsafe-account-resize"] } ``` -------------------------------- ### Error Handling with Unlikely Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/compiler-hints.md Demonstrates using `unlikely` for efficient error handling by marking the error path as cold. ```rust use pinocchio::hint::unlikely; use pinocchio::error::ProgramError; fn process(value: u64) -> Result<(), ProgramError> { if unlikely(value == 0) { return Err(ProgramError::InvalidArgument); } // Process the valid value Ok(()) } ``` -------------------------------- ### Calculate Minimum Rent Balance Unchecked Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-core.md Calculates the minimum lamports for rent exemption without performing any validation. Use this when performance is critical and overflow conditions are guaranteed not to occur. ```rust pub fn minimum_balance_unchecked(&self, data_len: usize) -> u64 ``` -------------------------------- ### Create InstructionContext (Unchecked) Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/entrypoint-functions.md Creates a new InstructionContext from a raw buffer pointer. The caller must ensure the input is a valid SVM loader input buffer. ```rust pub unsafe fn new_unchecked(input: *mut u8) -> Self ``` -------------------------------- ### Configure Workspace Resolver Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/configuration.md Set the workspace resolver to version 2, which is required for modern Cargo versions. ```toml [workspace] resolver = "2" ``` -------------------------------- ### Instructions Sysvar Definition Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/sysvars-advanced.md Defines the public key for the Instructions sysvar and the basic structure for wrapping sysvar data. ```rust pub const INSTRUCTIONS_ID: Address = /* Sysvar1nstructions1111111111111111111111111 */; pub struct Instructions> { data: T, } ``` -------------------------------- ### Reading Account Balance Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Safely reads the lamport balance of an account using `AccountView::lamports()`. ```rust use pinocchio::{ AccountView, ProgramResult, error::ProgramError, }; pub fn read_account_balance(account: &AccountView) -> Result { Ok(account.lamports()) } ``` -------------------------------- ### InstructionContext Entrypoint Structure Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/types.md Defines the InstructionContext structure, used for lazy instruction parsing and managing buffer and remaining data. ```rust pub struct InstructionContext { buffer: *mut u8, remaining: u64, } ``` -------------------------------- ### Safe Account Growth with account-resize Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/account-resizing.md Use this snippet when you need to safely increase the size of an account. It utilizes the `Resize` trait and performs necessary validations. ```rust use pinocchio::{AccountView, ProgramResult, Resize}; pub fn grow_account(account: &mut AccountView, additional_bytes: usize) -> ProgramResult { let new_size = account.data_len() + additional_bytes; account.resize(new_size)?; // New bytes are zeroed and ready to use let data = account.try_borrow_mut()?; // Write to new space Ok(()) } ``` -------------------------------- ### Safe Account Resizing with Validation Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/quick-start.md Use this method for safe account resizing when the `account-resize` feature is enabled. It ensures the new size is valid before resizing. ```rust use pinocchio::{AccountView, Resize, ProgramResult}; pub fn expand_account(account: &mut AccountView, additional_size: usize) -> ProgramResult { let new_size = account.data_len() + additional_size; account.resize(new_size)?; // New bytes are zeroed and ready to use let mut data = account.try_borrow_mut()?; // Write to the new space Ok(()) } ``` -------------------------------- ### Safe Account Shrinking with account-resize Source: https://github.com/anza-xyz/pinocchio/blob/main/_autodocs/account-resizing.md This snippet demonstrates how to safely reduce the size of an account using the `Resize` trait. Ensure the `keep_bytes` value is appropriate. ```rust use pinocchio::{AccountView, ProgramResult, Resize}; pub fn trim_account(account: &mut AccountView, keep_bytes: usize) -> ProgramResult { account.resize(keep_bytes)?; Ok(()) } ```