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