1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use anchor_lang::prelude::*;
use anchor_spl::token;
#[macro_export]
macro_rules! associated_seeds {
($state:expr, $($with:expr),+) => {
&[
b"anchor".as_ref(),
$($with),+,
]
};
}
use crate::UserStake;
macro_rules! perform_as_user {
($self:expr, $method:ident, $accounts:expr, $amount:expr) => {{
let cpi_program = $self.token_program.to_account_info();
let cpi_ctx = CpiContext::new(cpi_program, $accounts);
token::$method(cpi_ctx, $amount)
}};
}
macro_rules! perform_as_wrapper {
($self:expr, $accounts:expr, $method:ident, $amount:expr) => {{
let seeds = $crate::associated_seeds!(
$self.wrapper,
$self.wrapper.wrapper_underlying_mint.as_ref(),
&[$self.wrapper.decimals],
&[$self.wrapper.nonce()]
);
let signer = &[&seeds[..]];
let cpi_program = $self.token_program.to_account_info();
let cpi_ctx = CpiContext::new_with_signer(cpi_program, $accounts, signer);
token::$method(cpi_ctx, $amount)
}};
}
impl<'info> UserStake<'info> {
pub fn deposit_underlying(&self, amount: u64) -> ProgramResult {
let cpi_accounts = token::Transfer {
from: self.user_underlying_tokens.to_account_info(),
to: self.wrapper_underlying_tokens.to_account_info(),
authority: self.owner.to_account_info(),
};
perform_as_user!(self, transfer, cpi_accounts, amount)
}
pub fn burn_wrapped(&self, amount: u64) -> ProgramResult {
let cpi_accounts = token::Burn {
mint: self.wrapper_mint.to_account_info(),
to: self.user_wrapped_tokens.to_account_info(),
authority: self.owner.to_account_info(),
};
perform_as_user!(self, burn, cpi_accounts, amount)
}
pub fn mint_wrapped(&self, amount: u64) -> ProgramResult {
let cpi_accounts = token::MintTo {
mint: self.wrapper_mint.to_account_info(),
to: self.user_wrapped_tokens.to_account_info(),
authority: self.wrapper.to_account_info(),
};
perform_as_wrapper!(self, cpi_accounts, mint_to, amount)
}
pub fn withdraw_underlying(&self, amount: u64) -> ProgramResult {
let cpi_accounts = token::Transfer {
from: self.wrapper_underlying_tokens.to_account_info(),
to: self.user_underlying_tokens.to_account_info(),
authority: self.wrapper.to_account_info(),
};
perform_as_wrapper!(self, cpi_accounts, transfer, amount)
}
}