light_merkle_tree_program/verifier_invoked_instructions/
spl_transfer.rs

1use anchor_lang::prelude::*;
2use anchor_spl::token::{Token, TokenAccount, Transfer};
3
4use crate::{utils::constants::TOKEN_AUTHORITY_SEED, RegisteredVerifier};
5#[derive(Accounts)]
6pub struct UnshieldSpl<'info> {
7    /// CHECK:` Signer is registered verifier program.
8    #[account(mut, seeds=[__program_id.to_bytes().as_ref()],bump,seeds::program=registered_verifier_pda.pubkey)]
9    pub authority: Signer<'info>,
10    /// CHECK:` That the merkle tree token belongs to a registered Merkle tree.
11    #[account(mut)]
12    pub merkle_tree_token: Account<'info, TokenAccount>,
13    /// CHECK:` That the merkle tree token belongs to a registered Merkle tree.
14    #[account(mut)]
15    pub recipient: Account<'info, TokenAccount>,
16    pub token_program: Program<'info, Token>,
17    /// CHECK:` that the token authority is derived in the correct way.
18    #[account(mut, seeds=[TOKEN_AUTHORITY_SEED], bump)]
19    pub token_authority: AccountInfo<'info>,
20    #[account(seeds=[&registered_verifier_pda.pubkey.to_bytes()],  bump)]
21    pub registered_verifier_pda: Account<'info, RegisteredVerifier>,
22}
23
24pub fn process_spl_transfer<'info>(
25    ctx: Context<'_, '_, '_, 'info, UnshieldSpl<'info>>,
26    amount: u64,
27) -> Result<()> {
28    let (_, bump) =
29        anchor_lang::prelude::Pubkey::find_program_address(&[TOKEN_AUTHORITY_SEED], ctx.program_id);
30    let bump = &[bump][..];
31    let seeds = &[&[TOKEN_AUTHORITY_SEED, bump][..]];
32    let accounts = Transfer {
33        from: ctx.accounts.merkle_tree_token.to_account_info(),
34        to: ctx.accounts.recipient.to_account_info(),
35        authority: ctx.accounts.token_authority.to_account_info(),
36    };
37    let cpi_ctx = CpiContext::new_with_signer(
38        ctx.accounts.token_program.to_account_info(),
39        accounts,
40        seeds,
41    );
42    anchor_spl::token::transfer(cpi_ctx, amount)
43}