squads_multisig_program/instructions/
vault_transaction_create_from_buffer.rs1use crate::errors::*;
2use crate::instructions::*;
3use crate::state::*;
4use anchor_lang::{prelude::*, system_program};
5
6#[derive(Accounts)]
7pub struct VaultTransactionCreateFromBuffer<'info> {
8 pub vault_transaction_create: VaultTransactionCreate<'info>,
10
11 #[account(
12 mut,
13 close = creator,
14 constraint = transaction_buffer.creator == creator.key() @ MultisigError::Unauthorized,
17 seeds = [
18 SEED_PREFIX,
19 vault_transaction_create.multisig.key().as_ref(),
20 SEED_TRANSACTION_BUFFER,
21 creator.key().as_ref(),
22 &transaction_buffer.buffer_index.to_le_bytes(),
23 ],
24 bump
25 )]
26 pub transaction_buffer: Box<Account<'info, TransactionBuffer>>,
27
28 #[account(
31 mut,
32 address = vault_transaction_create.creator.key(),
33 )]
34 pub creator: Signer<'info>,
35}
36
37impl<'info> VaultTransactionCreateFromBuffer<'info> {
38 pub fn validate(&self, args: &VaultTransactionCreateArgs) -> Result<()> {
39 let transaction_buffer_account = &self.transaction_buffer;
40
41 require!(
43 args.transaction_message == vec![0, 0, 0, 0, 0, 0],
44 MultisigError::InvalidInstructionArgs
45 );
46
47 transaction_buffer_account.validate_hash()?;
49
50 transaction_buffer_account.validate_size()?;
52 Ok(())
53 }
54 #[access_control(ctx.accounts.validate(&args))]
56 pub fn vault_transaction_create_from_buffer(
57 ctx: Context<'_, '_, 'info, 'info, Self>,
58 args: VaultTransactionCreateArgs,
59 ) -> Result<()> {
60 let vault_transaction_account_info = &ctx
62 .accounts
63 .vault_transaction_create
64 .transaction
65 .to_account_info();
66 let rent_payer_account_info = &ctx
67 .accounts
68 .vault_transaction_create
69 .rent_payer
70 .to_account_info();
71
72 let system_program = &ctx.accounts.vault_transaction_create.system_program.to_account_info();
73
74 let transaction_buffer = &ctx.accounts.transaction_buffer;
76
77 let new_len =
80 VaultTransaction::size(args.ephemeral_signers, transaction_buffer.buffer.as_slice())?;
81
82 let rent_exempt_lamports = Rent::get().unwrap().minimum_balance(new_len).max(1);
84
85 let top_up_lamports =
87 rent_exempt_lamports.saturating_sub(vault_transaction_account_info.lamports());
88
89 let transfer_context = CpiContext::new(
91 system_program.to_account_info(),
92 system_program::Transfer {
93 from: rent_payer_account_info.clone(),
94 to: vault_transaction_account_info.clone(),
95 },
96 );
97 system_program::transfer(transfer_context, top_up_lamports)?;
98
99 AccountInfo::realloc(&vault_transaction_account_info, new_len, true)?;
102
103 let create_args = VaultTransactionCreateArgs {
105 vault_index: args.vault_index,
106 ephemeral_signers: args.ephemeral_signers,
107 transaction_message: transaction_buffer.buffer.clone(),
108 memo: args.memo,
109 };
110 let context = Context::new(
112 ctx.program_id,
113 &mut ctx.accounts.vault_transaction_create,
114 ctx.remaining_accounts,
115 ctx.bumps.vault_transaction_create,
116 );
117
118 VaultTransactionCreate::vault_transaction_create(context, create_args)?;
120
121 Ok(())
122 }
123}