extern crate proc_macro; use proc_macro::TokenStream; use quote::ToTokens; use syn::parse_macro_input; /// Implements an [`Accounts`](./trait.Accounts.html) deserializer on the given /// struct. Can provide further functionality through the use of attributes. /// /// # Table of Contents /// - [Instruction Attribute](#instruction-attribute) /// - [Constraints](#constraints) /// /// # Instruction Attribute /// /// You can access the instruction's arguments with the /// `#[instruction(..)]` attribute. You have to list them /// in the same order as in the instruction but you can /// omit all arguments after the last one you need. /// /// # Example /// /// ```ignore /// ... /// pub fn initialize(ctx: Context, bump: u8, authority: Pubkey, data: u64) -> ProgramResult { /// ... /// Ok(()) /// } /// ... /// #[derive(Accounts)] /// #[instruction(bump: u8)] /// pub struct Initialize<'info> { /// ... /// } /// ``` /// /// # Constraints /// /// There are different types of constraints that can be applied with the `#[account(..)]` attribute. /// /// Attributes may reference other data structures. When `` is used in the tables below, an arbitrary expression /// may be passed in as long as it evaluates to a value of the expected type, e.g. `owner = token_program.key()`. If `target_account` /// used, the `target_account` must exist in the struct and the `.key()` is implicit, e.g. `payer = authority`. /// /// - [Normal Constraints](#normal-constraints) /// - [SPL Constraints](#spl-constraints) /// # Normal Constraints /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
AttributeDescription
/// #[account(signer)]

#[account(signer @ <custom_error>)] ///
/// Checks the given account signed the transaction.
/// Custom errors are supported via @.
/// Consider using the Signer type if you would only have this constraint on the account.

/// Example: ///

/// #[account(signer)]
/// pub authority: AccountInfo<'info>,
/// #[account(signer @ MyError::MyErrorCode)]
/// pub payer: AccountInfo<'info>
///                 
///
/// #[account(mut)]

#[account(mut @ <custom_error>)] ///
/// Checks the given account is mutable.
/// Makes anchor persist any state changes.
/// Custom errors are supported via @.

/// Example: ///

/// #[account(mut)]
/// pub data_account: Account<'info, MyData>,
/// #[account(mut @ MyError::MyErrorCode)]
/// pub data_account_two: Account<'info, MyData>
///                 
///
/// #[account(init, payer = <target_account>)]

/// #[account(init, payer = <target_account>, space = <num_bytes>)] ///
/// Creates the account via a CPI to the system program and /// initializes it (sets its account discriminator).
/// Marks the account as mutable and is mutually exclusive with mut.
/// Makes the account rent exempt unless skipped with `rent_exempt = skip`.
///
    ///
  • /// Requires the payer constraint to also be on the account. /// The payer account pays for the /// account creation. ///
  • ///
  • /// Requires the system program to exist on the struct /// and be called system_program. ///
  • ///
  • /// Requires that the space constraint is specified /// or, if creating an Account type, the T of Account /// to implement the rust std Default trait.
    /// When using the space constraint, one must remember to add 8 to it /// which is the size of the account discriminator.
    /// The given number is the size of the account in bytes, so accounts that hold /// a variable number of items such as a Vec should use the space /// constraint instead of using the Default trait and allocate sufficient space for all items that may /// be added to the data structure because account size is fixed. Check out the borsh library /// (which anchor uses under the hood for serialization) specification to learn how much /// space different data structures require. ///
  • ///
    /// Example: ///
    /// #[account]
    /// #[derive(Default)]
    /// pub struct MyData {
    ///     pub data: u64
    /// }
    
    /// #[account]
    /// pub struct OtherData {
    ///     pub data: u64
    /// }
    
    /// #[derive(Accounts)]
    /// pub struct Initialize<'info> {
    ///     #[account(init, payer = payer)]
    ///     pub data_account: Account<'info, MyData>,
    ///     #[account(init, payer = payer, space = 8 + 8)]
    ///     pub data_account_two: Account<'info, OtherData>,
    ///     #[account(mut)]
    ///     pub payer: Signer<'info>,
    ///     pub system_program: Program<'info, System>,
    /// }
    ///                 
    ///
/// init can be combined with other constraints (at the same time): ///
    ///
  • /// By default init sets the owner field of the created account to the /// currently executing program. Add the owner constraint to specify a /// different program owner. ///
  • ///
  • /// Use the seeds constraint together with bumpto create PDAs.
    /// init uses find_program_address to calculate the pda so the /// bump value can be left empty.
    /// However, if you want to use the bump in your instruction, /// you can pass it in as instruction data and set the bump value like shown in the example, /// using the instruction_data attribute. /// Anchor will then check that the bump returned by find_program_address equals /// the bump in the instruction data. ///
  • ///
