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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::{
error::ErrorCode,
state::{MarketState, MINIMUM_BALANCE_FOR_SYSTEM_ACCS},
utils::*,
ClaimResource,
};
use anchor_lang::{prelude::*, solana_program::program_pack::Pack, system_program::System};
use anchor_spl::token;
use mpl_token_metadata::state::TokenMetadataAccount;
impl<'info> ClaimResource<'info> {
pub fn process(&mut self, vault_owner_bump: u8) -> Result<()> {
let market = &self.market;
let selling_resource = &self.selling_resource;
let vault = &self.vault;
let metadata = &self.metadata;
let vault_owner = &self.owner;
let destination = &self.destination;
let clock = &self.clock;
let treasury_holder = &self.treasury_holder;
let token_program = &self.token_program;
if let Some(end_date) = market.end_date {
if clock.unix_timestamp as u64 <= end_date {
return Err(ErrorCode::MarketInInvalidState.into());
}
} else if market.state != MarketState::Ended {
return Err(ErrorCode::MarketInInvalidState.into());
}
let is_native = market.treasury_mint == System::id();
let treasury_holder_amount = if is_native {
treasury_holder
.lamports()
.checked_sub(MINIMUM_BALANCE_FOR_SYSTEM_ACCS)
.ok_or(ErrorCode::MathOverflow)?
} else {
let token_account = spl_token::state::Account::unpack(&treasury_holder.data.borrow())?;
if token_account.owner != market.treasury_owner {
return Err(ErrorCode::DerivedKeyInvalid.into());
}
token_account.amount
};
if treasury_holder_amount != 0 {
return Err(ErrorCode::TreasuryIsNotEmpty.into());
}
assert_derivation(
&mpl_token_metadata::id(),
metadata,
&[
mpl_token_metadata::state::PREFIX.as_bytes(),
mpl_token_metadata::id().as_ref(),
selling_resource.resource.as_ref(),
],
)?;
let signer_seeds: &[&[&[u8]]] = &[&[
VAULT_OWNER_PREFIX.as_bytes(),
selling_resource.resource.as_ref(),
selling_resource.store.as_ref(),
&[vault_owner_bump],
]];
let metadata_state: mpl_token_metadata::state::Metadata =
mpl_token_metadata::state::Metadata::from_account_info(metadata)?;
if !metadata_state.primary_sale_happened {
mpl_update_primary_sale_happened_via_token(
&metadata.to_account_info(),
&vault_owner.to_account_info(),
&vault.to_account_info(),
signer_seeds[0],
)?;
}
let cpi_program = token_program.to_account_info();
let cpi_accounts = token::Transfer {
from: vault.to_account_info(),
to: destination.to_account_info(),
authority: vault_owner.to_account_info(),
};
let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer_seeds);
token::transfer(cpi_ctx, 1)?;
Ok(())
}
}