manifest/validation/
solana_checkers.rs

1use crate::require;
2use solana_program::{
3    account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, system_program,
4};
5use std::ops::Deref;
6
7#[derive(Clone)]
8pub struct Program<'a, 'info> {
9    pub info: &'a AccountInfo<'info>,
10}
11
12impl<'a, 'info> Program<'a, 'info> {
13    pub fn new(
14        info: &'a AccountInfo<'info>,
15        expected_program_id: &Pubkey,
16    ) -> Result<Program<'a, 'info>, ProgramError> {
17        require!(
18            info.key == expected_program_id,
19            ProgramError::IncorrectProgramId,
20            "Incorrect program id expected {:?} actual {:?}",
21            expected_program_id,
22            info.key
23        )?;
24        Ok(Self { info })
25    }
26}
27
28impl<'a, 'info> AsRef<AccountInfo<'info>> for Program<'a, 'info> {
29    fn as_ref(&self) -> &AccountInfo<'info> {
30        self.info
31    }
32}
33
34#[derive(Clone)]
35pub struct TokenProgram<'a, 'info> {
36    pub info: &'a AccountInfo<'info>,
37}
38
39impl<'a, 'info> TokenProgram<'a, 'info> {
40    pub fn new(info: &'a AccountInfo<'info>) -> Result<TokenProgram<'a, 'info>, ProgramError> {
41        require!(
42            *info.key == spl_token::id() || *info.key == spl_token_2022::id(),
43            ProgramError::IncorrectProgramId,
44            "Incorrect token program id: {:?}",
45            info.key
46        )?;
47        Ok(Self { info })
48    }
49}
50
51impl<'a, 'info> AsRef<AccountInfo<'info>> for TokenProgram<'a, 'info> {
52    fn as_ref(&self) -> &AccountInfo<'info> {
53        self.info
54    }
55}
56
57impl<'a, 'info> Deref for TokenProgram<'a, 'info> {
58    type Target = AccountInfo<'info>;
59
60    fn deref(&self) -> &Self::Target {
61        self.info
62    }
63}
64
65#[derive(Clone)]
66pub struct Signer<'a, 'info> {
67    pub info: &'a AccountInfo<'info>,
68}
69
70impl<'a, 'info> Signer<'a, 'info> {
71    pub fn new(info: &'a AccountInfo<'info>) -> Result<Signer<'a, 'info>, ProgramError> {
72        require!(
73            info.is_signer,
74            ProgramError::MissingRequiredSignature,
75            "Missing required signature for {:?}",
76            info.key
77        )?;
78        Ok(Self { info })
79    }
80
81    pub fn new_payer(info: &'a AccountInfo<'info>) -> Result<Signer<'a, 'info>, ProgramError> {
82        require!(
83            info.is_writable,
84            ProgramError::InvalidInstructionData,
85            "Payer is not writable. Key {:?}",
86            info.key
87        )?;
88        require!(
89            info.is_signer,
90            ProgramError::MissingRequiredSignature,
91            "Missing required signature for payer {:?}",
92            info.key
93        )?;
94        Ok(Self { info })
95    }
96}
97
98impl<'a, 'info> AsRef<AccountInfo<'info>> for Signer<'a, 'info> {
99    fn as_ref(&self) -> &AccountInfo<'info> {
100        self.info
101    }
102}
103
104impl<'a, 'info> Deref for Signer<'a, 'info> {
105    type Target = AccountInfo<'info>;
106
107    fn deref(&self) -> &Self::Target {
108        self.info
109    }
110}
111
112#[derive(Clone)]
113pub struct EmptyAccount<'a, 'info> {
114    pub info: &'a AccountInfo<'info>,
115}
116
117impl<'a, 'info> EmptyAccount<'a, 'info> {
118    pub fn new(info: &'a AccountInfo<'info>) -> Result<EmptyAccount<'a, 'info>, ProgramError> {
119        require!(
120            info.data_is_empty(),
121            ProgramError::InvalidAccountData,
122            "Account must be uninitialized {:?}",
123            info.key
124        )?;
125        require!(
126            info.owner == &system_program::id(),
127            ProgramError::IllegalOwner,
128            "Empty accounts must be owned by the system program {:?}",
129            info.key
130        )?;
131        Ok(Self { info })
132    }
133}
134
135impl<'a, 'info> AsRef<AccountInfo<'info>> for EmptyAccount<'a, 'info> {
136    fn as_ref(&self) -> &AccountInfo<'info> {
137        self.info
138    }
139}