Browse Source

instruction: SyncNative

febo 10 months ago
parent
commit
bb48b87cb1
3 changed files with 44 additions and 0 deletions
  1. 8 0
      p-token/src/entrypoint.rs
  2. 1 0
      p-token/src/processor/mod.rs
  3. 35 0
      p-token/src/processor/sync_native.rs

+ 8 - 0
p-token/src/entrypoint.rs

@@ -21,6 +21,7 @@ use crate::processor::{
     mint_to_checked::{process_mint_to_checked, MintToChecked},
     revoke::process_revoke,
     set_authority::{process_set_authority, SetAuthority},
+    sync_native::process_sync_native,
     thaw_account::process_thaw_account,
     transfer::process_transfer,
     transfer_checked::{process_transfer_checked, TransferChecked},
@@ -194,6 +195,13 @@ pub fn process_instruction(
 
             process_initialize_account2(program_id, accounts, owner)
         }
+        // 17 - SyncNative
+        Some((&17, _)) => {
+            #[cfg(feature = "logging")]
+            pinocchio::msg!("Instruction: SyncNative");
+
+            process_sync_native(program_id, accounts)
+        }
         // 18 - InitializeAccount3
         Some((&18, data)) => {
             #[cfg(feature = "logging")]

+ 1 - 0
p-token/src/processor/mod.rs

@@ -23,6 +23,7 @@ pub mod mint_to;
 pub mod mint_to_checked;
 pub mod revoke;
 pub mod set_authority;
+pub mod sync_native;
 pub mod thaw_account;
 pub mod transfer;
 pub mod transfer_checked;

+ 35 - 0
p-token/src/processor/sync_native.rs

@@ -0,0 +1,35 @@
+use pinocchio::{
+    account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
+};
+use token_interface::{error::TokenError, state::account::Account};
+
+use super::check_account_owner;
+
+pub fn process_sync_native(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
+    let [native_account_info, _remaning @ ..] = accounts else {
+        return Err(ProgramError::NotEnoughAccountKeys);
+    };
+
+    check_account_owner(program_id, native_account_info)?;
+
+    let native_account = bytemuck::try_from_bytes_mut::<Account>(unsafe {
+        native_account_info.borrow_mut_data_unchecked()
+    })
+    .map_err(|_error| ProgramError::InvalidAccountData)?;
+
+    if let Option::Some(rent_exempt_reserve) = native_account.is_native.get() {
+        let new_amount = native_account_info
+            .lamports()
+            .checked_sub(u64::from(rent_exempt_reserve))
+            .ok_or(TokenError::Overflow)?;
+
+        if new_amount < native_account.amount.into() {
+            return Err(TokenError::InvalidState.into());
+        }
+        native_account.amount = new_amount.into();
+    } else {
+        return Err(TokenError::NonNativeNotSupported.into());
+    }
+
+    Ok(())
+}