Did you solve this? I am having the exact same issue.
I am able to realloc (increase and decrease) if I remove the token transfer code in the instruction. I'm also able to do the token transfer by itself if I remove the realloc.
But if I combine them both I can only increase the PDA's size, not decrease, and I get the same error [Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: sum of account balances before and after instruction do not match]
.
use anchor_spl::{
associated_token::AssociatedToken,
token::{self, Mint, Token, TokenAccount, Transfer as SplTransfer},
};
#[derive(Accounts)]
#[instruction(description: String)]
pub struct EditProfile<'info> {
#[account(mut)]
pub owner: Signer<'info>,
#[account(mut)]
pub token_mint: Account<'info, Mint>,
#[account(mut,
associated_token::mint = token_mint,
associated_token::authority = owner,
)]
pub owner_ata: Account<'info, TokenAccount>,
#[account(mut, seeds = [b"user", owner.key().as_ref()], bump)]
pub user: Account<'info, User>,
//
#[account(
init_if_needed,
payer = owner,
associated_token::mint = token_mint,
associated_token::authority = user,
)]
pub user_ata: Account<'info, TokenAccount>,
#[account(
mut,
seeds = [b"profile", owner.key().as_ref()],
bump,
realloc = 8 + Post::BASE_SIZE + description.len(),
realloc::payer = owner,
realloc::zero = false,
)]
pub profile: Account<'info, Post>,
pub system_program: Program<'info, System>,
pub token_program: Program<'info, Token>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub rent: Sysvar<'info, Rent>,
}
pub fn edit_profile(
ctx: Context<EditProfile>,
description: String,
) -> Result<()> {
let profile = &mut ctx.accounts.profile;
profile.edit(description);
// instruction works if this is removed:
token::transfer(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
SplTransfer {
from: ctx.accounts.owner_ata.to_account_info(),
to: ctx.accounts.user_ata.to_account_info(),
authority: ctx.accounts.owner.to_account_info(),
}
),
COST_TO_EDIT_PROFILE,
)?;
Ok(())
}