2

Following the helloworld example, I have a client script that is supposed to create a data account for a program account:

export async function createAccount(connection,payer,programId,accountPubkey) {
  const lamports = await connection.getMinimumBalanceForRentExemption(ACCOUNT_SIZE);
  const transaction = new Transaction();
  const instruction = {
    basePubkey: payer.publicKey,
    fromPubkey: payer.publicKey,
    lamports,
    newAccountPubkey: accountPubkey,
    programId,
    seed: 'seed-string',
    space: ACCOUNT_SIZE
  };
  const tx = SystemProgram.createAccountWithSeed(instruction);
  transaction.add(tx);

  await sendAndConfirmTransaction(connection, transaction, [payer]);
}

This does what you expect - creates an account with <SCHEMA_SIZE> + 4 bytes allocated.

However, the program account seems unable to deserialize the account data:

SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Failed to serialize or deserialize account data: Unknown

Smart Contract

pub fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    let mut accounts_iter = accounts.iter();
    if let Some(account) = accounts_iter.next() {
        let mut message_account = MessageAccount::try_from_slice(&account.data.borrow())?;

From debugging, it appears the account data is not created with the correct 4 bytes:

  logs: [
    'Program 66turS2ScF6revuKuxN6Hc5aKAv6bvh2VFTmJ49s22Wj invoke [1]',
    'Program log: 284 RefCell { value: [0, 0, 0, 0, 0, 0,...

I would expect the first 4 bytes to be:

284 RefCell { value: [24, 1, 0, 0,

And my understanding is this denotes the struct has 24 bytes and 1 field?

Obviously, nothing in the client code can tell the account data to have this, but without forcing these values, the deserialization does not work:

let mut data = [0u8; 284];
data[0] = 24;data[1] = 1;data[2] = 0;data[3] = 0;
let account = AccountInfo::new(&program_id,false,true,&mut lam,&mut data,&program_id,false,2);
let accounts = vec![account];
let instruction_data = "Test".as_bytes();
let result = process_instruction(&program_id, &accounts, instruction_data);
// This works as expected
assert_eq!(result, Ok(()));

What am I missing?

1 Answer 1

1

createAccountWithSeed just allocates the space and assigns it to the program, and no data is written, so you should always see all zeroes in the program.

The failed deserialization likely means something is up with MessageAccount. Try writing some unit tests to try deserializing it from a slice of bytes to make sure that it's behaving as expected.

I don't know where you got the And my understanding is this denotes the struct has 24 bytes and 1 field? part, but that's not the Borsh serialization format. You can check it out at https://github.com/near/borsh#specification

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.