squads_multisig_program/instructions/
batch_create.rs

1use anchor_lang::prelude::*;
2
3use crate::errors::*;
4use crate::state::*;
5
6#[derive(AnchorSerialize, AnchorDeserialize)]
7pub struct BatchCreateArgs {
8    /// Index of the vault this transaction belongs to.
9    pub vault_index: u8,
10    pub memo: Option<String>,
11}
12
13#[derive(Accounts)]
14pub struct BatchCreate<'info> {
15    #[account(
16        mut,
17        seeds = [SEED_PREFIX, SEED_MULTISIG, multisig.create_key.as_ref()],
18        bump = multisig.bump,
19    )]
20    pub multisig: Account<'info, Multisig>,
21
22    #[account(
23        init,
24        payer = rent_payer,
25        space = 8 + Batch::INIT_SPACE,
26        seeds = [
27            SEED_PREFIX,
28            multisig.key().as_ref(),
29            SEED_TRANSACTION,
30            &multisig.transaction_index.checked_add(1).unwrap().to_le_bytes(),
31        ],
32        bump
33    )]
34    pub batch: Account<'info, Batch>,
35
36    /// The member of the multisig that is creating the batch.
37    pub creator: Signer<'info>,
38
39    /// The payer for the batch account rent.
40    #[account(mut)]
41    pub rent_payer: Signer<'info>,
42
43    pub system_program: Program<'info, System>,
44}
45
46impl BatchCreate<'_> {
47    fn validate(&self) -> Result<()> {
48        let Self {
49            multisig, creator, ..
50        } = self;
51
52        // creator
53        require!(
54            multisig.is_member(creator.key()).is_some(),
55            MultisigError::NotAMember
56        );
57        require!(
58            multisig.member_has_permission(creator.key(), Permission::Initiate),
59            MultisigError::Unauthorized
60        );
61
62        Ok(())
63    }
64
65    /// Create a new batch.
66    #[access_control(ctx.accounts.validate())]
67    pub fn batch_create(ctx: Context<Self>, args: BatchCreateArgs) -> Result<()> {
68        let multisig = &mut ctx.accounts.multisig;
69        let creator = &mut ctx.accounts.creator;
70        let batch = &mut ctx.accounts.batch;
71
72        let multisig_key = multisig.key();
73
74        // Increment the transaction index.
75        let index = multisig.transaction_index.checked_add(1).expect("overflow");
76
77        let vault_seeds = &[
78            SEED_PREFIX,
79            multisig_key.as_ref(),
80            SEED_VAULT,
81            &args.vault_index.to_le_bytes(),
82        ];
83        let (_, vault_bump) = Pubkey::find_program_address(vault_seeds, ctx.program_id);
84
85        batch.multisig = multisig_key;
86        batch.creator = creator.key();
87        batch.index = index;
88        batch.bump = ctx.bumps.batch;
89        batch.vault_index = args.vault_index;
90        batch.vault_bump = vault_bump;
91        batch.size = 0;
92        batch.executed_transaction_index = 0;
93
94        batch.invariant()?;
95
96        // Updated last transaction index in the multisig account.
97        multisig.transaction_index = index;
98
99        multisig.invariant()?;
100
101        // Logs for indexing.
102        msg!("batch index: {}", index);
103
104        Ok(())
105    }
106}