2

I want to transfer my custom SPL-token programmatically from my vault (source token account) to George (user destination token account), where the transaction caller-payer is George. Hence, I must use a PDA, but I'm struggling to create and invoke my PDA correctly. Unlike #1, #2, #3, I'm coding in native Solana Rust - NO Anchor.

What I have:

  • token mint account
  • source token account (ATA)
  • source token account holder (pubKey)
  • destination token account (ATA)

My Solana program:

    invoke_signed(
        &spl_token::instruction::transfer(
            token_program.key,
            vault_ata.key,
            george_ata.key, 
            pda.key,
            &[], //no signer keys, because the signer is the PDA
            amount
        )?,
        &[vault_ata.clone(), george_ata.clone(), pda.clone()],
        &[
            &[b"myseeds", b"here"] //PDA seeds
        ]
    )?;
    msg!("Transfer succeeded!");

    Ok(())

Questions:

  1. WHERE shall I derive the PDA? In the same Solana program that performs the transfer OR in a separate program?
  2. Ultimately, the PDA must sign on the vault's behalf and transfer SPL-tokens. Should I transfer the ownership of the vault to the PDA? If so, how? OR should I rather transfer tokens from vault to PDA (and later from PDA to George's ATA)? If so, how?

Thanks a lot!

1 Answer 1

2

You should still include the signer keys argument as &[&pda.key], it doesn't matter that the signer in this case is a pda. Also, you probably should include the token_program in your accounts.

Lastly derive your seeds like this:

&[&[b"myseeds", b"here",&[bump]][..]]

You need to derive the bump somehow and pass it as one of the signer seeds. Usually it's stored in the pda itself, during its creation, for use later.

Your final code should look like this:

invoke_signed(
    &spl_token::instruction::transfer(
        token_program.key,
        vault_ata.key,
        george_ata.key, 
        pda.key,
        &[&pda.key]
        amount
    )?,
    &[
        vault_ata.clone(), 
        george_ata.clone(), 
        pda.clone(), 
        token_program.clone()
    ],
    &[&[b"myseeds", b"here",&[bump]][..]],   
)?;

msg!("Transfer succeeded!");

Ok(())

PS: If you're using Buffer.from("myseeds", "utf8") in your testing code then the on-chain seed should be specified as b"myseeds".as_ref(). I have no way to tell if the way you're currently doing it is purposeful or not.

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.