/// Example: ///
/// #[derive(Accounts)]
/// #[instruction(bump: u8)]
/// pub struct Initialize<'info> {
///     #[account(
///         init, payer = payer,
///         seeds = [b"example_seed".as_ref()], bump = bump
///     )]
///     pub pda_data_account: Account<'info, MyData>,
///     #[account(
///         init, payer = payer,
///         space = 8 + 8, owner = other_program.key()
///     )]
///     pub account_for_other_program: AccountInfo<'info>,
///     #[account(
///         init,payer = payer, space = 8 + 8,
///         owner = other_program.key(),
///         seeds = [b"other_seed".as_ref()], bump
///     )]
///     pub pda_for_other_program: AccountInfo<'info>,
///     #[account(mut)]
///     pub payer: Signer<'info>,
///     pub system_program: Program<'info, System>,
///     pub other_program: Program<'info, OtherProgram>
/// }
///                 
///
/// #[account(init_if_needed, payer = <target_account>)]

/// #[account(init_if_needed, payer = <target_account>, space = <num_bytes>)] ///
/// Exact same functionality as the init constraint but only runs if the account does not exist yet.
/// If it does exist, it still checks whether the given init constraints are correct, /// e.g. that the account has the expected amount of space and, if it's a PDA, the correct seeds etc. ///

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

/// #[account]
/// pub struct OtherData {
///     pub data: u64
/// }

/// #[derive(Accounts)]
/// pub struct Initialize<'info> {
///     #[account(init_if_needed, payer = payer)]
///     pub data_account: Account<'info, MyData>,
///     #[account(init_if_needed, payer = payer, space = 8 + 8)]
///     pub data_account_two: Account<'info, OtherData>,
///     #[account(mut)]
///     pub payer: Signer<'info>,
///     pub system_program: Program<'info, System>
/// }
///                 
///
/// #[account(seeds = <seeds>, bump)]

/// #[account(seeds = <seeds>, bump = <expr>)] ///
/// Checks that given account is a PDA derived from the currently executing program, /// the seeds, and if provided, the bump. If not provided, anchor uses the canonical /// bump. Will be adjusted in the future to allow PDA to be derived from other programs.
/// This constraint behaves slightly differently when used with init. /// See its description. ///

/// Example: ///

/// #[account(seeds = [b"example_seed], bump)]
/// pub canonical_pda: AccountInfo<'info>,
/// #[account(seeds = [b"other_seed], bump = 142)]
/// pub arbitrary_pda: AccountInfo<'info>
///                 
///
/// #[account(has_one = <target_account>)]

/// #[account(has_one = <target_account> @ <custom_error>)] ///
/// Checks the target_account field on the account matches the /// key of the target_account field in the Accounts struct.
/// Custom errors are supported via @.

/// Example: ///

/// #[account(mut, has_one = authority)]
/// pub data: Account<'info, MyData>,
/// pub authority: Signer<'info>
///                 
/// In this example has_one checks that data.authority = authority.key() ///
/// #[account(address = <expr>)]

/// #[account(address = <expr> @ <custom_error>)] ///
/// Checks the account key matches the pubkey.
/// Custom errors are supported via @.

/// Example: ///

/// #[account(address = crate::ID)]
/// pub data: Account<'info, MyData>,
/// #[account(address = crate::ID @ MyError::MyErrorCode)]
/// pub data_two: Account<'info, MyData>
///                 
///
/// #[account(owner = <expr>)]

/// #[account(owner = <expr> @ <custom_error>)] ///
/// Checks the account owner matches expr.
/// Custom errors are supported via @.

/// Example: ///

/// #[account(owner = Token::ID @ MyError::MyErrorCode)]
/// pub data: Account<'info, MyData>,
/// #[account(owner = token_program.key())]
/// pub data_two: Account<'info, MyData>,
/// pub token_program: Program<'info, Token>
///                 
///
/// #[account(executable)] /// /// Checks the account is executable (i.e. the account is a program).
/// You may want to use the Program type instead.

/// Example: ///

/// #[account(executable)]
/// pub my_program: AccountInfo<'info>
///                 
///
/// #[account(rent_exempt = skip)]

/// #[account(rent_exempt = enforce)] ///
/// Enforces rent exemption with = enforce.
/// Skips rent exemption check that would normally be done /// through other constraints with = skip, /// e.g. when used with the zero constraint

/// Example: ///

