123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- 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<Create>, bump: u8, authority: Pubkey, data: u64) -> anchor_lang::Result<()> {
- /// ...
- /// 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 `<expr>` 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
- /// <table>
- /// <thead>
- /// <tr>
- /// <th>Attribute</th>
- /// <th>Description</th>
- /// </tr>
- /// </thead>
- /// <tbody>
- /// <tr>
- /// <td>
- /// <code>#[account(signer)]</code> <br><br><code>#[account(signer @ <custom_error>)]</code>
- /// </td>
- /// <td>
- /// Checks the given account signed the transaction.<br>
- /// Custom errors are supported via <code>@</code>.<br>
- /// Consider using the <code>Signer</code> type if you would only have this constraint on the account.<br><br>
- /// Example:
- /// <pre><code>
- /// #[account(signer)]
- /// pub authority: AccountInfo<'info>,
- /// #[account(signer @ MyError::MyErrorCode)]
- /// pub payer: AccountInfo<'info>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(mut)]</code> <br><br><code>#[account(mut @ <custom_error>)]</code>
- /// </td>
- /// <td>
- /// Checks the given account is mutable.<br>
- /// Makes anchor persist any state changes.<br>
- /// Custom errors are supported via <code>@</code>.<br><br>
- /// Example:
- /// <pre><code>
- /// #[account(mut)]
- /// pub data_account: Account<'info, MyData>,
- /// #[account(mut @ MyError::MyErrorCode)]
- /// pub data_account_two: Account<'info, MyData>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(init, payer = <target_account>, space = <num_bytes>)]</code>
- /// </td>
- /// <td>
- /// Creates the account via a CPI to the system program and
- /// initializes it (sets its account discriminator).<br>
- /// Marks the account as mutable and is mutually exclusive with <code>mut</code>.<br>
- /// Makes the account rent exempt unless skipped with <code>rent_exempt = skip</code>.<br><br>
- /// Use <code>#[account(zero)]</code> for accounts larger than 10 Kibibyte.<br><br>
- /// <code>init</code> has to be used with additional constraints:
- /// <ul>
- /// <li>
- /// Requires the <code>payer</code> constraint to also be on the account.
- /// The <code>payer</code> account pays for the
- /// account creation.
- /// </li>
- /// <li>
- /// Requires the system program to exist on the struct
- /// and be called <code>system_program</code>.
- /// </li>
- /// <li>
- /// Requires that the <code>space</code> constraint is specified.
- /// When using the <code>space</code> constraint, one must remember to add 8 to it
- /// which is the size of the account discriminator. This only has to be done
- /// for accounts owned by anchor programs.<br>
- /// The given space number is the size of the account in bytes, so accounts that hold
- /// a variable number of items such as a <code>Vec</code> should allocate sufficient space for all items that may
- /// be added to the data structure because account size is fixed.
- /// Check out the <a href = "https://book.anchor-lang.com/anchor_references/space.html" target = "_blank" rel = "noopener noreferrer">space reference</a>
- /// and the <a href = "https://borsh.io/" target = "_blank" rel = "noopener noreferrer">borsh library</a>
- /// (which anchor uses under the hood for serialization) specification to learn how much
- /// space different data structures require.
- /// </li>
- /// <br>
- /// Example:
- /// <pre>
- /// #[account]
- /// pub struct MyData {
- /// pub data: u64
- /// }
- /// #[derive(Accounts)]
- /// pub struct Initialize<'info> {
- /// #[account(init, payer = payer, space = 8 + 8)]
- /// pub data_account_two: Account<'info, MyData>,
- /// #[account(mut)]
- /// pub payer: Signer<'info>,
- /// pub system_program: Program<'info, System>,
- /// }
- /// </pre>
- /// </ul>
- /// <code>init</code> can be combined with other constraints (at the same time):
- /// <ul>
- /// <li>
- /// By default <code>init</code> sets the owner field of the created account to the
- /// currently executing program. Add the <code>owner</code> constraint to specify a
- /// different program owner.
- /// </li>
- /// <li>
- /// Use the <code>seeds</code> constraint together with <code>bump</code>to create PDAs.<br>
- /// <code>init</code> uses <code>find_program_address</code> to calculate the pda so the
- /// bump value can be left empty.<br>
- /// 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 <code>instruction_data</code> attribute.
- /// Anchor will then check that the bump returned by <code>find_program_address</code> equals
- /// the bump in the instruction data.<br>
- /// <code>seeds::program</code> cannot be used together with init because the creation of an
- /// account requires its signature which for PDAs only the currently executing program can provide.
- /// </li>
- /// </ul>
- /// Example:
- /// <pre>
- /// #[derive(Accounts)]
- /// #[instruction(bump: u8)]
- /// pub struct Initialize<'info> {
- /// #[account(
- /// init, payer = payer, space = 8 + 8
- /// seeds = [b"example_seed"], 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"], 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>
- /// }
- /// </pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(init_if_needed, payer = <target_account>)]</code><br><br>
- /// <code>#[account(init_if_needed, payer = <target_account>, space = <num_bytes>)]</code>
- /// </td>
- /// <td>
- /// Exact same functionality as the <code>init</code> constraint but only runs if the account does not exist yet.<br>
- /// If the account 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.<br><br>
- /// This feature should be used with care and is therefore behind a feature flag.
- /// You can enable it by importing <code>anchor-lang</code> with the <code>init-if-needed</code> cargo feature.<br>
- /// When using <code>init_if_needed</code>, you need to make sure you properly protect yourself
- /// against re-initialization attacks. You need to include checks in your code that check
- /// that the initialized account cannot be reset to its initial settings after the first time it was
- /// initialized (unless that it what you want).<br>
- /// Because of the possibility of re-initialization attacks and the general guideline that instructions
- /// should avoid having multiple execution flows (which is important so they remain easy to understand),
- /// consider breaking up your instruction into two instructions - one for initializing and one for using
- /// the account - unless you have a good reason not to do so.
- /// <br><br>
- /// Example:
- /// <pre>
- /// #[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>
- /// }
- /// </pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(seeds = <seeds>, bump)]</code><br><br>
- /// <code>#[account(seeds = <seeds>, bump, seeds::program = <expr>)]<br><br>
- /// <code>#[account(seeds = <seeds>, bump = <expr>)]</code><br><br>
- /// <code>#[account(seeds = <seeds>, bump = <expr>, seeds::program = <expr>)]</code><br><br>
- /// </td>
- /// <td>
- /// 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. <br>
- /// Add <code>seeds::program = <expr></code> to derive the PDA from a different
- /// program than the currently executing one.<br>
- /// This constraint behaves slightly differently when used with <code>init</code>.
- /// See its description.
- /// <br><br>
- /// Example:
- /// <pre><code>
- /// #[derive(Accounts)]
- /// #[instruction(first_bump: u8, second_bump: u8)]
- /// pub struct Example {
- /// #[account(seeds = [b"example_seed"], bump)]
- /// pub canonical_pda: AccountInfo<'info>,
- /// #[account(
- /// seeds = [b"example_seed"],
- /// bump,
- /// seeds::program = other_program.key()
- /// )]
- /// pub canonical_pda_two: AccountInfo<'info>,
- /// #[account(seeds = [b"other_seed"], bump = first_bump)]
- /// pub arbitrary_pda: AccountInfo<'info>
- /// #[account(
- /// seeds = [b"other_seed"],
- /// bump = second_bump,
- /// seeds::program = other_program.key()
- /// )]
- /// pub arbitrary_pda_two: AccountInfo<'info>,
- /// pub other_program: Program<'info, OtherProgram>
- /// }
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(has_one = <target_account>)]</code><br><br>
- /// <code>#[account(has_one = <target_account> @ <custom_error>)]</code>
- /// </td>
- /// <td>
- /// Checks the <code>target_account</code> field on the account matches the
- /// key of the <code>target_account</code> field in the Accounts struct.<br>
- /// Custom errors are supported via <code>@</code>.<br><br>
- /// Example:
- /// <pre><code>
- /// #[account(mut, has_one = authority)]
- /// pub data: Account<'info, MyData>,
- /// pub authority: Signer<'info>
- /// </code></pre>
- /// In this example <code>has_one</code> checks that <code>data.authority = authority.key()</code>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(address = <expr>)]</code><br><br>
- /// <code>#[account(address = <expr> @ <custom_error>)]</code>
- /// </td>
- /// <td>
- /// Checks the account key matches the pubkey.<br>
- /// Custom errors are supported via <code>@</code>.<br><br>
- /// Example:
- /// <pre><code>
- /// #[account(address = crate::ID)]
- /// pub data: Account<'info, MyData>,
- /// #[account(address = crate::ID @ MyError::MyErrorCode)]
- /// pub data_two: Account<'info, MyData>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(owner = <expr>)]</code><br><br>
- /// <code>#[account(owner = <expr> @ <custom_error>)]</code>
- /// </td>
- /// <td>
- /// Checks the account owner matches <code>expr</code>.<br>
- /// Custom errors are supported via <code>@</code>.<br><br>
- /// Example:
- /// <pre><code>
- /// #[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>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(executable)]</code>
- /// </td>
- /// <td>
- /// Checks the account is executable (i.e. the account is a program).<br>
- /// You may want to use the <code>Program</code> type instead.<br><br>
- /// Example:
- /// <pre><code>
- /// #[account(executable)]
- /// pub my_program: AccountInfo<'info>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(rent_exempt = skip)]</code><br><br>
- /// <code>#[account(rent_exempt = enforce)]</code>
- /// </td>
- /// <td>
- /// Enforces rent exemption with <code>= enforce</code>.<br>
- /// Skips rent exemption check that would normally be done
- /// through other constraints with <code>= skip</code>,
- /// e.g. when used with the <code>zero</code> constraint<br><br>
- /// Example:
- /// <pre><code>
- /// #[account(zero, rent_exempt = skip)]
- /// pub skipped_account: Account<'info, MyData>,
- /// #[account(rent_exempt = enforce)]
- /// pub enforced_account: AccountInfo<'info>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(zero)]</code>
- /// </td>
- /// <td>
- /// Checks the account discriminator is zero.<br>
- /// Enforces rent exemption unless skipped with <code>rent_exempt = skip</code>.<br><br>
- /// Use this constraint if you want to create an account in a previous instruction
- /// and then initialize it in your instruction instead of using <code>init</code>.
- /// This is necessary for accounts that are larger than 10 Kibibyte because those
- /// accounts cannot be created via a CPI (which is what <code>init</code> would do).<br><br>
- /// Anchor adds internal data to the account when using <code>zero</code> just like it
- /// does with <code>init</code> which is why <code>zero</code> implies <code>mut</code>.
- /// <br><br>
- /// Example:
- /// <pre><code>
- /// #[account(zero)]
- /// pub my_account: Account<'info, MyData>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(close = <target_account>)]</code>
- /// </td>
- /// <td>
- /// Marks the account as closed at the end of the instruction’s execution
- /// (sets its discriminator to the <code>CLOSED_ACCOUNT_DISCRIMINATOR</code>)
- /// and sends its lamports to the specified account.<br>
- /// Setting the discriminator to a special variant
- /// makes account revival attacks (where a subsequent instruction
- /// adds the rent exemption lamports again) impossible.<br>
- /// Requires <code>mut</code> to exist on the account.
- /// <br><br>
- /// Example:
- /// <pre><code>
- /// #[account(mut, close = receiver)]
- /// pub data_account: Account<'info, MyData>,
- /// #[account(mut)]
- /// pub receiver: SystemAccount<'info>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(constraint = <expr>)]</code><br><br><code>#[account(constraint = <expr> @ <custom_error>)]</code>
- /// </td>
- /// <td>
- /// Constraint that checks whether the given expression evaluates to true.<br>
- /// Use this when no other constraint fits your use case.
- /// <br><br>
- /// Example:
- /// <pre><code>
- /// #[account(constraint = one.keys[0].age == two.apple.age)]
- /// pub one: Account<'info, MyData>,
- /// pub two: Account<'info, OtherData>
- /// </code></pre>
- /// </td>
- /// </tr>
- /// </tbody>
- /// </table>
- ///
- /// # SPL Constraints
- ///
- /// Anchor provides constraints that make verifying SPL accounts easier.
- ///
- /// <table>
- /// <thead>
- /// <tr>
- /// <th>Attribute</th>
- /// <th>Description</th>
- /// </tr>
- /// </thead>
- /// <tbody>
- /// <tr>
- /// <td>
- /// <code>#[account(token::mint = <target_account>, token::authority = <target_account>)]</code>
- /// </td>
- /// <td>
- /// Can be used as a check or with <code>init</code> to create a token
- /// account with the given mint address and authority.<br>
- /// When used as a check, it's possible to only specify a subset of the constraints.
- /// <br><br>
- /// Example:
- /// <pre>
- /// 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>
- /// </pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(mint::authority = <target_account>, mint::decimals = <expr>)]</code>
- /// <br><br>
- /// <code>#[account(mint::authority = <target_account>, mint::decimals = <expr>, mint::freeze_authority = <target_account>)]</code>
- /// </td>
- /// <td>
- /// Can be used as a check or with <code>init</code> to create a mint
- /// account with the given mint decimals and mint authority.<br>
- /// The freeze authority is optional when used with <code>init</code>.<br>
- /// When used as a check, it's possible to only specify a subset of the constraints.
- /// <br><br>
- /// Example:
- /// <pre>
- /// 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>
- /// </pre>
- /// </td>
- /// </tr>
- /// <tr>
- /// <td>
- /// <code>#[account(associated_token::mint = <target_account>, associated_token::authority = <target_account>)]</code>
- /// </td>
- /// <td>
- /// Can be used as a standalone as a check or with <code>init</code> to create an associated token
- /// account with the given mint address and authority.
- /// <br><br>
- /// Example:
- /// <pre>
- /// 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>
- /// </pre>
- /// </td>
- /// </tr>
- /// <tbody>
- /// </table>
- #[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()
- }
|