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
use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey};
use crate::{
assertions::assert_derivation,
error::MetadataError,
pda,
state::{UseAuthorityRecord, UseMethod, Uses, PREFIX, USER},
};
pub fn assert_valid_use(
incoming_use: &Option<Uses>,
current_use: &Option<Uses>,
) -> Result<(), ProgramError> {
if let Some(i) = incoming_use {
if i.use_method == UseMethod::Single && (i.total != 1 || i.remaining != 1) {
return Err(MetadataError::InvalidUseMethod.into());
}
if i.use_method == UseMethod::Multiple && (i.total < 2 || i.total < i.remaining) {
return Err(MetadataError::InvalidUseMethod.into());
}
}
match (incoming_use, current_use) {
(Some(incoming), Some(current)) => {
if incoming.use_method != current.use_method && current.total != current.remaining {
return Err(MetadataError::CannotChangeUseMethodAfterFirstUse.into());
}
if incoming.total != current.total && current.total != current.remaining {
return Err(MetadataError::CannotChangeUsesAfterFirstUse.into());
}
if incoming.remaining != current.remaining && current.total != current.remaining {
return Err(MetadataError::CannotChangeUsesAfterFirstUse.into());
}
Ok(())
}
_ => Ok(()),
}
}
pub fn assert_burner(program_as_burner: &Pubkey) -> Result<u8, MetadataError> {
let (canon_burn, b) = pda::find_program_as_burner_account();
if &canon_burn != program_as_burner {
return Err(MetadataError::DerivedKeyInvalid);
}
Ok(b)
}
pub fn assert_valid_bump(
canonical_bump: u8,
use_authority_record: &UseAuthorityRecord,
) -> Result<(), ProgramError> {
if canonical_bump != use_authority_record.bump {
return Err(MetadataError::InvalidUseAuthorityRecord.into());
}
Ok(())
}
pub fn assert_use_authority_derivation(
program_id: &Pubkey,
use_authority_record_info: &AccountInfo,
user_info: &AccountInfo,
mint_info: &AccountInfo,
) -> Result<u8, ProgramError> {
let use_authority_seeds = [
PREFIX.as_bytes(),
program_id.as_ref(),
mint_info.key.as_ref(),
USER.as_bytes(),
user_info.key.as_ref(),
];
assert_derivation(program_id, use_authority_record_info, &use_authority_seeds)
}
pub fn process_use_authority_validation(
data_len: usize,
must_be_empty: bool,
) -> Result<(), ProgramError> {
let record_info_empty = data_len == 0;
if must_be_empty {
if !record_info_empty {
return Err(MetadataError::UseAuthorityRecordAlreadyExists.into());
}
} else if record_info_empty {
return Err(MetadataError::UseAuthorityRecordAlreadyRevoked.into());
}
Ok(())
}