I'm working on a Solana program and encountered an issue related to state management with Program Derived Accounts (PDAs).
I successfully created a state for my Solana program and saved it to a PDA (Program Derived Account). However, when I attempt to retrieve the state from the PDA, I encounter the following error: Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Failed to serialize or deserialize account data: Unknown
here is instruction code:
use borsh::{BorshSerialize, BorshDeserialize};
use solana_program::{
account_info::{AccountInfo, next_account_info},
entrypoint::ProgramResult,
program_error::ProgramError,
pubkey::Pubkey,
sysvar::{rent::Rent, Sysvar},
};
use std::collections::BTreeMap;
use crate::state::{State, Distribution};
use solana_program::msg;
#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct InitializeArgs {
pub initial_ticket_prices: Vec<u64>,
pub initial_token_addresses: Vec<Pubkey>,
pub min_buy_amounts: Vec<u64>,
pub distributions: Vec<Distribution>,
pub max_tickets_per_user: u64,
pub total_tickets_threshold: u64,
pub depth: u64,
pub rewards_percent_by_depth: Vec<u64>,
pub ref_code_length: u64
}
pub fn initialize(program_id: &Pubkey, accounts: &[AccountInfo], args: InitializeArgs) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let state_account = next_account_info(account_info_iter)?;
let mut state = State::try_from_slice(&state_account.data.borrow()).unwrap_or_else(|_| State {
ticket_prices: BTreeMap::new(),
min_buy_amounts: BTreeMap::new(),
deposited_by_token: BTreeMap::new(),
address_to_ref_code: BTreeMap::new(),
ref_code_to_address: BTreeMap::new(),
referrer_to_referrals: BTreeMap::new(),
referral_to_referrer: BTreeMap::new(),
user_tickets: BTreeMap::new(),
user_rewards: BTreeMap::new(),
rewards_percent_by_depth: BTreeMap::new(),
distributions: Vec::new(),
max_tickets_per_user: 0,
total_tickets_threshold: 0,
ref_code_length: 0,
total_tickets: 0,
depth: 0,
paused: false,
});
let token_addresses_clone = args.initial_token_addresses.clone();
args.initial_token_addresses.into_iter().zip(args.initial_ticket_prices).for_each(|(token_address, price)| {
state.ticket_prices.insert(token_address, price);
});
token_addresses_clone.into_iter().zip(args.min_buy_amounts).for_each(|(token_address, amount)| {
state.min_buy_amounts.insert(token_address, amount);
});
state.distributions = args.distributions;
state.max_tickets_per_user = args.max_tickets_per_user;
state.total_tickets_threshold = args.total_tickets_threshold;
state.depth = args.depth;
state.ref_code_length = args.ref_code_length;
args.rewards_percent_by_depth.into_iter().enumerate().for_each(|(index, percent)| {
state.rewards_percent_by_depth.insert(index as u64 + 1, percent);
});
state.serialize(&mut *state_account.data.borrow_mut())?;
let state = State::try_from_slice(&state_account.data.borrow())?;
Ok(())
}
initialize
is confirmed before sending your next transaction, or perhaps the next transaction is using an incorrect pubkey.