-
Notifications
You must be signed in to change notification settings - Fork 93
Expand file tree
/
Copy pathapprove.rs
More file actions
84 lines (71 loc) · 2.79 KB
/
approve.rs
File metadata and controls
84 lines (71 loc) · 2.79 KB
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 {
crate::processor::validate_owner,
pinocchio::{
account_info::AccountInfo, hint::unlikely, program_error::ProgramError, pubkey::pubkey_eq,
ProgramResult,
},
pinocchio_token_interface::{
error::TokenError,
state::{account::Account, load, load_mut, mint::Mint},
},
};
#[inline(always)]
pub fn process_approve(
accounts: &[AccountInfo],
amount: u64,
expected_decimals: Option<u8>,
) -> ProgramResult {
// Accounts expected depend on whether we have the mint `decimals` or not; when
// we have the mint `decimals`, we expect the mint account to be present.
let (source_account_info, expected_mint_info, delegate_info, owner_info, remaining) =
if let Some(expected_decimals) = expected_decimals {
let [source_account_info, expected_mint_info, delegate_info, owner_info, remaining @ ..] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
(
source_account_info,
Some((expected_mint_info, expected_decimals)),
delegate_info,
owner_info,
remaining,
)
} else {
let [source_account_info, delegate_info, owner_info, remaining @ ..] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
(
source_account_info,
None,
delegate_info,
owner_info,
remaining,
)
};
// Validates source account.
// SAFETY: single mutable borrow to `source_account_info` account data and
// `load_mut` validates that the account is initialized.
let source_account =
unsafe { load_mut::<Account>(source_account_info.borrow_mut_data_unchecked())? };
if source_account.is_frozen()? {
return Err(TokenError::AccountFrozen.into());
}
if let Some((mint_info, expected_decimals)) = expected_mint_info {
if unlikely(!pubkey_eq(mint_info.key(), &source_account.mint)) {
return Err(TokenError::MintMismatch.into());
}
// SAFETY: single immutable borrow of `mint_info` account data and
// `load` validates that the mint is initialized.
let mint = unsafe { load::<Mint>(mint_info.borrow_data_unchecked())? };
if unlikely(expected_decimals != mint.decimals) {
return Err(TokenError::MintDecimalsMismatch.into());
}
}
// SAFETY: `owner_info` is not currently borrowed.
unsafe { validate_owner(&source_account.owner, owner_info, remaining)? };
// Sets the delegate and delegated amount.
source_account.set_delegate(delegate_info.key());
source_account.set_delegated_amount(amount);
Ok(())
}