Browse Source

backport #438 to v2

Jack May 5 years ago
parent
commit
7d793af951
1 changed files with 166 additions and 6 deletions
  1. 166 6
      program/src/processor.rs

+ 166 - 6
program/src/processor.rs

@@ -552,8 +552,7 @@ impl Processor {
         let dest_account_info = next_account_info(account_info_iter)?;
         let authority_info = next_account_info(account_info_iter)?;
 
-        let mut source_data = source_account_info.data.borrow_mut();
-        Account::unpack_mut(&mut source_data, &mut |source_account: &mut Account| {
+        let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
             if !source_account.is_native() && source_account.amount != 0 {
                 return Err(TokenError::NonNativeHasBalance.into());
             }
@@ -576,8 +575,9 @@ impl Processor {
             **source_account_info.lamports.borrow_mut() = 0;
             source_account.amount = 0;
 
+        Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
+
             Ok(())
-        })
     }
 
     /// Processes a [FreezeAccount](enum.TokenInstruction.html) or a
@@ -592,8 +592,7 @@ impl Processor {
         let mint_info = next_account_info(account_info_iter)?;
         let authority_info = next_account_info(account_info_iter)?;
 
-        let mut source_data = source_account_info.data.borrow_mut();
-        Account::unpack_mut(&mut source_data, &mut |source_account: &mut Account| {
+        let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
             if source_account.is_native() {
                 return Err(TokenError::NativeNotSupported.into());
             }
@@ -621,8 +620,9 @@ impl Processor {
                 AccountState::Initialized
             };
 
+        Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
+
             Ok(())
-        })
     }
 
     /// Processes an [Instruction](enum.Instruction.html).
@@ -3567,6 +3567,97 @@ mod tests {
         signers[5].is_signer = true;
     }
 
+    #[test]
+    fn test_close_account_dups() {
+        let program_id = pubkey_rand();
+        let account1_key = pubkey_rand();
+        let mut account1_account = SolanaAccount::new(
+            account_minimum_balance(),
+            Account::get_packed_len(),
+            &program_id,
+        );
+        let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
+        let account2_key = pubkey_rand();
+        let mut account2_account = SolanaAccount::new(
+            account_minimum_balance(),
+            Account::get_packed_len(),
+            &program_id,
+        );
+        let account2_info: AccountInfo = (&account2_key, true, &mut account2_account).into();
+        let owner_key = pubkey_rand();
+        let mint_key = pubkey_rand();
+        let mut mint_account =
+            SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
+        let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
+        let rent_key = rent::id();
+        let mut rent_sysvar = rent_sysvar();
+        let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
+
+        // create mint
+        do_process_instruction_dups(
+            initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
+            vec![mint_info.clone(), rent_info.clone()],
+        )
+        .unwrap();
+
+        // create account
+        do_process_instruction_dups(
+            initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
+            vec![
+                account1_info.clone(),
+                mint_info.clone(),
+                account1_info.clone(),
+                rent_info.clone(),
+            ],
+        )
+        .unwrap();
+
+        // source-owner close
+        do_process_instruction_dups(
+            close_account(
+                &program_id,
+                &account1_key,
+                &account2_key,
+                &account1_key,
+                &[],
+            )
+            .unwrap(),
+            vec![
+                account1_info.clone(),
+                account2_info.clone(),
+                account1_info.clone(),
+            ],
+        )
+        .unwrap();
+
+        // source-close-authority close
+        Account::unpack_unchecked_mut(
+            &mut account1_info.data.borrow_mut(),
+            &mut |account: &mut Account| {
+                account.close_authority = COption::Some(account1_key);
+                account.owner = owner_key;
+                Ok(())
+            },
+        )
+        .unwrap();
+        do_process_instruction_dups(
+            close_account(
+                &program_id,
+                &account1_key,
+                &account2_key,
+                &account1_key,
+                &[],
+            )
+            .unwrap(),
+            vec![
+                account1_info.clone(),
+                account2_info.clone(),
+                account1_info.clone(),
+            ],
+        )
+        .unwrap();
+    }
+
     #[test]
     fn test_close_account() {
         let program_id = pubkey_rand();
@@ -4390,6 +4481,75 @@ mod tests {
         );
     }
 
+    #[test]
+    fn test_freeze_thaw_dups() {
+        let program_id = pubkey_rand();
+        let account1_key = pubkey_rand();
+        let mut account1_account = SolanaAccount::new(
+            account_minimum_balance(),
+            Account::get_packed_len(),
+            &program_id,
+        );
+        let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
+        let owner_key = pubkey_rand();
+        let mint_key = pubkey_rand();
+        let mut mint_account =
+            SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
+        let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
+        let rent_key = rent::id();
+        let mut rent_sysvar = rent_sysvar();
+        let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
+
+        // create mint
+        do_process_instruction_dups(
+            initialize_mint(&program_id, &mint_key, &owner_key, Some(&account1_key), 2).unwrap(),
+            vec![mint_info.clone(), rent_info.clone()],
+        )
+        .unwrap();
+
+        // create account
+        do_process_instruction_dups(
+            initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
+            vec![
+                account1_info.clone(),
+                mint_info.clone(),
+                account1_info.clone(),
+                rent_info.clone(),
+            ],
+        )
+        .unwrap();
+
+        // freeze where mint freeze_authority is account
+        do_process_instruction_dups(
+            freeze_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
+            vec![
+                account1_info.clone(),
+                mint_info.clone(),
+                account1_info.clone(),
+            ],
+        )
+        .unwrap();
+
+        // thaw where mint freeze_authority is account
+        Account::unpack_unchecked_mut(
+            &mut account1_info.data.borrow_mut(),
+            &mut |account: &mut Account| {
+                account.state = AccountState::Frozen;
+                Ok(())
+            },
+        )
+        .unwrap();
+        do_process_instruction_dups(
+            thaw_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
+            vec![
+                account1_info.clone(),
+                mint_info.clone(),
+                account1_info.clone(),
+            ],
+        )
+        .unwrap();
+    }
+
     #[test]
     fn test_freeze_account() {
         let program_id = pubkey_rand();