/// #[account(zero, rent_exempt = skip)]
/// pub skipped_account: Account<'info, MyData>,
/// #[account(rent_exempt = enforce)]
/// pub enforced_account: AccountInfo<'info>
///                 
///
/// #[account(zero)] /// /// Checks the account discriminator is zero.
/// Enforces rent exemption unless skipped with rent_exempt = skip

/// Example: ///

/// #[account(zero)]
/// pub my_account: Account<'info, MyData>
///                 
///
/// #[account(close = <target_account>)] /// /// Marks the account as closed at the end of the instruction’s execution /// (sets its discriminator to the CLOSED_ACCOUNT_DISCRIMINATOR) /// and sends its lamports to the specified account.
/// Setting the discriminator to a special variant /// makes account revival attacks (where a subsequent instruction /// adds the rent exemption lamports again) impossible.
/// Requires mut to exist on the account. ///

/// Example: ///

/// #[account(mut, close = receiver)]
/// pub data_account: Account<'info, MyData>,
/// #[account(mut)]
/// pub receiver: SystemAccount<'info>
///                 
///
/// #[account(constraint = <expr>)]

#[account(constraint = <expr> @ <custom_error>)] ///
/// Constraint that checks whether the given expression evaluates to true.
/// Use this when no other constraint fits your use case. ///

/// Example: ///

/// #[account(constraint = one.keys[0].age == two.apple.age)]
/// pub one: Account<'info, MyData>,
/// pub two: Account<'info, OtherData>
///                 
///
/// /// # SPL Constraints /// /// Anchor provides constraints that make verifying SPL accounts easier. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
AttributeDescription
/// #[account(token::mint = <target_account>, token::authority = <target_account>)] /// /// Can currently only be used with init to create a token /// account with the given mint address and authority. ///

/// Example: ///
/// use anchor_spl::{mint, token::{TokenAccount, Mint, Token}};
/// ...

/// #[account(
///     init,
///     payer = payer,
///     token::mint = mint,
///     token::authority = payer,
/// )]
/// pub token: Account<'info, TokenAccount>,
/// #[account(address = mint::USDC)]
/// pub mint: Account<'info, Mint>,
/// #[account(mut)]
/// pub payer: Signer<'info>,
/// pub token_program: Program<'info, Token>,
/// pub system_program: Program<'info, System>
///                 
///
/// #[account(mint::authority = <target_account>, mint::decimals = <expr>)] ///

/// #[account(mint::authority = <target_account>, mint::decimals = <expr>, mint::freeze_authority = <target_account>)] ///
/// Can currently only be used with init to create a mint /// account with the given mint decimals and mint authority.
/// The freeze authority is optional. ///

/// Example: ///
/// use anchor_spl::token::{Mint, Token};
/// ...

/// #[account(
///     init,
///     payer = payer,
///     mint::decimals = 9,
///     mint::authority = payer,
/// )]
/// pub mint_one: Account<'info, Mint>,
/// #[account(
///     init,
///     payer = payer,
///     mint::decimals = 9,
///     mint::authority = payer,
///     mint::freeze_authority = payer
/// )]
/// pub mint_two: Account<'info, Mint>,
/// #[account(mut)]
/// pub payer: Signer<'info>,
/// pub token_program: Program<'info, Token>,
/// pub system_program: Program<'info, System>
///                 
///
/// #[account(associated_token::mint = <target_account>, associated_token::authority = <target_account>)] /// /// Can be used as a standalone as a check or with init to create an associated token /// account with the given mint address and authority. ///

/// Example: ///
/// use anchor_spl::{
///     associated_token::AssociatedToken,
///     mint,
///     token::{TokenAccount, Mint, Token}
/// };
/// ...

/// #[account(
///     init,
///     payer = payer,
///     associated_token::mint = mint,
///     associated_token::authority = payer,
/// )]
/// pub token: Account<'info, TokenAccount>,
/// #[account(
///     associated_token::mint = mint,
///     associated_token::authority = payer,
/// )]
/// pub second_token: Account<'info, TokenAccount>,
/// #[account(address = mint::USDC)]
/// pub mint: Account<'info, Mint>,
/// #[account(mut)]
/// pub payer: Signer<'info>,
/// pub token_program: Program<'info, Token>,
/// pub associated_token_program: Program<'info, AssociatedToken>,
/// pub system_program: Program<'info, System>
///                 
///
#[proc_macro_derive(Accounts, attributes(account, instruction))] pub fn derive_anchor_deserialize(item: TokenStream) -> TokenStream { parse_macro_input!(item as anchor_syn::AccountsStruct) .to_token_stream() .into() }