2

The callee program

#[program]
pub mod puppet {
    use super::*;
    pub fn initialize(_ctx: Context<Initialize>) -> Result<()> {
        Ok(())
    }

    pub fn set_data(ctx: Context<SetData>, data: u64) -> Result<()> {
        let puppet = &mut ctx.accounts.puppet;
        puppet.data = data;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init, payer = user, space = 8 + 8)]
    pub puppet: Account<'info, Data>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct SetData<'info> {
    #[account(mut,signer)]
    pub puppet: Account<'info, Data>,
    #[account(mut)]
    pub user: Signer<'info>,
}

#[account]
pub struct Data {
    pub data: u64,
}

The caller program


#[constant]
const USER_TEMP_ACCOUNT: &[u8] = b"USER_TEMP_ACCOUNT";

#[program]
mod puppet_master {
    use super::*;

    pub fn create_user_temp_account(ctx: Context<CreateUserTempAccount>) -> Result<()> {
        let (pubkey, bump) = Pubkey::find_program_address(
            &[USER_TEMP_ACCOUNT, ctx.accounts.signer.key().as_ref()],
            &ID,
        );
        anchor_lang::solana_program::program::invoke_signed(
            &anchor_lang::solana_program::system_instruction::create_account(
                &ctx.accounts.signer.key(),
                &pubkey,
                100000000,
                50,
                &anchor_lang::system_program::ID,
            ),
            &[
                ctx.accounts.signer.to_account_info(),
                ctx.accounts.user_account.to_account_info(),
            ],
            &[&[
                USER_TEMP_ACCOUNT,
                ctx.accounts.signer.key().as_ref(),
                &[bump],
            ]],
        )?;
        Ok(())
    }

    pub fn pull_strings(ctx: Context<PullStrings>, _data: u64) -> Result<()> {
        let cpi_program = ctx.accounts.puppet_program.to_account_info();
        let cpi_accounts = Initialize {
            puppet: ctx.accounts.puppet.to_account_info(),
            user: ctx.accounts.user_account.to_account_info(),
            system_program: ctx.accounts.system_program.to_account_info(),
        };
        let (_pubkey, bump) = Pubkey::find_program_address(
            &[USER_TEMP_ACCOUNT, ctx.accounts.signer.key().as_ref()],
            &ID,
        );
        puppet::cpi::initialize(CpiContext::new_with_signer(
            cpi_program,
            cpi_accounts,
            &[&[
                USER_TEMP_ACCOUNT,
                ctx.accounts.signer.key().as_ref(),
                &[bump],
            ]],
        ))
    }
}

#[derive(Accounts)]
pub struct PullStrings<'info> {
    /// CHECK: provide dummy program ID here
    #[account(mut, signer)]
    pub puppet: AccountInfo<'info>,
    pub puppet_program: Program<'info, Puppet>,
    // #[account(mut)]
    // pub user_account: Account<'info, UserAccount>,
    /// CHECK: provide dummy program ID here
    #[account(mut)]
    pub user_account: AccountInfo<'info>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct CreateUserTempAccount<'info> {
    /// CHECK: provide dummy program ID here
    #[account(mut)]
    pub user_account: AccountInfo<'info>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[account]
pub struct UserAccount {}


  • I am just trying to invoke initialize method of puppet program from puppet_master program in which pda is signer and payer.
  • As explained here, i am using system owned PDA as a signer and payer to invoke initialize method of puppet program.
  • When i am invoking pull_string method of puppet_master program to invoke initialize method of puppet program in which actual transaction signer is signer and payer it's working fine.
  • But when i am using system owned pda as a signer and payer i am getting error as "Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: invalid program argument".

1 Answer 1

2

Use below given code to create system program owned pda account.

    pub fn create_user_temp_account(ctx: Context<CreateUserTempAccount>) -> Result<()> {
        let (pubkey, bump) = Pubkey::find_program_address(
            &[USER_TEMP_ACCOUNT, ctx.accounts.signer.key().as_ref()],
            &ID,
        );
        let lamports = 1000000000;
        anchor_lang::solana_program::program::invoke_signed(
            &anchor_lang::solana_program::system_instruction::transfer(
                &ctx.accounts.signer.key(),
                &ctx.accounts.user_account.key(),
                lamports,
            ),
            &[
                ctx.accounts.signer.to_account_info(),
                ctx.accounts.user_account.to_account_info(),
            ],
            &[&[
                USER_TEMP_ACCOUNT,
                ctx.accounts.signer.key().as_ref(),
                &[bump],
            ]],
        )?;
        Ok(())
    }

You can check this post How to create an account in any other program using CPI in which PDA is used as signer and payer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.