'How to withdraw sol/lamports from PDA in solana

I transfer the SOL/Lamports to the PDA accounts but I am not able to withdraw SOL from PDA back.

Transfer SOL to PDA

I generate PDA account from the below given code.

 const GREETING_SEED = 'Hello';
  greetedPubkey = await PublicKey.createWithSeed(
    payer.publicKey,
    GREETING_SEED,
    programId,
  );
const transaction = new Transaction().add(
      SystemProgram.createAccountWithSeed({
        fromPubkey: payer.publicKey,
        basePubkey: payer.publicKey,
        seed: GREETING_SEED,
        newAccountPubkey: greetedPubkey,
        lamports,
        space: GREETING_SIZE,
        programId,
      }),
    );
    await sendAndConfirmTransaction(connection, transaction, [payer]);

Transaction of Sol make using below code snippet:

 transaction.add(
    SystemProgram.transfer({
      fromPubkey:toaccount.publicKey,
      toPubkey:  greetedPubkey,
      lamports: LAMPORTS_PER_SOL/100,
      programId: programId,
     
    }),
    
  );
  const signature=await sendAndConfirmTransaction(connection, transaction, [toaccount]);

Above code is working fine.

Withdraw SOL from PDA

But I am not able to withdraw SOL from the PDA account.

transaction.add(
    SystemProgram.transfer({
      fromPubkey: greetedPubKey,
      toPubkey:  toaccount.publicKey,
      lamports: LAMPORTS_PER_SOL/100,
      programId: programId,

    }),

  );
  const signature=await sendAndConfirmTransaction(connection, transaction, [greetedPubKey]);

I try all the way to do it. But not able to sign transaction using PDA address. Is there any other way or Point if I make any mistake



Solution 1:[1]

An account that is assigned to a program, like greetedPubkey is after doing createAccountWithSeed, can only have its data changed or lamports deducted by the program itself. Here's an excerpt from the docs:

A created account is initialized to be owned by a built-in program called the System program and is called a system account aptly. An account includes "owner" metadata. The owner is a program id. The runtime grants the program write access to the account if its id matches the owner. For the case of the System program, the runtime allows clients to transfer lamports and importantly assign account ownership, meaning changing the owner to a different program id. If an account is not owned by a program, the program is only permitted to read its data and credit the account.

https://docs.solana.com/developing/programming-model/accounts#ownership-and-assignment-to-programs

In order to transfer the lamports back then, you must have your program process an instruction to move the lamports from greetedPubkey back to your account, for example, by doing:

**from_account.try_borrow_mut_lamports()? -= amount_of_lamports;
**to_account.try_borrow_mut_lamports()? += amount_of_lamports;

You can find the full example at https://solanacookbook.com/references/programs.html#how-to-transfer-sol-in-a-program

This isn't part of your question, but as an addendum, an account created with createAccountWithSeed is not a PDA, so your program will not be able to sign for it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jon C