I am trying to build a kind of a complex instruction in which there are lots of accounts and variables. I guess, I can't handle memory well that why there are some errors like "Access violation in unknown section error"
I am also using Box<> wrapper for smart pointers to reduce stack usage.
How can I solve that issue? I am not sure if I use zero_copy
account constraint
#[derive(Accounts)]#[instruction(data: FractionSplitData)]pub struct FractionSplit<'info> { #[account( mut @ Error::AccountNotMutable, signer @ Error::AccountNotSigner )] pub payer: Signer<'info>, #[account( seeds = [ADMINISTRATOR_SEED], seeds::program = administrator::id(), bump = administrator.bump )] pub administrator: Box<Account<'info, Administrator>>, // TODO: fraction_split_authority is required or not! Be sure that. If the pda that has fraction_create_authority also can split fractions, no problem #[account( signer @ Error::AccountNotSigner, )] pub user: Signer<'info>, /// CHECK: checked in MPL Core pub owner: AccountInfo<'info>, #[account( address = base_fraction.application )] pub application: Box<Account<'info, Application>>, /// CHECK: Checked in fraction_create #[account( seeds = [ IDENTITY_SEED, application.key().as_ref(), identity.id.as_ref() ], seeds::program = guardian::id(), bump = identity.bump, )] pub identity: Box<Account<'info, Identity>>, #[account( address = base_fraction.asset )] pub asset: Box<Account<'info, Asset>>, /// CHECK: Checked in mpl-core. #[account( mut @ Error::AccountNotMutable, seeds = [ ASSET_MPL_CORE_COLLECTION_SEED, application.key().as_ref(), asset.key().as_ref() ], bump = Asset::asset_mpl_core_collection(application.key(), asset.key()).1, constraint = asset_mpl_core_collection.key() == asset.asset_mpl_core_collection.unwrap().clone().key() @ Error::AccountAssetMplCoreCollectionInvalid )] pub asset_mpl_core_collection: AccountInfo<'info>, #[account( mut, seeds = [ FRACTION_SEED, application.key().as_ref(), asset.key().as_ref(), data.base_fraction_id.as_ref() ], bump = base_fraction.bump )] pub base_fraction: Box<Account<'info, Fraction>>, /// CHECK: Checked in mpl-core. #[account( mut @ Error::AccountNotMutable, seeds = [ FRACTION_MPL_CORE_ASSET_SEED, application.key().as_ref(), asset.key().as_ref(), base_fraction.key().as_ref() ], bump = Fraction::fraction_mpl_core_asset(application.key(), asset.key(), base_fraction.key()).1 )] pub base_fraction_mpl_core_asset: AccountInfo<'info>, #[account( init, payer = payer, space = 8 + Fraction::INIT_SPACE, seeds = [ FRACTION_SEED, application.key().as_ref(), asset.key().as_ref(), data.new_first_fraction_id.as_ref() ], bump )] pub new_first_fraction: Box<Account<'info, Fraction>>, #[account( init, payer = payer, space = 8 + Fraction::INIT_SPACE, seeds = [ FRACTION_SEED, application.key().as_ref(), asset.key().as_ref(), data.new_second_fraction_id.as_ref() ], bump )] pub new_second_fraction: Box<Account<'info, Fraction>>, /// CHECK: Checked in mpl-core. #[account( mut @ Error::AccountNotMutable, seeds = [ FRACTION_MPL_CORE_ASSET_SEED, application.key().as_ref(), asset.key().as_ref(), new_first_fraction.key().as_ref() ], bump = Fraction::fraction_mpl_core_asset(application.key(), asset.key(), new_first_fraction.key()).1 )] pub new_first_fraction_mpl_core_asset: AccountInfo<'info>, /// CHECK: Checked in mpl-core. #[account( mut @ Error::AccountNotMutable, seeds = [ FRACTION_MPL_CORE_ASSET_SEED, application.key().as_ref(), asset.key().as_ref(), new_second_fraction.key().as_ref() ], bump = Fraction::fraction_mpl_core_asset(application.key(), asset.key(), new_second_fraction.key()).1 )] pub new_second_fraction_mpl_core_asset: AccountInfo<'info>, pub system_program: Program<'info, System>, /// CHECK: The MPL Core program #[account(address = mpl_core::ID)] pub mpl_core_program: AccountInfo<'info>,}#[derive(AnchorSerialize, AnchorDeserialize)]pub struct FractionSplitData { pub base_fraction_id: Pubkey, pub new_first_fraction_id: Pubkey, pub new_first_fraction_name: String, pub new_first_fraction_uri: String, pub new_second_fraction_id: Pubkey, pub new_second_fraction_name: String, pub new_second_fraction_uri: String, pub split_ratios: Vec<u64>,}//impl method// TODO: add validations and handling errorsimpl<'info> FractionSplit<'info> { pub fn process(&mut self, data: FractionSplitData) -> Result<()> { let base_fraction_key = self.base_fraction.key(); let first_fraction_key = self.new_first_fraction.key(); let first_fraction_bump = self.new_first_fraction.bump; let second_fraction_key = self.new_second_fraction.key(); let second_fraction_bump = self.new_second_fraction.bump; //determine the split ratios. Think the originial token amount is 10, and user wants to split it 2:3 // Validate split ratios first to fail early let first_ratio = data.split_ratios.get(0).ok_or(Error::InvalidSplitRatio)?; let second_ratio = data.split_ratios.get(1).ok_or(Error::InvalidSplitRatio)?; let total_ratio = first_ratio .checked_add(*second_ratio) .ok_or(Error::FractionSplitRatioOverflow)?; require!(total_ratio > 0, Error::InvalidSplitRatio); // Calculate new amounts once let base_amount = self.base_fraction.tokens_amount; let first_amount = base_amount .checked_mul(*first_ratio) .and_then(|v| v.checked_div(total_ratio)) .ok_or(Error::FractionSplitRatioOverflow)?; let second_amount = base_amount .checked_mul(*second_ratio) .and_then(|v| v.checked_div(total_ratio)) .ok_or(Error::FractionSplitRatioOverflow)?; msg!("new_fraction_amounts are calculated"); // --------- MARK: create the new fractions --------- self.new_first_fraction.create( FractionCreateData { fraction_id: data.new_first_fraction_id, fraction_name: data.new_first_fraction_name, fraction_uri: data.new_first_fraction_uri, tokens_amount: first_amount, },&self.identity,&self.new_first_fraction_mpl_core_asset,&self.payer,&self.owner,&self.system_program,&self.mpl_core_program,&self.application,&self.asset,&self.asset_mpl_core_collection, first_fraction_key, first_fraction_bump, )?; msg!("new_first_fraction created"); self.new_second_fraction.create( FractionCreateData { fraction_id: data.new_second_fraction_id, fraction_name: data.new_second_fraction_name, fraction_uri: data.new_second_fraction_uri, tokens_amount: second_amount, },&self.identity,&self.new_second_fraction_mpl_core_asset,&self.payer,&self.owner,&self.system_program,&self.mpl_core_program,&self.application,&self.asset,&self.asset_mpl_core_collection, second_fraction_key, second_fraction_bump, )?; msg!("new_second_fraction created"); // burn the original fraction self.base_fraction.burn(&self.identity,&self.base_fraction_mpl_core_asset,&self.payer,&self.mpl_core_program,&self.application,&self.asset,&self.asset_mpl_core_collection, base_fraction_key, )?; // close base_fraction account self.base_fraction.close(self.payer.to_account_info())?; Ok(()) }}