Struct anchor_lang::accounts::account::Account

source ·
pub struct Account<'info, T: AccountSerialize + AccountDeserialize + Clone> { /* private fields */ }
Expand description

Wrapper around AccountInfo that verifies program ownership and deserializes underlying data into a Rust type.

§Table of Contents

§Basic Functionality

Account checks that Account.info.owner == T::owner(). This means that the data type that Accounts wraps around (=T) needs to implement the Owner trait. The #[account] attribute implements the Owner trait for a struct using the crate::ID declared by declare_id in the same program. It follows that Account can also be used with a T that comes from a different program.

Checks:

  • Account.info.owner == T::owner()
  • !(Account.info.owner == SystemProgram && Account.info.lamports() == 0)

§Example

use anchor_lang::prelude::*;
use other_program::Auth;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
mod hello_anchor {
    use super::*;
    pub fn set_data(ctx: Context<SetData>, data: u64) -> Result<()> {
        if (*ctx.accounts.auth_account).authorized {
            (*ctx.accounts.my_account).data = data;
        }
        Ok(())
    }
}

#[account]
#[derive(Default)]
pub struct MyData {
    pub data: u64
}

#[derive(Accounts)]
pub struct SetData<'info> {
    #[account(mut)]
    pub my_account: Account<'info, MyData> // checks that my_account.info.owner == Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS
    pub auth_account: Account<'info, Auth> // checks that auth_account.info.owner == FEZGUxNhZWpYPj9MJCrZJvUo1iF9ys34UHx52y4SzVW9
}

// In a different program

...
declare_id!("FEZGUxNhZWpYPj9MJCrZJvUo1iF9ys34UHx52y4SzVW9");
#[account]
#[derive(Default)]
pub struct Auth {
    pub authorized: bool
}
...

§Using Account with non-anchor programs

Account can also be used with non-anchor programs. The data types from those programs are not annotated with #[account] so you have to

  • create a wrapper type around the structs you want to wrap with Account
  • implement the functions required by Account yourself instead of using #[account]. You only have to implement a fraction of the functions #[account] generates. See the example below for the code you have to write.

The mint wrapper type that Anchor provides out of the box for the token program (source)

#[derive(Clone)]
pub struct Mint(spl_token::state::Mint);

// This is necessary so we can use "anchor_spl::token::Mint::LEN"
// because rust does not resolve "anchor_spl::token::Mint::LEN" to
// "spl_token::state::Mint::LEN" automatically
impl Mint {
    pub const LEN: usize = spl_token::state::Mint::LEN;
}

// You don't have to implement the "try_deserialize" function
// from this trait. It delegates to
// "try_deserialize_unchecked" by default which is what we want here
// because non-anchor accounts don't have a discriminator to check
impl anchor_lang::AccountDeserialize for Mint {
    fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result<Self> {
        spl_token::state::Mint::unpack(buf).map(Mint)
    }
}
// AccountSerialize defaults to a no-op which is what we want here
// because it's a foreign program, so our program does not
// have permission to write to the foreign program's accounts anyway
impl anchor_lang::AccountSerialize for Mint {}

impl anchor_lang::Owner for Mint {
    fn owner() -> Pubkey {
        // pub use spl_token::ID is used at the top of the file
        ID
    }
}

// Implement the "std::ops::Deref" trait for better user experience
impl Deref for Mint {
    type Target = spl_token::state::Mint;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

§Out of the box wrapper types

§Accessing BPFUpgradeableLoader Data

Anchor provides wrapper types to access data stored in programs owned by the BPFUpgradeableLoader such as the upgrade authority. If you’re interested in the data of a program account, you can use

Account<'info, BpfUpgradeableLoaderState>

and then match on its contents inside your instruction function.

Alternatively, you can use

Account<'info, ProgramData>

to let anchor do the matching for you and return the ProgramData variant of BpfUpgradeableLoaderState.

§Example

use anchor_lang::prelude::*;
use crate::program::MyProgram;

declare_id!("Cum9tTyj5HwcEiAmhgaS7Bbj4UczCwsucrCkxRECzM4e");

#[program]
pub mod my_program {
    use super::*;

    pub fn set_initial_admin(
        ctx: Context<SetInitialAdmin>,
        admin_key: Pubkey
    ) -> Result<()> {
        ctx.accounts.admin_settings.admin_key = admin_key;
        Ok(())
    }

    pub fn set_admin(...){...}

    pub fn set_settings(...){...}
}

#[account]
#[derive(Default, Debug)]
pub struct AdminSettings {
    admin_key: Pubkey
}

#[derive(Accounts)]
pub struct SetInitialAdmin<'info> {
    #[account(init, payer = authority, seeds = [b"admin"], bump)]
    pub admin_settings: Account<'info, AdminSettings>,
    #[account(mut)]
    pub authority: Signer<'info>,
    #[account(constraint = program.programdata_address()? == Some(program_data.key()))]
    pub program: Program<'info, MyProgram>,
    #[account(constraint = program_data.upgrade_authority_address == Some(authority.key()))]
    pub program_data: Account<'info, ProgramData>,
    pub system_program: Program<'info, System>,
}

This example solves a problem you may face if your program has admin settings: How do you set the admin key for restricted functionality after deployment? Setting the admin key itself should be a restricted action but how do you restrict it without having set an admin key? You’re stuck in a loop. One solution is to use the upgrade authority of the program as the initial (or permanent) admin key.

