6

I am trying to build an NFT marketplace where the NFT will be transferred to an escrow wallet a PDA with seeds and the SOL will be transferred from the buyer to a PDA with seeds = "bid" and address of the mint, Now upon successful completion of the NFT being deposited to the escrow wallet users will bid on the NFT and if there is a previous bidder then the amount will be transferred back to the previous bidder and the new bidder's bid will be transferred to the "bid" PDA Now I have successfully transferred the NFT from the escrow wallet to the buyer's wallet by using cpi to sign the transaction on behalf of my program but i also want to transfer the SOL from the PDA to the seller's wallet..i tried using https://solanacookbook.com/references/programs.html#how-to-transfer-sol-in-a-program to transfer the SOL stored in "bid" PDA(This PDA is owned by my program) to the previous bidder but nothing is happening i.e no SOL transfer is taking place from my bid account to the previous bidder though the program is returning success

  let amount_of_lamports: u64  = 1000000;
  let from_account = ctx.accounts.bid_state.to_account_info();
   let to_account = ctx.accounts.user_bidding_past.to_account_info();
    msg!("from_account is {}", ctx.accounts.bid_state.key() );
    msg!("to_account is {}", ctx.accounts.user_bidding_past.key );
**from_account.try_borrow_mut_lamports()? -= amount_of_lamports;
**to_account.try_borrow_mut_lamports()? += amount_of_lamports;

I am passing the user_bidding_past and bid_state as accounts in my function place_new_bids . bid_state is just a struct defining the bids.

#[account]
#[derive(Default)]
pub struct Bid {
// A primary key that allows us to derive other important accounts
idx: u64,

//amount that the user will bid with.
pub amount : u64,

// Alice
pub user_sending: Pubkey,

// the user bidding on the item.
pub user_bidding: Pubkey,

//the market wallet
pub market_wallet: Pubkey,

// The Mint of the token that bidder wants to bid on
pub mint_of_token_being_sent: Pubkey,

// The escrow wallet
pub escrow_wallet: Pubkey,

// An enumm that is to represent some kind of state machine
pub stage: u8,

}

Is there something that I am missing about the transfer being done in this way? because the cookbook mentions that Your Solana Program can transfer lamports from one account to another without 'invoking' the System program. The fundamental rule is that your program can transfer lamports from any account owned by your program to any account at all. And if I am on the wrong path can someone please guide me on the correct path to achieve what I am trying to do..thanks for your help in advance

                                                                **UPDATE 1**

I removed all the different parameters of the seeds from the "bid" account and only left the "bid" keyword as shown in the answer given but now I am getting the following error : Phantom - RPC Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: invalid program argument don't know what is the problem.

2
  • Share some more of your code please. It looks like the most likely issue is that the from and to accounts are being passed in as the same address. It would help to see the rest of your program & your test.
    – Joe C
    Commented Apr 14, 2023 at 19:30
  • I am sorry I couldn't post it earlier but it was my mistake that I didn't check thoroughly cause I found that the transaction was going through and the SOL transfers were happening but those are not reflected in the data shown in the transactions in solscan. Later found that the wallet sol amount is increasing and decreasing respectively. Commented Apr 29, 2023 at 21:08

3 Answers 3

4

For Anchor 0.29.0:

let lamports = ctx.accounts.my_account.get_lamports();
ctx.accounts.from.sub_lamports(amount)?;
ctx.accounts.to.add_lamports(amount)?;
1

let from = ctx.accounts.my_sol_vault.to_account_info();

let to = ctx.accounts.user_sol_vault.to_account_info();

**from.try_borrow_mut_lamports()? -= pool.deposit_amount;

**to.try_borrow_mut_lamports()? += pool.deposit_amount;

1
0

Here is an example in anchor sending SOL from PDA.

    pub fn process(&mut self, bump: u8) -> Result<()> {

        // transfer from pda
        let seeds = &["sol_bank".as_bytes(), &[bump]];

        let ix = anchor_lang::solana_program::system_instruction::transfer(
            &sol_bank.key(),
            &payer.key(),
            offer.amount,
        );

        anchor_lang::solana_program::program::invoke_signed(
            &ix,
            &[sol_bank.to_account_info(), payer.to_account_info()],
            &[&seeds[..]],
        )?;
    }

and make sure you add #[account(mut)] for payer and sol_bank

8
  • Hi..thank you for your answer..i just have a question that for the seeds i have "bid" and address of the mint ,so do I need to add that also after the "bid".as_bytes(),mint_of_token_being_sent.as_bytes()..like so?? Commented Aug 21, 2022 at 12:16
  • let seeds = &["sol_bank".as_bytes(), mint_of_token_being_sent.key.as_ref(), &[bump]];
    – vicyyn
    Commented Aug 21, 2022 at 12:23
  • If this answers your question, please mark this as answered and upvote. Thank you :)) solana.stackexchange.com/help/privileges/vote-up
    – vicyyn
    Commented Aug 21, 2022 at 12:24
  • hi now I am getting this error failed to send transaction: Transaction simulation failed: Error processing Instruction 0: invalid program argument Commented Aug 21, 2022 at 13:04
  • I used the following code for seeds let user_sending=ctx.accounts.user_sending.key(); let mint_of_token_being_sent=ctx.accounts.mint_of_token_being_sent.key(); let application_id=application_idx.to_le_bytes(); let seeds = &["bid".as_bytes(),user_sending.as_ref(), mint_of_token_being_sent.as_ref(), application_id.as_ref(), &[bid_bump]]; Commented Aug 21, 2022 at 13:24

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.