1

yo

im experiementing with CPI calls on devnet (running test validator locally), and I get this "Unknown program 11111111111111111111111111111111" error with An account required by the instruction is missing. here is the code for the lib and for the client:

lib:

use solana_program::{
    account_info::{next_account_info, AccountInfo},
    borsh::try_from_slice_unchecked,
    entrypoint,
    entrypoint::ProgramResult,
    msg,
    program::invoke_signed,
    pubkey::Pubkey,
    system_instruction,
    sysvar::{rent::Rent, Sysvar},
};
use std::convert::TryInto;
pub mod instruction;
pub mod state;
use borsh::BorshSerialize;
use instruction::MovieInstruction;
use state::MovieAccountState;

entrypoint!(process_instruction);

pub fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    let instruction = MovieInstruction::unpack(instruction_data)?;
    match instruction {
        MovieInstruction::AddMovieReview {
            title,
            rating,
            description,
        } => add_movie_review(program_id, accounts, title, rating, description),
    }
}

pub fn add_movie_review(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    title: String,
    rating: u8,
    description: String,
) -> ProgramResult {
    msg!("Adding movie review...");
    msg!("Title: {}", title);
    msg!("Rating: {}", rating);
    msg!("Description: {}", description);

    // Get Account iterator
    let account_info_iter = &mut accounts.iter();

    // Get accounts
    let initializer = next_account_info(account_info_iter)?;
    let pda_account = next_account_info(account_info_iter)?;
    let program = next_account_info(account_info_iter)?;

    // Derive PDA and check that it matches client
    let (pda, bump_seed) = Pubkey::find_program_address(
        &[initializer.key.as_ref(), title.as_bytes().as_ref()],
        program_id,
    );

    // Calculate account size required
    let account_len: usize = 1 + 1 + (4 + title.len()) + (4 + description.len());

    // Calculate rent required
    let rent = Rent::get()?;
    let rent_lamports = rent.minimum_balance(account_len);

    // Create the account
    invoke_signed(
        &system_instruction::create_account(
            initializer.key,
            pda_account.key,
            rent_lamports,
            account_len.try_into().unwrap(),
            program_id,
        ),
        &[
            initializer.clone(),
            pda_account.clone(),
            program.clone(),
        ],
        &[&[
            initializer.key.as_ref(),
            title.as_bytes().as_ref(),
            &[bump_seed],
        ]],
    )?;

    msg!("PDA created: {}", pda);

    msg!("unpacking state account");
    let mut account_data =
        try_from_slice_unchecked::<MovieAccountState>(&pda_account.data.borrow()).unwrap();
    msg!("borrowed account data");

    account_data.title = title;
    account_data.rating = rating;
    account_data.description = description;
    account_data.is_initialized = true;

    msg!("serializing account");
    account_data.serialize(&mut &mut pda_account.data.borrow_mut()[..])?;
    msg!("state account serialized");

    Ok(())
}

client:

use anyhow::Result;
// use borsh::{BorshDeserialize, BorshSerialize};
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
    commitment_config::CommitmentConfig,
    instruction::{AccountMeta, Instruction},
    message::Message,
    pubkey,
    pubkey::Pubkey,
    signature::{Keypair, Signature, Signer},
    transaction::Transaction,
};

use solana_uniswapv3_core::instruction::MovieInstruction;

//pg id E4smcTetGFV1kKe328CVwKNc9bMsHSUU8bxQAz2JiJBJ