§SPL Types

Anchor provides wrapper types to access accounts owned by the token program. Use

use anchor_spl::token::TokenAccount;

#[derive(Accounts)]
pub struct Example {
    pub my_acc: Account<'info, TokenAccount>
}

to access token accounts and

use anchor_spl::token::Mint;

#[derive(Accounts)]
pub struct Example {
    pub my_acc: Account<'info, Mint>
}

to access mint accounts.

Implementations§

source§

impl<'a, T: AccountSerialize + AccountDeserialize + Clone> Account<'a, T>

source

pub fn reload(&mut self) -> Result<()>

Reloads the account from storage. This is useful, for example, when observing side effects after CPI.

source

pub fn into_inner(self) -> T

source

pub fn set_inner(&mut self, inner: T)

Sets the inner account.

Instead of this:

pub fn new_user(ctx: Context<CreateUser>, new_user:User) -> Result<()> {
    (*ctx.accounts.user_to_create).name = new_user.name;
    (*ctx.accounts.user_to_create).age = new_user.age;
    (*ctx.accounts.user_to_create).address = new_user.address;
}

You can do this:

pub fn new_user(ctx: Context<CreateUser>, new_user:User) -> Result<()> {
    ctx.accounts.user_to_create.set_inner(new_user);
}
source§

impl<'a, T: AccountSerialize + AccountDeserialize + Owner + Clone> Account<'a, T>

source

pub fn try_from(info: &'a AccountInfo<'a>) -> Result<Account<'a, T>>

Deserializes the given info into a Account.

source

pub fn try_from_unchecked(info: &'a AccountInfo<'a>) -> Result<Account<'a, T>>

Deserializes the given info into a Account without checking the account discriminator. Be careful when using this and avoid it if possible.

Trait Implementations§

source§

impl<'info, B, T> Accounts<'info, B> for Account<'info, T>

source§

fn try_accounts( _program_id: &Pubkey, accounts: &mut &'info [AccountInfo<'info>], _ix_data: &[u8], _bumps: &mut B, _reallocs: &mut BTreeSet<Pubkey> ) -> Result<Self>

Returns the validated accounts struct. What constitutes “valid” is program dependent. However, users of these types should never have to worry about account substitution attacks. For example, if a program expects a Mint account from the SPL token program in a particular field, then it should be impossible for this method to return Ok if any other account type is given–from the SPL token program or elsewhere. Read more
source§

impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AccountsClose<'info> for Account<'info, T>

source§

fn close(&self, sol_destination: AccountInfo<'info>) -> Result<()>

source§

impl<'info, T: AccountSerialize + AccountDeserialize + Owner + Clone> AccountsExit<'info> for Account<'info, T>

source§

fn exit(&self, program_id: &Pubkey) -> Result<()>

program_id is the currently executing program.
source§

impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AsRef<AccountInfo<'info>> for Account<'info, T>

source§

fn as_ref(&self) -> &AccountInfo<'info>

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AsRef<T> for Account<'info, T>

source§

fn as_ref(&self) -> &T

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<'info, T: Clone + AccountSerialize + AccountDeserialize + Clone> Clone for Account<'info, T>

source§

fn clone(&self) -> Account<'info, T>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<'info, T: AccountSerialize + AccountDeserialize + Clone + Debug> Debug for Account<'info, T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'a, T: AccountSerialize + AccountDeserialize + Clone> Deref for Account<'a, T>

§

type Target = T

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<'a, T: AccountSerialize + AccountDeserialize + Clone> DerefMut for Account<'a, T>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<'info, T: AccountSerialize + AccountDeserialize + Clone> Key for Account<'info, T>

source§

fn key(&self) -> Pubkey

source§

impl<'info, T: AccountSerialize + AccountDeserialize + Clone> ToAccountInfos<'info> for Account<'info, T>

source§

impl<'info, T: AccountSerialize + AccountDeserialize + Clone> ToAccountMetas for Account<'info, T>

source§

fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta>

is_signer is given as an optional override for the signer meta field. This covers the edge case when a program-derived-address needs to relay a transaction from a client to another program but sign the transaction before the relay. The client cannot mark the field as a signer, and so we have to override the is_signer meta field given by the client.

Auto Trait Implementations§

§

impl<'info, T> Freeze for Account<'info, T>
where T: Freeze,

§

impl<'info, T> !RefUnwindSafe for Account<'info, T>

§

impl<'info, T> !Send for Account<'info, T>

§

impl<'info, T> !Sync for Account<'info, T>

§

impl<'info, T> Unpin for Account<'info, T>
where T: Unpin,

§

impl<'info, T> !UnwindSafe for Account<'info, T>

Blanket Implementations§

source§

impl<T> AbiExample for T

source§

default fn example() -> T

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<'info, T> Lamports<'info> for T
where T: AsRef<AccountInfo<'info>>,

source§

fn get_lamports(&self) -> u64

Get the lamports of the account.
source§

fn add_lamports(&self, amount: u64) -> Result<&Self>

Add lamports to the account. Read more
source§

fn sub_lamports(&self, amount: u64) -> Result<&Self>

Subtract lamports from the account. Read more
source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<'info, T> ToAccountInfo<'info> for T
where T: AsRef<AccountInfo<'info>>,

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V