1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use anchor_lang::{prelude::*, AccountsClose};
use crate::{
cmp_pubkeys,
constants::{FREEZE_FEATURE_INDEX, FREEZE_LOCK_FEATURE_INDEX},
is_feature_active, CandyError, CandyMachine, CollectionPDA,
};
#[derive(Accounts)]
pub struct WithdrawFunds<'info> {
#[account(mut, close = authority, has_one = authority)]
candy_machine: Account<'info, CandyMachine>,
#[account(mut, address = candy_machine.authority)]
authority: Signer<'info>,
}
pub fn handle_withdraw_funds<'info>(
ctx: Context<'_, '_, '_, 'info, WithdrawFunds<'info>>,
) -> Result<()> {
let authority = &ctx.accounts.authority;
let candy_machine = &ctx.accounts.candy_machine;
if is_feature_active(&candy_machine.data.uuid, FREEZE_FEATURE_INDEX) {
return err!(CandyError::NoWithdrawWithFreeze);
}
if is_feature_active(&candy_machine.data.uuid, FREEZE_LOCK_FEATURE_INDEX) {
return err!(CandyError::NoWithdrawWithFrozenFunds);
}
if !ctx.remaining_accounts.is_empty() {
let candy_key = candy_machine.key();
let seeds = [CollectionPDA::PREFIX.as_bytes(), candy_key.as_ref()];
let collection_pda = &ctx.remaining_accounts[0];
if !cmp_pubkeys(
&collection_pda.key(),
&Pubkey::find_program_address(&seeds, &crate::id()).0,
) {
return err!(CandyError::MismatchedCollectionPDA);
}
let collection_pda: Account<CollectionPDA> =
Account::try_from(&collection_pda.to_account_info())?;
collection_pda.close(authority.to_account_info())?;
}
Ok(())
}