fn main() {
    const MY_WALLET_ADDRESS: &str = "4aFf4bacjbusdoQVXdQTTann2reoDzUWCULPL8arsjcT";
    const PROGRAM_KEYPAIR: [u8; 64] = [
        53, 139, 19, 121, 208, 187, 65, 171, 215, 223, 27, 248, 72, 111, 180, 230, 83, 212, 104,
        155, 54, 41, 89, 6, 57, 114, 44, 21, 180, 207, 238, 207, 230, 234, 194, 249, 239, 135, 0,
        120, 164, 66, 71, 208, 154, 242, 46, 243, 123, 78, 234, 135, 91, 45, 49, 233, 127, 253,
        166, 245, 82, 247, 217, 21,
    ];
    let ACCOUNT_KEYPAIR: [u8; 64] = [
        232, 79, 59, 39, 17, 25, 68, 190, 46, 152, 92, 192, 113, 2, 110, 82, 137, 115, 86, 191,
        199, 163, 103, 216, 28, 79, 212, 219, 49, 50, 230, 93, 53, 23, 204, 161, 199, 145, 73, 224,
        201, 175, 182, 50, 109, 80, 208, 89, 233, 123, 108, 248, 54, 206, 174, 10, 254, 244, 219,
        21, 160, 184, 160, 176,
    ];
    let rpc_url = String::from("http://127.0.0.1:8899");

    let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
    let pkeypair =
        Keypair::from_bytes(&PROGRAM_KEYPAIR).expect("Failed to create keypair from bytes");
    let akeypair =
        Keypair::from_bytes(&ACCOUNT_KEYPAIR).expect("Failed to create keypair from bytes");
    let signer: &dyn Signer = &akeypair;

    let movie_review = MovieInstruction::AddMovieReview {
        title: "title".to_string(),
        rating: 5,
        description: "description".to_string(),
    };

    let (pda_account, bump) = Pubkey::find_program_address(
        &[
            akeypair.pubkey().as_ref(),
            "title".to_string().as_bytes().as_ref(),
        ],
        &pkeypair.pubkey(),
    );

    let instruction = Instruction::new_with_borsh(
        pkeypair.pubkey(),
        &movie_review,
        vec![
            AccountMeta::new_readonly(akeypair.pubkey(), true),
            AccountMeta::new(pda_account, false),
            AccountMeta::new_readonly(pkeypair.pubkey(), false),
        ],
    );

    let tx_hash = submit_transaction(
        &connection,
        signer,
        instruction,
        CommitmentConfig::confirmed(),
    );

    // println!("hash: {:?}", tx_hash);
}

/// Submits the program instruction as per the
/// instruction definition
pub fn submit_transaction(
    rpc_client: &RpcClient,
    wallet_signer: &dyn Signer,
    instruction: Instruction,
    commitment_config: CommitmentConfig,
) -> Result<Signature, Box<dyn std::error::Error>> {
    let mut transaction =
        Transaction::new_unsigned(Message::new(&[instruction], Some(&wallet_signer.pubkey())));
    let recent_blockhash = rpc_client
        .get_latest_blockhash()
        .map_err(|err| format!("error: unable to get recent blockhash: {}", err))?;
    transaction
        .try_sign(&vec![wallet_signer], recent_blockhash)
        .map_err(|err| format!("error: failed to sign transaction: {}", err))?;

    // Simulate transaction to get logs
    println!("{:?}", rpc_client.simulate_transaction(&transaction));

    let signature = rpc_client
        .send_and_confirm_transaction_with_spinner_and_commitment(&transaction, commitment_config)
        .map_err(|err| format!("error: send transaction: {}", err))?;
    Ok(signature)
}

full log:

Ok(Response { context: RpcResponseContext { slot: 53211, api_version: Some(RpcApiVersion(Version { major: 1, minor: 17, patch: 25 })) }, value: RpcSimulateTransactionResult { err: Some(InstructionError(0, MissingAccount)), logs: Some(["Program GYQPuJRH45Z6rpomwj52AtoApYYgk1Pg5XT5yDjPsbuN invoke [1]", "Program log: Adding movie review...", "Program log: Title: title", "Program log: Rating: 5", "Program log: Description: description", "Unknown program 11111111111111111111111111111111", "Program GYQPuJRH45Z6rpomwj52AtoApYYgk1Pg5XT5yDjPsbuN consumed 10092 of 200000 compute units", "Program GYQPuJRH45Z6rpomwj52AtoApYYgk1Pg5XT5yDjPsbuN failed: An account required by the instruction is missing"]), accounts: None, units_consumed: Some(0), return_data: None } })

i tried to look online for people having similar issues but could only find one who had forgotten to submit the system_program account which i do submit.

thanks

1 Answer 1

2

fixed by sending solana system program (https://docs.solanalabs.com/runtime/programs) to the program and using its instance as a invoke_signed() account

1
  • Hi can you please elaborate on this, How you are you sending solana system program?
    – Lobo1897
    Commented Apr 30 at 16:36

Your Answer

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