squads_multisig_program/instructions/
multisig_add_spending_limit.rs1use anchor_lang::prelude::*;
2
3use crate::errors::*;
4use crate::state::*;
5
6#[derive(AnchorSerialize, AnchorDeserialize)]
7pub struct MultisigAddSpendingLimitArgs {
8 pub create_key: Pubkey,
10 pub vault_index: u8,
12 pub mint: Pubkey,
14 pub amount: u64,
18 pub period: Period,
21 pub members: Vec<Pubkey>,
24 pub destinations: Vec<Pubkey>,
27 pub memo: Option<String>,
29}
30
31#[derive(Accounts)]
32#[instruction(args: MultisigAddSpendingLimitArgs)]
33pub struct MultisigAddSpendingLimit<'info> {
34 #[account(
35 seeds = [SEED_PREFIX, SEED_MULTISIG, multisig.create_key.as_ref()],
36 bump = multisig.bump,
37 )]
38 multisig: Account<'info, Multisig>,
39
40 pub config_authority: Signer<'info>,
42
43 #[account(
44 init,
45 seeds = [
46 SEED_PREFIX,
47 multisig.key().as_ref(),
48 SEED_SPENDING_LIMIT,
49 args.create_key.as_ref(),
50 ],
51 bump,
52 space = SpendingLimit::size(args.members.len(), args.destinations.len()),
53 payer = rent_payer
54 )]
55 pub spending_limit: Account<'info, SpendingLimit>,
56
57 #[account(mut)]
59 pub rent_payer: Signer<'info>,
60
61 pub system_program: Program<'info, System>,
62}
63
64impl MultisigAddSpendingLimit<'_> {
65 fn validate(&self) -> Result<()> {
66 require_keys_eq!(
68 self.config_authority.key(),
69 self.multisig.config_authority,
70 MultisigError::Unauthorized
71 );
72
73 Ok(())
76 }
77
78 #[access_control(ctx.accounts.validate())]
82 pub fn multisig_add_spending_limit(
83 ctx: Context<Self>,
84 args: MultisigAddSpendingLimitArgs,
85 ) -> Result<()> {
86 let spending_limit = &mut ctx.accounts.spending_limit;
87
88 let mut sorted_members = args.members;
90 sorted_members.sort();
91
92 spending_limit.multisig = ctx.accounts.multisig.key();
93 spending_limit.create_key = args.create_key;
94 spending_limit.vault_index = args.vault_index;
95 spending_limit.mint = args.mint;
96 spending_limit.amount = args.amount;
97 spending_limit.period = args.period;
98 spending_limit.remaining_amount = args.amount;
99 spending_limit.last_reset = Clock::get()?.unix_timestamp;
100 spending_limit.bump = ctx.bumps.spending_limit;
101 spending_limit.members = sorted_members;
102 spending_limit.destinations = args.destinations;
103
104 spending_limit.invariant()?;
105
106 Ok(())
107 }
108}