Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 7e3dfb9

Browse files
authored
Merge pull request #1 from febo/shared-processor
Refactor shared processors
2 parents 7e0e82a + acfbba5 commit 7e3dfb9

27 files changed

+729
-643
lines changed

program/src/entrypoint.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ use crate::processor::{
1818
initialize_account2::process_initialize_account2,
1919
initialize_account3::process_initialize_account3,
2020
initialize_immutable_owner::process_initialize_immutable_owner,
21-
initialize_mint::{process_initialize_mint, InitializeMint},
21+
initialize_mint::process_initialize_mint,
2222
initialize_mint2::process_initialize_mint2,
2323
initialize_multisig::process_initialize_multisig,
2424
initialize_multisig2::process_initialize_multisig2,
2525
mint_to::process_mint_to,
2626
mint_to_checked::{process_mint_to_checked, MintToChecked},
2727
revoke::process_revoke,
2828
set_authority::{process_set_authority, SetAuthority},
29+
shared::initialize_mint::InitializeMint,
2930
sync_native::process_sync_native,
3031
thaw_account::process_thaw_account,
3132
transfer::process_transfer,
@@ -49,14 +50,14 @@ pub fn process_instruction(
4950

5051
let instruction = InitializeMint::try_from_bytes(data)?;
5152

52-
process_initialize_mint(accounts, &instruction, true)
53+
process_initialize_mint(accounts, &instruction)
5354
}
5455
// 1 - InitializeAccount
5556
Some((&1, _)) => {
5657
#[cfg(feature = "logging")]
5758
pinocchio::msg!("Instruction: InitializeAccount");
5859

59-
process_initialize_account(program_id, accounts, None, true)
60+
process_initialize_account(program_id, accounts)
6061
}
6162
// 2 - InitializeMultisig
6263
Some((&2, data)) => {
@@ -77,7 +78,7 @@ pub fn process_instruction(
7778
.map_err(|_error| ProgramError::InvalidInstructionData)?,
7879
);
7980

80-
process_transfer(program_id, accounts, amount, None)
81+
process_transfer(program_id, accounts, amount)
8182
}
8283
// 4 - Approve
8384
Some((&4, data)) => {
@@ -89,7 +90,7 @@ pub fn process_instruction(
8990
.map_err(|_error| ProgramError::InvalidInstructionData)?,
9091
);
9192

92-
process_approve(program_id, accounts, amount, None)
93+
process_approve(program_id, accounts, amount)
9394
}
9495
// 5 - Revoke
9596
Some((&5, _)) => {
@@ -121,7 +122,7 @@ pub fn process_instruction(
121122
.map_err(|_error| ProgramError::InvalidInstructionData)?,
122123
);
123124

124-
process_mint_to(program_id, accounts, amount, None)
125+
process_mint_to(program_id, accounts, amount)
125126
}
126127
// 8 - Burn
127128
Some((&8, data)) => {
@@ -133,7 +134,7 @@ pub fn process_instruction(
133134
.map_err(|_error| ProgramError::InvalidInstructionData)?,
134135
);
135136

136-
process_burn(program_id, accounts, amount, None)
137+
process_burn(program_id, accounts, amount)
137138
}
138139
// 9 - CloseAccount
139140
Some((&9, _)) => {

program/src/processor/approve.rs

Lines changed: 3 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,11 @@
1-
use pinocchio::{
2-
account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
3-
};
4-
use token_interface::{
5-
error::TokenError,
6-
state::{account::Account, mint::Mint, PodCOption},
7-
};
1+
use pinocchio::{account_info::AccountInfo, pubkey::Pubkey, ProgramResult};
82

9-
use super::validate_owner;
3+
use super::shared;
104

115
pub fn process_approve(
126
program_id: &Pubkey,
137
accounts: &[AccountInfo],
148
amount: u64,
15-
expected_decimals: Option<u8>,
169
) -> ProgramResult {
17-
let (source_account_info, expected_mint_info, delegate_info, owner_info, remaining) =
18-
if let Some(expected_decimals) = expected_decimals {
19-
let [source_account_info, expected_mint_info, delegate_info, owner_info, remaning @ ..] =
20-
accounts
21-
else {
22-
return Err(ProgramError::NotEnoughAccountKeys);
23-
};
24-
25-
(
26-
source_account_info,
27-
Some((expected_mint_info, expected_decimals)),
28-
delegate_info,
29-
owner_info,
30-
remaning,
31-
)
32-
} else {
33-
let [source_account_info, delegate_info, owner_info, remaning @ ..] = accounts else {
34-
return Err(ProgramError::NotEnoughAccountKeys);
35-
};
36-
(
37-
source_account_info,
38-
None,
39-
delegate_info,
40-
owner_info,
41-
remaning,
42-
)
43-
};
44-
45-
let source_account = bytemuck::try_from_bytes_mut::<Account>(unsafe {
46-
source_account_info.borrow_mut_data_unchecked()
47-
})
48-
.map_err(|_error| ProgramError::InvalidAccountData)?;
49-
50-
if source_account.is_frozen() {
51-
return Err(TokenError::AccountFrozen.into());
52-
}
53-
54-
if let Some((mint_info, expected_decimals)) = expected_mint_info {
55-
if mint_info.key() != &source_account.mint {
56-
return Err(TokenError::MintMismatch.into());
57-
}
58-
59-
let mint = bytemuck::try_from_bytes::<Mint>(unsafe { mint_info.borrow_data_unchecked() })
60-
.map_err(|_error| ProgramError::InvalidAccountData)?;
61-
62-
if expected_decimals != mint.decimals {
63-
return Err(TokenError::MintDecimalsMismatch.into());
64-
}
65-
}
66-
67-
validate_owner(program_id, &source_account.owner, owner_info, remaining)?;
68-
69-
source_account.delegate = PodCOption::some(*delegate_info.key());
70-
source_account.delegated_amount = amount.into();
71-
72-
Ok(())
10+
shared::approve::process_approve(program_id, accounts, amount, None)
7311
}

program/src/processor/approve_checked.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use pinocchio::{
44
account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
55
};
66

7-
use super::approve::process_approve;
7+
use super::shared;
88

99
#[inline(always)]
1010
pub fn process_approve_checked(
@@ -13,7 +13,7 @@ pub fn process_approve_checked(
1313
amount: u64,
1414
decimals: u8,
1515
) -> ProgramResult {
16-
process_approve(program_id, accounts, amount, Some(decimals))
16+
shared::approve::process_approve(program_id, accounts, amount, Some(decimals))
1717
}
1818

1919
pub struct ApproveChecked<'a> {

program/src/processor/burn.rs

Lines changed: 4 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,7 @@
1-
use pinocchio::{
2-
account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
3-
};
4-
use token_interface::{
5-
error::TokenError,
6-
state::{account::Account, mint::Mint},
7-
};
1+
use pinocchio::{account_info::AccountInfo, pubkey::Pubkey, ProgramResult};
82

9-
use super::{check_account_owner, is_owned_by_system_program_or_incinerator, validate_owner};
3+
use super::shared;
104

11-
/// Processes a [Burn](enum.TokenInstruction.html) instruction.
12-
pub fn process_burn(
13-
program_id: &Pubkey,
14-
accounts: &[AccountInfo],
15-
amount: u64,
16-
expected_decimals: Option<u8>,
17-
) -> ProgramResult {
18-
let [source_account_info, mint_info, authority_info, remaining @ ..] = accounts else {
19-
return Err(ProgramError::NotEnoughAccountKeys);
20-
};
21-
22-
// Safety: There are no conflicting borrows – the source account is only borrowed once.
23-
let source_account = bytemuck::try_from_bytes_mut::<Account>(unsafe {
24-
source_account_info.borrow_mut_data_unchecked()
25-
})
26-
.map_err(|_error| ProgramError::InvalidAccountData)?;
27-
28-
if source_account.is_frozen() {
29-
return Err(TokenError::AccountFrozen.into());
30-
}
31-
if source_account.is_native.is_some() {
32-
return Err(TokenError::NativeNotSupported.into());
33-
}
34-
35-
// Ensure the source account has the sufficient amount. This is done before
36-
// the value is updated on the account.
37-
let updated_source_amount = u64::from(source_account.amount)
38-
.checked_sub(amount)
39-
.ok_or(TokenError::InsufficientFunds)?;
40-
41-
// Safety: There are no conflicting borrows – the mint account is only borrowed once.
42-
let mint =
43-
bytemuck::try_from_bytes_mut::<Mint>(unsafe { mint_info.borrow_mut_data_unchecked() })
44-
.map_err(|_error| ProgramError::InvalidAccountData)?;
45-
46-
if mint_info.key() != &source_account.mint {
47-
return Err(TokenError::MintMismatch.into());
48-
}
49-
50-
if let Some(expected_decimals) = expected_decimals {
51-
if expected_decimals != mint.decimals {
52-
return Err(TokenError::MintDecimalsMismatch.into());
53-
}
54-
}
55-
56-
if !is_owned_by_system_program_or_incinerator(&source_account.owner) {
57-
match source_account.delegate.as_ref() {
58-
Some(delegate) if authority_info.key() == delegate => {
59-
validate_owner(program_id, delegate, authority_info, remaining)?;
60-
61-
let delegated_amount = u64::from(source_account.delegated_amount)
62-
.checked_sub(amount)
63-
.ok_or(TokenError::InsufficientFunds)?;
64-
source_account.delegated_amount = delegated_amount.into();
65-
66-
if delegated_amount == 0 {
67-
source_account.delegate.clear();
68-
}
69-
}
70-
_ => {
71-
validate_owner(program_id, &source_account.owner, authority_info, remaining)?;
72-
}
73-
}
74-
}
75-
76-
if amount == 0 {
77-
check_account_owner(program_id, source_account_info)?;
78-
check_account_owner(program_id, mint_info)?;
79-
}
80-
81-
source_account.amount = updated_source_amount.into();
82-
83-
let mint_supply = u64::from(mint.supply)
84-
.checked_sub(amount)
85-
.ok_or(TokenError::Overflow)?;
86-
mint.supply = mint_supply.into();
87-
88-
Ok(())
5+
pub fn process_burn(program_id: &Pubkey, accounts: &[AccountInfo], amount: u64) -> ProgramResult {
6+
shared::burn::process_burn(program_id, accounts, amount, None)
897
}

program/src/processor/burn_checked.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use pinocchio::{
44
account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
55
};
66

7-
use super::burn::process_burn;
7+
use super::shared;
88

99
#[inline(always)]
1010
pub fn process_burn_checked(
@@ -13,7 +13,7 @@ pub fn process_burn_checked(
1313
amount: u64,
1414
decimals: u8,
1515
) -> ProgramResult {
16-
process_burn(program_id, accounts, amount, Some(decimals))
16+
shared::burn::process_burn(program_id, accounts, amount, Some(decimals))
1717
}
1818

1919
pub struct BurnChecked<'a> {
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use pinocchio::{account_info::AccountInfo, pubkey::Pubkey, ProgramResult};
22

3-
use super::toggle_account_state::process_toggle_account_state;
3+
use super::shared::toggle_account_state::process_toggle_account_state;
44

5-
#[inline(always)]
65
pub fn process_freeze_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
76
process_toggle_account_state(program_id, accounts, true)
87
}
Lines changed: 4 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,7 @@
1-
use pinocchio::{
2-
account_info::AccountInfo,
3-
program_error::ProgramError,
4-
pubkey::Pubkey,
5-
sysvars::{rent::Rent, Sysvar},
6-
ProgramResult,
7-
};
8-
use std::mem::size_of;
9-
use token_interface::{
10-
error::TokenError,
11-
native_mint::is_native_mint,
12-
state::{
13-
account::{Account, AccountState},
14-
mint::Mint,
15-
PodCOption,
16-
},
17-
};
1+
use pinocchio::{account_info::AccountInfo, pubkey::Pubkey, ProgramResult};
182

19-
use super::check_account_owner;
3+
use super::shared;
204

21-
pub fn process_initialize_account(
22-
program_id: &Pubkey,
23-
accounts: &[AccountInfo],
24-
owner: Option<&Pubkey>,
25-
rent_sysvar_account: bool,
26-
) -> ProgramResult {
27-
let (new_account_info, mint_info, owner, remaning) = if let Some(owner) = owner {
28-
let [new_account_info, mint_info, remaning @ ..] = accounts else {
29-
return Err(ProgramError::NotEnoughAccountKeys);
30-
};
31-
(new_account_info, mint_info, owner, remaning)
32-
} else {
33-
let [new_account_info, mint_info, owner_info, remaning @ ..] = accounts else {
34-
return Err(ProgramError::NotEnoughAccountKeys);
35-
};
36-
(new_account_info, mint_info, owner_info.key(), remaning)
37-
};
38-
39-
// Check rent-exempt status of the token account.
40-
41-
let is_exempt = if rent_sysvar_account {
42-
let rent_sysvar_info = remaning.first().ok_or(ProgramError::NotEnoughAccountKeys)?;
43-
let rent = unsafe { Rent::from_bytes(rent_sysvar_info.borrow_data_unchecked()) };
44-
rent.is_exempt(new_account_info.lamports(), size_of::<Account>())
45-
} else {
46-
Rent::get()?.is_exempt(new_account_info.lamports(), size_of::<Account>())
47-
};
48-
49-
if !is_exempt {
50-
return Err(TokenError::NotRentExempt.into());
51-
}
52-
53-
let account_data = unsafe { new_account_info.borrow_mut_data_unchecked() };
54-
let account = bytemuck::try_from_bytes_mut::<Account>(account_data)
55-
.map_err(|_error| ProgramError::InvalidAccountData)?;
56-
57-
if account.is_initialized() {
58-
return Err(TokenError::AlreadyInUse.into());
59-
}
60-
61-
let is_native_mint = is_native_mint(mint_info.key());
62-
63-
if !is_native_mint {
64-
check_account_owner(program_id, mint_info)?;
65-
66-
let mint_data = unsafe { mint_info.borrow_data_unchecked() };
67-
let mint = bytemuck::try_from_bytes::<Mint>(mint_data)
68-
.map_err(|_error| ProgramError::InvalidAccountData)?;
69-
70-
if !bool::from(mint.is_initialized) {
71-
return Err(TokenError::InvalidMint.into());
72-
}
73-
}
74-
75-
account.mint = *mint_info.key();
76-
account.owner = *owner;
77-
account.close_authority.clear();
78-
account.delegate.clear();
79-
account.delegated_amount = 0u64.into();
80-
account.state = AccountState::Initialized as u8;
81-
82-
if is_native_mint {
83-
let rent = Rent::get()?;
84-
let rent_exempt_reserve = rent.minimum_balance(size_of::<Account>());
85-
86-
account.is_native = PodCOption::from(Some(rent_exempt_reserve.into()));
87-
unsafe {
88-
account.amount = new_account_info
89-
.borrow_lamports_unchecked()
90-
.checked_sub(rent_exempt_reserve)
91-
.ok_or(TokenError::Overflow)?
92-
.into()
93-
}
94-
} else {
95-
account.is_native.clear();
96-
account.amount = 0u64.into();
97-
};
98-
99-
Ok(())
5+
pub fn process_initialize_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
6+
shared::initialize_account::process_initialize_account(program_id, accounts, None, true)
1007
}

0 commit comments

Comments
 (0)