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
pub mod bpf_writer;
pub mod errors;
pub mod metadata;
pub mod traits;
pub use {bpf_writer::*, errors::*, metadata::*, traits::*};
use {
anchor_lang::{prelude::*, solana_program},
errors::UtilErrors,
mpl_token_metadata::{self, state::Metadata},
};
pub fn reallocate<'info>(
len: isize,
account_info: AccountInfo<'info>,
payer_info: AccountInfo<'info>,
rent_sysvar: &Sysvar<'info, Rent>,
system_program: &Program<'info, System>,
) -> Result<()> {
let curr_len = isize::try_from(account_info.data_len()).unwrap();
let new_len = curr_len + len;
let curr_rent = rent_sysvar.minimum_balance(usize::try_from(curr_len).unwrap());
let new_rent = rent_sysvar.minimum_balance(usize::try_from(new_len).unwrap());
let rent_diff: isize = isize::try_from(new_rent).unwrap() - isize::try_from(curr_rent).unwrap();
let account_info_borrow = account_info.clone();
if rent_diff > 0 {
solana_program::program::invoke(
&solana_program::system_instruction::transfer(
payer_info.key,
account_info_borrow.key,
u64::try_from(rent_diff).unwrap(),
),
&[
payer_info,
account_info_borrow,
system_program.to_account_info(),
],
)?;
} else if rent_diff < 0 {
let parsed_rent_diff = u64::try_from(rent_diff * -1).unwrap();
**payer_info.lamports.borrow_mut() = payer_info
.lamports()
.checked_add(parsed_rent_diff)
.ok_or(UtilErrors::Overflow)?;
**account_info.lamports.borrow_mut() = account_info
.lamports()
.checked_sub(parsed_rent_diff)
.ok_or(UtilErrors::Overflow)?;
} else {
return Ok(());
}
account_info
.realloc(usize::try_from(new_len).unwrap(), false)
.map_err(Into::into)
}
pub enum ValidateCollectionCreatorOutput {
Collection { address: Pubkey },
Creator { address: Pubkey },
}
pub fn validate_collection_creator<'info>(
metadata: Metadata,
collections: &Vec<Pubkey>,
creators: &Vec<Pubkey>,
) -> Result<ValidateCollectionCreatorOutput> {
if collections.len() > 0 {
if let Some(collection) = metadata.collection {
if collection.verified && collections.contains(&collection.key) {
return Ok(ValidateCollectionCreatorOutput::Collection {
address: collection.key,
});
}
}
}
if creators.len() > 0 {
if let Some(metadata_creators) = metadata.data.creators {
let found = metadata_creators
.iter()
.position(|x| x.verified && creators.contains(&x.address));
if let Some(index) = found {
return Ok(ValidateCollectionCreatorOutput::Creator {
address: metadata_creators[index].address,
});
}
}
}
Err(UtilErrors::InvalidNFT.into())
}