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