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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use crate::{error::TokenError, instruction::MAX_SIGNERS, option::COption};
use solana_sdk::{program_error::ProgramError, pubkey::Pubkey};
use std::mem::size_of;
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Mint {
pub mint_authority: COption<Pubkey>,
pub supply: u64,
pub decimals: u8,
pub is_initialized: bool,
pub freeze_authority: COption<Pubkey>,
}
impl IsInitialized for Mint {
fn is_initialized(&self) -> bool {
self.is_initialized
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Account {
pub mint: Pubkey,
pub owner: Pubkey,
pub amount: u64,
pub delegate: COption<Pubkey>,
pub state: AccountState,
pub is_native: COption<u64>,
pub delegated_amount: u64,
pub close_authority: COption<Pubkey>,
}
impl Account {
pub fn is_frozen(&self) -> bool {
self.state == AccountState::Frozen
}
pub fn is_native(&self) -> bool {
self.is_native.is_some()
}
}
impl IsInitialized for Account {
fn is_initialized(&self) -> bool {
self.state != AccountState::Uninitialized
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AccountState {
Uninitialized,
Initialized,
Frozen,
}
impl Default for AccountState {
fn default() -> Self {
AccountState::Uninitialized
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Multisig {
pub m: u8,
pub n: u8,
pub is_initialized: bool,
pub signers: [Pubkey; MAX_SIGNERS],
}
impl IsInitialized for Multisig {
fn is_initialized(&self) -> bool {
self.is_initialized
}
}
pub trait IsInitialized {
fn is_initialized(&self) -> bool;
}
pub fn unpack<T: IsInitialized>(input: &mut [u8]) -> Result<&mut T, ProgramError> {
let mut_ref: &mut T = unpack_unchecked(input)?;
if !mut_ref.is_initialized() {
return Err(TokenError::UninitializedState.into());
}
Ok(mut_ref)
}
pub fn unpack_unchecked<T: IsInitialized>(input: &mut [u8]) -> Result<&mut T, ProgramError> {
if input.len() != size_of::<T>() {
return Err(ProgramError::InvalidAccountData);
}
#[allow(clippy::cast_ptr_alignment)]
Ok(unsafe { &mut *(&mut input[0] as *mut u8 as *mut T) })
}