hydra/processors/stake/
set_for.rs1use crate::error::{HydraError, OrArithError};
2use crate::state::{Fanout, FanoutMembershipVoucher, FANOUT_MEMBERSHIP_VOUCHER_SIZE};
3
4use crate::utils::validation::*;
5use crate::MembershipModel;
6use anchor_lang::prelude::*;
7use anchor_spl::token::{Mint, Token, TokenAccount};
8#[derive(Accounts)]
9#[instruction(shares: u64)]
10pub struct SetForTokenMemberStake<'info> {
11 #[account(mut)]
12 pub authority: Signer<'info>,
13 pub member: UncheckedAccount<'info>,
15 #[account(
16 mut,
17 seeds = [b"fanout-config", fanout.name.as_bytes()],
18 bump = fanout.bump_seed,
19 )]
20 pub fanout: Account<'info, Fanout>,
21 #[account(
22 init,
23 space = FANOUT_MEMBERSHIP_VOUCHER_SIZE,
24 seeds = [b"fanout-membership", fanout.key().as_ref(), member.key().as_ref()],
25 bump,
26 payer = authority
27 )]
28 pub membership_voucher: Account<'info, FanoutMembershipVoucher>,
29 #[account(
30 mut,
31 constraint = fanout.membership_mint.is_some() && membership_mint.key() == fanout.membership_mint.unwrap(),
32 )]
33 pub membership_mint: Account<'info, Mint>,
34 #[account(
35 mut,
36 constraint = membership_mint_token_account.mint == membership_mint.key(),
37 constraint = membership_mint_token_account.delegate.is_none(),
38 constraint = membership_mint_token_account.close_authority.is_none(),
39 constraint = membership_mint_token_account.amount >= shares,
40 constraint = membership_mint_token_account.owner == authority.key()
41 )]
42 pub membership_mint_token_account: Account<'info, TokenAccount>,
43 #[account(
44 mut,
45 constraint = member_stake_account.owner == membership_voucher.key(),
46 constraint = member_stake_account.mint == membership_mint.key(),
47 )]
48 pub member_stake_account: Account<'info, TokenAccount>,
49 pub system_program: Program<'info, System>,
50 pub token_program: Program<'info, Token>,
51}
52
53pub fn set_for_token_member_stake(
54 ctx: Context<SetForTokenMemberStake>,
55 shares: u64,
56) -> Result<()> {
57 let fanout = &mut ctx.accounts.fanout;
58 let member = &ctx.accounts.member;
59 let membership_voucher = &mut ctx.accounts.membership_voucher;
60 let membership_mint = &mut ctx.accounts.membership_mint;
61 assert_owned_by(&fanout.to_account_info(), &crate::ID)?;
62 assert_owned_by(&member.to_account_info(), &System::id())?;
63 assert_membership_model(fanout, MembershipModel::Token)?;
64 assert_ata(
65 &ctx.accounts.member_stake_account.to_account_info(),
66 &membership_voucher.key(),
67 &membership_mint.key(),
68 Some(HydraError::InvalidStakeAta.into()),
69 )?;
70 membership_voucher.fanout = fanout.key();
71 membership_voucher.membership_key = member.key();
72 fanout.total_staked_shares = fanout
73 .total_staked_shares
74 .and_then(|ss| ss.checked_add(shares));
75 fanout.total_shares = membership_mint.supply;
76 fanout.total_members = fanout.total_members.checked_add(1).or_arith_error()?;
77 membership_voucher.shares = shares;
78 membership_voucher.bump_seed = *ctx.bumps.get("membership_voucher").unwrap();
79 let cpi_program = ctx.accounts.token_program.to_account_info();
80 let accounts = anchor_spl::token::Transfer {
81 from: ctx.accounts.membership_mint_token_account.to_account_info(),
82 to: ctx.accounts.member_stake_account.to_account_info(),
83 authority: ctx.accounts.authority.to_account_info(),
84 };
85 let cpi_ctx = CpiContext::new(cpi_program, accounts);
86 anchor_spl::token::transfer(cpi_ctx, shares)?;
87 Ok(())
88}