I created an auction with escrow. I succesfully create a campaign account, and can do the first bid. But I try a second bid, the program should send the previous bid back to the previous bidder. Every time I try this I get this error:
Proxy {logs: Array(4), programErrorStack: wt, stack: 'Error: failed to send transaction: Transaction sim…id (webpack-internal:///./pages/index.jsx:110:13)', message: 'failed to send transaction: Transaction simulation…alances before and after instruction do not match'}
[[Handler]]
:
Object
[[Target]]
:
Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: sum of account balances before and after instruction do not match at Connection.sendEncodedTransaction (webpack-internal:///../node_modules/@solana/web3.js/lib/index.browser.esm.js:7362:13) at async Connection.sendRawTransaction (webpack-internal:///../node_modules/@solana/web3.js/lib/index.browser.esm.js:7319:20) at async ct (webpack-internal:///../node_modules/@project-serum/anchor/dist/browser/index.js:59:9950) at async st.sendAndConfirm (webpack-internal:///../node_modules/@project-serum/anchor/dist/browser/index.js:59:8673) at async Object.eval [as bid] (webpack-internal:///../node_modules/@project-serum/anchor/dist/browser/index.js:74:48251) at async bid (webpack-internal:///./pages/index.jsx:110:13)
[[IsRevoked]]
:
false
This is my program:
use anchor_lang::prelude::*;
use anchor_lang::solana_program::entrypoint::ProgramResult;
declare_id!("9V9FcjfsbLV1LD3n7GrdScf1pNh9ReUiRiWK12JKQjDu");
#[program]
pub mod crowdfunding {
use super::*;
pub fn create(ctx: Context<Create>, name: String, description: String, minimum: u64, delta: u64) -> ProgramResult {
let campaign = &mut ctx.accounts.campaign;
campaign.name = name;
campaign.description = description;
campaign.highest_bid = minimum;
campaign.minimum = minimum;
campaign.delta = delta;
campaign.highest_bidder = *ctx.accounts.user.key;
campaign.admin = *ctx.accounts.user.key;
Ok(())
}
pub fn close(ctx: Context<Close>) -> ProgramResult {
let campaign = &mut ctx.accounts.campaign;
let user = &mut ctx.accounts.user;
if campaign.admin != *user.key {
return Err(ProgramError::IllegalOwner);
}
let rent_balance = Rent::get()?.minimum_balance(campaign.to_account_info().data_len());
if **campaign.to_account_info().lamports.borrow() - rent_balance < campaign.highest_bid {
return Err(ProgramError::InsufficientFunds);
}
**campaign.to_account_info().try_borrow_mut_lamports()? -= campaign.highest_bid;
**user.to_account_info().try_borrow_mut_lamports()? += campaign.highest_bid;
Ok(())
}
pub fn bid(ctx: Context<Bid>, amount: u64) -> ProgramResult {
let campaign = &mut ctx.accounts.campaign;
let old_bid = &campaign.highest_bid;
let old_bidcopy = &campaign.highest_bid;
let old_bidder = &mut ctx.accounts.old_bidder;
if amount < ( campaign.highest_bid + campaign.delta ) {
return Err(ProgramError::InsufficientFunds);
}
if campaign.highest_bidder != *old_bidder.key {
return Err(ProgramError::IllegalOwner);
}
if campaign.admin != *old_bidder.key {
let rent_balance = Rent::get()?.minimum_balance(campaign.to_account_info().data_len());
if **campaign.to_account_info().lamports.borrow() - rent_balance < campaign.highest_bid {
return Err(ProgramError::InsufficientFunds);
}
**campaign.to_account_info().try_borrow_mut_lamports()? -= *old_bid;
**old_bidder.to_account_info().try_borrow_mut_lamports()? += *old_bidcopy ;
}
let ix = anchor_lang::solana_program::system_instruction::transfer(
&ctx.accounts.user.key(),
&ctx.accounts.campaign.key(),
amount
);
anchor_lang::solana_program::program::invoke(
&ix,
&[
ctx.accounts.user.to_account_info(),
ctx.accounts.campaign.to_account_info()
]
);
(&mut ctx.accounts.campaign).highest_bid = amount;
(&mut ctx.accounts.campaign).highest_bidder = ctx.accounts.user.key();
Ok(())
}
}
#[derive(Accounts)]
#[instruction(name: String)]
pub struct Create<'info> {
#[account(init,
payer=user,
space=1000,
seeds=[
user.key().as_ref(),
b"_",
name.as_ref()
], bump)]
pub campaign: Account<'info, Campaign>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>
}
#[derive(Accounts)]
pub struct Close<'info> {
#[account(mut)]
pub campaign: Account<'info, Campaign>,
#[account(mut)]
pub user: Signer<'info>
}
#[derive(Accounts)]
pub struct Bid<'info> {
#[account(mut)]
pub campaign: Account<'info, Campaign>,
#[account(mut)]
pub user: Signer<'info>,
/// CHECK We check it with campaign data
#[account(mut)]
pub old_bidder: AccountInfo<'info>,
pub system_program: Program<'info, System>
}
#[account]
pub struct Campaign {
pub admin: Pubkey,
pub highest_bidder: Pubkey,
name: String,
description: String,
minimum: u64,
delta: u64,
highest_bid: u64
}
I was also wondering: Who will pay for this transaction (send the SOL back). It should be the new bidder... Thank you very much for your time!