I'm writing an English auction program that tries to refund the previous bidder if they are outbid.
I store funds from bidding in a PDA called auction
, and attempt to send them to the previous highest bidder if they get outbid. I'm getting this error related to the refund and am having a hard time diagnosing it:
failed to send transaction: Transaction simulation failed: Error processing Instruction 0: invalid program argument
Based on a response from another StackExchange question, I try to "sign" the transfer from the auction PDA to the previous bidder using the seeds and bump of the auction PDA account, but clearly something about how I'm doing it is wrong.
I also tried to refund the previous bidder by manually adjusting the lamports (it's commented out in the code below), but that produced the error sum of account balances before and after instruction do not match
.
Does anyone know why this is happening? Here is my bidding function:
pub fn place_bid(ctx: Context<PlaceBid>, amount: u64) -> Result<()> {
let auction = &mut ctx.accounts.auction;
let current_time = clock::Clock::get()?.unix_timestamp;
require!(
current_time >= auction.start_time,
AuctionError::AuctionNotStarted
);
require!(current_time <= auction.end_time, AuctionError::AuctionEnded);
require!(amount > auction.highest_bid, AuctionError::BidTooLow);
// Refund the previous highest bidder, if any
if auction.highest_bidder != Pubkey::default() {
let refund_amount = auction.highest_bid;
//attempt 1: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: invalid program argument
let bump = auction.bump;
let seeds= &[
b"auction1".as_ref(),
auction.nft_mint.as_ref(),
&[bump],
];
let seeds_slice = &[&seeds[..]];
let cpi_context = CpiContext::new_with_signer(
ctx.accounts.system_program.to_account_info(),
system_program::Transfer {
from: auction.to_account_info(),
to: ctx.accounts.highest_bidder_account.to_account_info(),
},
seeds_slice
);
system_program::transfer(cpi_context, refund_amount)?;
//attempt 2: Error processing Instruction 0: sum of account balances before and after instruction do not match
// **auction.to_account_info().try_borrow_mut_lamports()? -= refund_amount;
// **ctx.accounts.highest_bidder_account.to_account_info().try_borrow_mut_lamports()? += refund_amount;
}
// Transfer the new bid amount from the bidder to the auction account
let cpi_accounts = system_program::Transfer {
from: ctx.accounts.bidder.to_account_info(),
to: auction.to_account_info(),
};
let cpi_program = ctx.accounts.system_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
system_program::transfer(cpi_context, amount)?;
// Update the auction state
auction.highest_bid = amount;
auction.highest_bidder = *ctx.accounts.bidder.key;
Ok(())
}
Here are how the accounts are defined:
#[derive(Accounts)]
pub struct PlaceBid<'info> {
#[account(mut)]
pub auction: Account<'info, Auction>,
#[account(mut)]
pub bidder: Signer<'info>,
#[account(mut)]
pub bidder_account: SystemAccount<'info>,
#[account(mut)]
pub highest_bidder_account: SystemAccount<'info>,
pub system_program: Program<'info, System>,
}
My whole Rust program and test code is here, for reference. Please let me know if I can clarify anything.