squads_multisig_program/instructions/
multisig_config.rs1use anchor_lang::prelude::*;
2
3use crate::errors::*;
4use crate::state::*;
5
6#[derive(AnchorSerialize, AnchorDeserialize)]
7pub struct MultisigAddMemberArgs {
8 pub new_member: Member,
9 pub memo: Option<String>,
11}
12
13#[derive(AnchorSerialize, AnchorDeserialize)]
14pub struct MultisigRemoveMemberArgs {
15 pub old_member: Pubkey,
16 pub memo: Option<String>,
18}
19
20#[derive(AnchorSerialize, AnchorDeserialize)]
21pub struct MultisigChangeThresholdArgs {
22 pub new_threshold: u16,
23 pub memo: Option<String>,
25}
26
27#[derive(AnchorSerialize, AnchorDeserialize)]
28pub struct MultisigSetTimeLockArgs {
29 pub time_lock: u32,
30 pub memo: Option<String>,
32}
33
34#[derive(AnchorSerialize, AnchorDeserialize)]
35pub struct MultisigSetConfigAuthorityArgs {
36 pub config_authority: Pubkey,
37 pub memo: Option<String>,
39}
40
41#[derive(AnchorSerialize, AnchorDeserialize)]
42pub struct MultisigSetRentCollectorArgs {
43 pub rent_collector: Option<Pubkey>,
44 pub memo: Option<String>,
46}
47
48#[derive(Accounts)]
49pub struct MultisigConfig<'info> {
50 #[account(
51 mut,
52 seeds = [SEED_PREFIX, SEED_MULTISIG, multisig.create_key.as_ref()],
53 bump = multisig.bump,
54 )]
55 multisig: Account<'info, Multisig>,
56
57 pub config_authority: Signer<'info>,
59
60 #[account(mut)]
64 pub rent_payer: Option<Signer<'info>>,
65
66 pub system_program: Option<Program<'info, System>>,
68}
69
70impl MultisigConfig<'_> {
71 fn validate(&self) -> Result<()> {
72 require_keys_eq!(
73 self.config_authority.key(),
74 self.multisig.config_authority,
75 MultisigError::Unauthorized
76 );
77
78 Ok(())
79 }
80
81 #[access_control(ctx.accounts.validate())]
86 pub fn multisig_add_member(ctx: Context<Self>, args: MultisigAddMemberArgs) -> Result<()> {
87 let MultisigAddMemberArgs { new_member, .. } = args;
88
89 let multisig = &mut ctx.accounts.multisig;
90
91 multisig.add_member(new_member);
92
93 Multisig::realloc_if_needed(
95 multisig.to_account_info(),
96 multisig.members.len(),
97 ctx.accounts
98 .rent_payer
99 .as_ref()
100 .map(ToAccountInfo::to_account_info),
101 ctx.accounts
102 .system_program
103 .as_ref()
104 .map(ToAccountInfo::to_account_info),
105 )?;
106
107 multisig.invalidate_prior_transactions();
108
109 multisig.invariant()?;
110
111 Ok(())
112 }
113
114 #[access_control(ctx.accounts.validate())]
119 pub fn multisig_remove_member(
120 ctx: Context<Self>,
121 args: MultisigRemoveMemberArgs,
122 ) -> Result<()> {
123 let multisig = &mut ctx.accounts.multisig;
124
125 require!(multisig.members.len() > 1, MultisigError::RemoveLastMember);
126
127 multisig.remove_member(args.old_member)?;
128
129 multisig.invalidate_prior_transactions();
130
131 multisig.invariant()?;
132
133 Ok(())
134 }
135
136 #[access_control(ctx.accounts.validate())]
139 pub fn multisig_change_threshold(
140 ctx: Context<Self>,
141 args: MultisigChangeThresholdArgs,
142 ) -> Result<()> {
143 let MultisigChangeThresholdArgs { new_threshold, .. } = args;
144
145 let multisig = &mut ctx.accounts.multisig;
146
147 multisig.threshold = new_threshold;
148
149 multisig.invalidate_prior_transactions();
150
151 multisig.invariant()?;
152
153 Ok(())
154 }
155
156 #[access_control(ctx.accounts.validate())]
161 pub fn multisig_set_time_lock(ctx: Context<Self>, args: MultisigSetTimeLockArgs) -> Result<()> {
162 let multisig = &mut ctx.accounts.multisig;
163
164 multisig.time_lock = args.time_lock;
165
166 multisig.invalidate_prior_transactions();
167
168 multisig.invariant()?;
169
170 Ok(())
171 }
172
173 #[access_control(ctx.accounts.validate())]
178 pub fn multisig_set_config_authority(
179 ctx: Context<Self>,
180 args: MultisigSetConfigAuthorityArgs,
181 ) -> Result<()> {
182 let multisig = &mut ctx.accounts.multisig;
183
184 multisig.config_authority = args.config_authority;
185
186 multisig.invalidate_prior_transactions();
187
188 multisig.invariant()?;
189
190 Ok(())
191 }
192
193 #[access_control(ctx.accounts.validate())]
198 pub fn multisig_set_rent_collector(
199 ctx: Context<Self>,
200 args: MultisigSetRentCollectorArgs,
201 ) -> Result<()> {
202 let multisig = &mut ctx.accounts.multisig;
203
204 multisig.rent_collector = args.rent_collector;
205
206 Multisig::realloc_if_needed(
208 multisig.to_account_info(),
209 multisig.members.len(),
210 ctx.accounts
211 .rent_payer
212 .as_ref()
213 .map(ToAccountInfo::to_account_info),
214 ctx.accounts
215 .system_program
216 .as_ref()
217 .map(ToAccountInfo::to_account_info),
218 )?;
219
220 multisig.invariant()?;
224
225 Ok(())
226 }
227}