How do I close an account, empty the rent into a wrapped sol account, and then sync it?

Viewed 1869

I have an account that stores some data and is owned by my Solana program. I'd like to implement a Close instruction that "closes" the account and transfers the remaining native-SOL into a wrapped-SOL token account, and then call spl-token's sync_native instruction.

If I try to use the SystemProgram's Transfer instruction, I hit the error in the processor that says Transfer: from must not carry data.

So instead, I just do this:

let dest_starting_lamports = dest_account_info.lamports();
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports
        .checked_add(source_account_info.lamports())
        .unwrap();

**source_account_info.lamports.borrow_mut() = 0;

However, if I later call sync_native via CPI anywhere in the same instruction, I get an error:

sum of account balances before and after instruction do not match

Is it possible to both modify the lamport values (transfer) of accounts AND call a CPI instruction? Or alternatively, is there a way to close the account with the SystemProgram?

2 Answers

Okay So here I want to figure it out that CPI in a single instructions causes conflict with each other as in my case I was using token program and system program in a single instruction and I figured it out that token program CPI should be done above the system program CPI.

This may be a bug in the runtime, because otherwise it looks like you're doing everything correctly. The only time this should fail is if dest_account_info and source_account_info are the same, but you mentioned that the sync_native is what caused the problem.

As a workaround, you can have sync_native done as a separate instruction in the transaction rather than as a CPI.

Related