anchor_lang/accounts/
system_account.rs

1//! Type validating that the account is owned by the system program
2
3use crate::error::ErrorCode;
4use crate::*;
5use solana_program::system_program;
6use std::ops::Deref;
7
8/// Type validating that the account is owned by the system program
9///
10/// Checks:
11///
12/// - `SystemAccount.info.owner == SystemProgram`
13#[derive(Debug, Clone)]
14pub struct SystemAccount<'info> {
15    info: &'info AccountInfo<'info>,
16}
17
18impl<'info> SystemAccount<'info> {
19    fn new(info: &'info AccountInfo<'info>) -> SystemAccount<'info> {
20        Self { info }
21    }
22
23    #[inline(never)]
24    pub fn try_from(info: &'info AccountInfo<'info>) -> Result<SystemAccount<'info>> {
25        if *info.owner != system_program::ID {
26            return Err(ErrorCode::AccountNotSystemOwned.into());
27        }
28        Ok(SystemAccount::new(info))
29    }
30}
31
32impl<'info, B> Accounts<'info, B> for SystemAccount<'info> {
33    #[inline(never)]
34    fn try_accounts(
35        _program_id: &Pubkey,
36        accounts: &mut &'info [AccountInfo<'info>],
37        _ix_data: &[u8],
38        _bumps: &mut B,
39        _reallocs: &mut BTreeSet<Pubkey>,
40    ) -> Result<Self> {
41        if accounts.is_empty() {
42            return Err(ErrorCode::AccountNotEnoughKeys.into());
43        }
44        let account = &accounts[0];
45        *accounts = &accounts[1..];
46        SystemAccount::try_from(account)
47    }
48}
49
50impl<'info> AccountsExit<'info> for SystemAccount<'info> {}
51
52impl ToAccountMetas for SystemAccount<'_> {
53    fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
54        let is_signer = is_signer.unwrap_or(self.info.is_signer);
55        let meta = match self.info.is_writable {
56            false => AccountMeta::new_readonly(*self.info.key, is_signer),
57            true => AccountMeta::new(*self.info.key, is_signer),
58        };
59        vec![meta]
60    }
61}
62
63impl<'info> ToAccountInfos<'info> for SystemAccount<'info> {
64    fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
65        vec![self.info.clone()]
66    }
67}
68
69impl<'info> AsRef<AccountInfo<'info>> for SystemAccount<'info> {
70    fn as_ref(&self) -> &AccountInfo<'info> {
71        self.info
72    }
73}
74
75impl<'info> Deref for SystemAccount<'info> {
76    type Target = AccountInfo<'info>;
77
78    fn deref(&self) -> &Self::Target {
79        self.info
80    }
81}
82
83impl Key for SystemAccount<'_> {
84    fn key(&self) -> Pubkey {
85        *self.info.key
86    }
87}