I would like to send spl-token to an onchain program pda account, so that It will be helpful for me to transfer tokens to destination address based on conditions provided in smart contract, with out the need for my actual private key. I want to know whether it is the secure way to store spl-token or is there any other way?
2 Answers
That is a good way to do it. You should probably take a look to PDA section on solana cookbook :
PDAs : https://solanacookbook.com/core-concepts/pdas.html https://docs.solana.com/developing/programming-model/calling-between-programs#program-derived-addresses
How to sign with a PDA : https://solanacookbook.com/references/accounts.html#how-to-sign-with-a-pda
Program (Rust):
use solana_program::{
account_info::next_account_info, account_info::AccountInfo, entrypoint,
entrypoint::ProgramResult, program::invoke_signed, pubkey::Pubkey, system_instruction,
};
entrypoint!(process_instruction);
fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let pda_account_info = next_account_info(account_info_iter)?;
let to_account_info = next_account_info(account_info_iter)?;
let system_program_account_info = next_account_info(account_info_iter)?;
// pass bump seed for saving compute budget
let bump_seed = instruction_data[0];
invoke_signed(
&system_instruction::transfer(
&pda_account_info.key,
&to_account_info.key,
100_000_000, // 0.1 SOL
),
&[
pda_account_info.clone(),
to_account_info.clone(),
system_program_account_info.clone(),
],
&[&[b"escrow", &[bump_seed]]],
)?;
Ok(())
}
Client :
let tx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: pda,
// Leave `false` here although we need a pda as a signer.
// It will be escalated on program if we use invoke_signed.
isSigner: false,
isWritable: true,
},
{
pubkey: to.publicKey,
isSigner: false,
isWritable: true,
},
{
pubkey: SystemProgram.programId,
isSigner: false,
isWritable: false,
},
],
data: Buffer.from(new Uint8Array([bump])),
programId: programId,
})
);
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
thats the right way to do it, potentially better to create an instruction for transferring funds from a funder wallet to the PDA.