Skip to content

Commit 7a21495

Browse files
committed
Add processor
1 parent 3d74a84 commit 7a21495

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

p-token/src/entrypoint.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,13 @@ fn inner_process_remaining_instruction(
473473

474474
process_withdraw_excess_lamports(accounts)
475475
}
476+
// 39 - UnwrapLamports
477+
39 => {
478+
#[cfg(feature = "logging")]
479+
pinocchio::msg!("Instruction: UnwrapLamports");
480+
481+
process_unwrap_lamports(accounts, instruction_data)
482+
}
476483
_ => Err(TokenError::InvalidInstruction.into()),
477484
}
478485
}

p-token/src/processor/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub mod thaw_account;
4242
pub mod transfer;
4343
pub mod transfer_checked;
4444
pub mod ui_amount_to_amount;
45+
pub mod unwrap_lamports;
4546
pub mod withdraw_excess_lamports;
4647
// Shared processors.
4748
pub mod shared;
@@ -62,6 +63,7 @@ pub use {
6263
set_authority::process_set_authority, sync_native::process_sync_native,
6364
thaw_account::process_thaw_account, transfer::process_transfer,
6465
transfer_checked::process_transfer_checked, ui_amount_to_amount::process_ui_amount_to_amount,
66+
unwrap_lamports::process_unwrap_lamports,
6567
withdraw_excess_lamports::process_withdraw_excess_lamports,
6668
};
6769

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use {
2+
super::validate_owner,
3+
crate::processor::{check_account_owner, unpack_amount},
4+
pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramResult},
5+
pinocchio_token_interface::{
6+
error::TokenError,
7+
state::{account::Account, load_mut},
8+
},
9+
};
10+
11+
#[allow(clippy::arithmetic_side_effects)]
12+
pub fn process_unwrap_lamports(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
13+
// Amount being unwrapped.
14+
let amount = unpack_amount(instruction_data)?;
15+
16+
let [source_account_info, destination_account_info, authority_info, remaining @ ..] = accounts
17+
else {
18+
return Err(ProgramError::NotEnoughAccountKeys);
19+
};
20+
21+
// SAFETY: single immutable borrow to `source_account_info` account data
22+
let source_account =
23+
unsafe { load_mut::<Account>(source_account_info.borrow_mut_data_unchecked())? };
24+
25+
if !source_account.is_native() {
26+
return Err(TokenError::NonNativeNotSupported.into());
27+
}
28+
29+
// SAFETY: `authority_info` is not currently borrowed; in the case `authority_info` is
30+
// the same as `source_account_info`, then it cannot be a multisig.
31+
unsafe { validate_owner(&source_account.owner, authority_info, remaining)? };
32+
33+
let remaining_amount = source_account
34+
.amount()
35+
.checked_sub(amount)
36+
.ok_or(TokenError::InsufficientFunds)?;
37+
38+
// Comparing whether the AccountInfo's "point" to the same account or
39+
// not - this is a faster comparison since it just checks the internal
40+
// raw pointer.
41+
let self_transfer = source_account_info == destination_account_info;
42+
43+
if self_transfer || amount == 0 {
44+
// Validates the token account owner since we are not writing
45+
// to the account.
46+
check_account_owner(source_account_info)?;
47+
} else {
48+
source_account.set_amount(remaining_amount);
49+
50+
// SAFETY: single mutable borrow to `source_account_info` lamports.
51+
let source_lamports = unsafe { source_account_info.borrow_mut_lamports_unchecked() };
52+
// Note: The amount of a source token account is already validated and the
53+
// `lamports` on the account is always greater than `amount`.
54+
*source_lamports -= amount;
55+
56+
// SAFETY: single mutable borrow to `destination_account_info` lamports; the
57+
// account is already validated to be different from
58+
// `source_account_info`.
59+
let destination_lamports =
60+
unsafe { destination_account_info.borrow_mut_lamports_unchecked() };
61+
// Note: The total lamports supply is bound to `u64::MAX`.
62+
*destination_lamports += amount;
63+
}
64+
65+
Ok(())
66+
}

0 commit comments

Comments
 (0)