squads_multisig_program/instructions/
multisig_create.rs1#![allow(deprecated)]
2use anchor_lang::prelude::*;
3use anchor_lang::system_program;
4use solana_program::native_token::LAMPORTS_PER_SOL;
5
6use crate::errors::MultisigError;
7use crate::state::*;
8
9#[derive(AnchorSerialize, AnchorDeserialize)]
10pub struct MultisigCreateArgs {
11 pub config_authority: Option<Pubkey>,
14 pub threshold: u16,
16 pub members: Vec<Member>,
18 pub time_lock: u32,
20 pub memo: Option<String>,
22}
23
24#[deprecated(
25 since = "0.4.0",
26 note = "This instruction is deprecated and will be removed soon. Please use `multisig_create_v2` to ensure future compatibility."
27)]
28#[derive(Accounts)]
29#[instruction(args: MultisigCreateArgs)]
30pub struct MultisigCreate<'info> {
31 #[account(
32 init,
33 payer = creator,
34 space = Multisig::size(args.members.len()),
35 seeds = [SEED_PREFIX, SEED_MULTISIG, create_key.key().as_ref()],
36 bump
37 )]
38 pub multisig: Account<'info, Multisig>,
39
40 pub create_key: Signer<'info>,
43
44 #[account(mut)]
46 pub creator: Signer<'info>,
47
48 pub system_program: Program<'info, System>,
49}
50
51#[allow(deprecated)]
52impl MultisigCreate<'_> {
53 fn validate(&self) -> Result<()> {
54 Ok(())
55 }
56
57 #[allow(deprecated)]
59 #[access_control(ctx.accounts.validate())]
60 pub fn multisig_create(ctx: Context<Self>, args: MultisigCreateArgs) -> Result<()> {
61 msg!("WARNING: This instruction is deprecated and will be removed soon. Please use `multisig_create_v2` to ensure future compatibility.");
62
63 let mut members = args.members;
65 members.sort_by_key(|m| m.key);
66
67 let multisig = &mut ctx.accounts.multisig;
69 multisig.config_authority = args.config_authority.unwrap_or_default();
70 multisig.threshold = args.threshold;
71 multisig.time_lock = args.time_lock;
72 multisig.transaction_index = 0;
73 multisig.stale_transaction_index = 0;
74 multisig.create_key = ctx.accounts.create_key.key();
75 multisig.bump = ctx.bumps.multisig;
76 multisig.members = members;
77 multisig.rent_collector = None;
78
79 multisig.invariant()?;
80
81 Ok(())
82 }
83}
84
85#[derive(AnchorSerialize, AnchorDeserialize)]
86pub struct MultisigCreateArgsV2 {
87 pub config_authority: Option<Pubkey>,
90 pub threshold: u16,
92 pub members: Vec<Member>,
94 pub time_lock: u32,
96 pub rent_collector: Option<Pubkey>,
99 pub memo: Option<String>,
101}
102
103#[derive(Accounts)]
104#[instruction(args: MultisigCreateArgsV2)]
105pub struct MultisigCreateV2<'info> {
106 #[account(seeds = [SEED_PREFIX, SEED_PROGRAM_CONFIG], bump)]
108 pub program_config: Account<'info, ProgramConfig>,
109
110 #[account(mut)]
113 pub treasury: AccountInfo<'info>,
114
115 #[account(
116 init,
117 payer = creator,
118 space = Multisig::size(args.members.len()),
119 seeds = [SEED_PREFIX, SEED_MULTISIG, create_key.key().as_ref()],
120 bump
121 )]
122 pub multisig: Account<'info, Multisig>,
123
124 pub create_key: Signer<'info>,
127
128 #[account(mut)]
130 pub creator: Signer<'info>,
131
132 pub system_program: Program<'info, System>,
133}
134
135impl MultisigCreateV2<'_> {
136 fn validate(&self) -> Result<()> {
137 require_keys_eq!(
139 self.treasury.key(),
140 self.program_config.treasury,
141 MultisigError::InvalidAccount
142 );
143 Ok(())
146 }
147
148 #[access_control(ctx.accounts.validate())]
150 pub fn multisig_create(ctx: Context<Self>, args: MultisigCreateArgsV2) -> Result<()> {
151 let mut members = args.members;
153 members.sort_by_key(|m| m.key);
154
155 let multisig = &mut ctx.accounts.multisig;
157 multisig.config_authority = args.config_authority.unwrap_or_default();
158 multisig.threshold = args.threshold;
159 multisig.time_lock = args.time_lock;
160 multisig.transaction_index = 0;
161 multisig.stale_transaction_index = 0;
162 multisig.create_key = ctx.accounts.create_key.key();
163 multisig.bump = ctx.bumps.multisig;
164 multisig.members = members;
165 multisig.rent_collector = args.rent_collector;
166
167 multisig.invariant()?;
168
169 let creation_fee = ctx.accounts.program_config.multisig_creation_fee;
170
171 if creation_fee > 0 {
172 system_program::transfer(
173 CpiContext::new(
174 ctx.accounts.system_program.to_account_info(),
175 system_program::Transfer {
176 from: ctx.accounts.creator.to_account_info(),
177 to: ctx.accounts.treasury.to_account_info(),
178 },
179 ),
180 creation_fee,
181 )?;
182 msg!("Creation fee: {}", creation_fee / LAMPORTS_PER_SOL);
183 }
184
185 Ok(())
186 }
187}