hydra/processors/stake/
set_for.rs

1use 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    /// CHECK: Native Account
14    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}