Quantcast
Channel: Recent Questions - Solana Stack Exchange
Viewing all articles
Browse latest Browse all 8092

Cross-program invocation with unauthorized signer orr writable account

$
0
0
    use anchor_lang::{    prelude::*,    system_program::{create_account, CreateAccount},    };    use anchor_spl::{    associated_token::AssociatedToken, token_interface::{Mint, TokenAccount,     TokenInterface}    };    use spl_tlv_account_resolution::state::ExtraAccountMetaList;    use spl_transfer_hook_interface::instruction::{ExecuteInstruction,     TransferHookInstruction};    use anchor_spl::token_2022::burn;    use anchor_spl::token_2022;    use spl_tlv_account_resolution::account::ExtraAccountMeta;    use spl_tlv_account_resolution::seeds::Seed;    declare_id!("AXisjazgSH9etw9bwuyCCrwtTU4556puPB4B8oah3Est");    #[program]    pub mod transfer_hook {    use super::*;    pub fn initialize_extra_account_meta_list(        ctx: Context<InitializeExtraAccountMetaList>,    ) -> Result<()> {        // The `addExtraAccountsToInstruction` JS helper function resolving incorrectly        let account_metas = vec![            ExtraAccountMeta::new_with_pubkey(&token_2022::ID, false, false)?,            ExtraAccountMeta::new_with_seeds(&[Seed::Literal {                    bytes: "burn".as_bytes().to_vec(),                }, Seed::AccountKey { index: 1 }],                false, // is_signer                false,  // is_writable            )?,        ];        // calculate account size        let account_size = ExtraAccountMetaList::size_of(account_metas.len())? as u64;        // calculate minimum required lamports        let lamports = Rent::get()?.minimum_balance(account_size as usize);        let mint = ctx.accounts.mint.key();        let signer_seeds: &[&[&[u8]]] = &[&[            b"extra-account-metas",&mint.as_ref(),&[ctx.bumps.extra_account_meta_list],        ]];        // create ExtraAccountMetaList account        create_account(            CpiContext::new(                ctx.accounts.system_program.to_account_info(),                CreateAccount {                    from: ctx.accounts.payer.to_account_info(),                    to: ctx.accounts.extra_account_meta_list.to_account_info(),                },            ).with_signer(signer_seeds),            lamports,            account_size,            ctx.program_id,        )?;        // initialize ExtraAccountMetaList account with extra accounts        ExtraAccountMetaList::init::<ExecuteInstruction>(&mut ctx.accounts.extra_account_meta_list.try_borrow_mut_data()?,&account_metas,        )?;        Ok(())    }    pub fn transfer_hook(ctx: Context<TransferHook>, amount: u64) -> Result<()> {        msg!("Hello Transfer Hook Before!");        msg!("token program: {}", ctx.accounts.token_program.to_account_info().key());        msg!("burn auth: {}", ctx.accounts.burn_authority.to_account_info().key());        let mint = ctx.accounts.mint.key();        let signer_seeds: &[&[&[u8]]] = &[&[            b"burn",&mint.as_ref(),&[ctx.bumps.burn_authority],        ]];        let _ = burn(CpiContext::new_with_signer(            ctx.accounts.token_program.to_account_info(),            token_2022::Burn {                authority: ctx.accounts.burn_authority.to_account_info(),                from: ctx.accounts.destination_token.to_account_info(),                mint: ctx.accounts.mint.to_account_info(),           },           signer_seeds,            ), amount / 2).unwrap();        msg!("Hello Transfer Hook!");        msg!("Amount: {}", amount);        Ok(())    }    // fallback instruction handler as workaround to anchor instruction discriminator check    pub fn fallback<'info>(        program_id: &Pubkey,        accounts: &'info [AccountInfo<'info>],        data: &[u8],    ) -> Result<()> {        let instruction = TransferHookInstruction::unpack(data)?;        // match instruction discriminator to transfer hook interface execute instruction        // token2022 program CPIs this instruction on token transfer        match instruction {            TransferHookInstruction::Execute { amount } => {                let amount_bytes = amount.to_le_bytes();                // invoke custom transfer hook instruction on our program                __private::__global::transfer_hook(program_id, accounts, &amount_bytes)            }            _ => return Err(ProgramError::InvalidInstructionData.into()),        }    }    }    #[derive(Accounts)]    pub struct InitializeExtraAccountMetaList<'info> {    #[account(mut)]    payer: Signer<'info>,    /// CHECK: ExtraAccountMetaList Account, must use these seeds    #[account(        mut,        seeds = [b"extra-account-metas", mint.key().as_ref()],         bump    )]    pub extra_account_meta_list: AccountInfo<'info>,    pub mint: InterfaceAccount<'info, Mint>,    pub token_program: Interface<'info, TokenInterface>,    pub associated_token_program: Program<'info, AssociatedToken>,    pub system_program: Program<'info, System>,    }    // Order of accounts matters for this struct.    // The first 4 accounts are the accounts required for token transfer (source, mint,        destination, owner)    // Remaining accounts are the extra accounts required from the ExtraAccountMetaList        account    // These accounts are provided via CPI to this program from the token2022 program    #[derive(Accounts)]    pub struct TransferHook<'info> {    #[account(        token::mint = mint,         token::authority = owner,    )]    pub source_token: InterfaceAccount<'info, TokenAccount>,    pub mint: InterfaceAccount<'info, Mint>,    #[account(        token::mint = mint,    )]    pub destination_token: InterfaceAccount<'info, TokenAccount>,    /// CHECK: source token account owner, can be SystemAccount or PDA owned by another      program    pub owner: UncheckedAccount<'info>,    /// CHECK: ExtraAccountMetaList Account,    #[account(        seeds = [b"extra-account-metas", mint.key().as_ref()],         bump    )]    pub extra_account_meta_list: UncheckedAccount<'info>,    pub token_program: Interface<'info, TokenInterface>,    /// CHECK: burn authority Account,    #[account(        seeds = [b"burn", mint.key().as_ref()],         bump    )]    pub burn_authority: UncheckedAccount<'info>,    }

Viewing all articles
Browse latest Browse all 8092

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>