From e7a876f2800f5693e076d7ebff2585d5153eb56c Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Mon, 14 Sep 2020 15:08:14 -0600 Subject: [PATCH] Remove Pack mutable unpack methods (#443) * Remove Pack::unpack_mut * Remove Pack::unpack_unchecked_mut --- token/program-v3/src/pack.rs | 27 -- token/program-v3/src/processor.rs | 695 +++++++++++------------------- 2 files changed, 263 insertions(+), 459 deletions(-) diff --git a/token/program-v3/src/pack.rs b/token/program-v3/src/pack.rs index 7a86cb96..106b51b9 100644 --- a/token/program-v3/src/pack.rs +++ b/token/program-v3/src/pack.rs @@ -47,33 +47,6 @@ pub trait Pack: Sealed { Ok(Self::unpack_from_slice(input)?) } - /// Borrow `Self` from `input` for the duration of the call to `f`, but first check that `Self` - /// is initialized - #[inline(never)] - fn unpack_mut(input: &mut [u8], f: &mut F) -> Result - where - F: FnMut(&mut Self) -> Result, - Self: IsInitialized, - { - let mut t = Self::unpack(input)?; - let u = f(&mut t)?; - Self::pack(t, input)?; - Ok(u) - } - - /// Borrow `Self` from `input` for the duration of the call to `f`, without checking that - /// `Self` has been initialized - #[inline(never)] - fn unpack_unchecked_mut(input: &mut [u8], f: &mut F) -> Result - where - F: FnMut(&mut Self) -> Result, - { - let mut t = Self::unpack_unchecked(input)?; - let u = f(&mut t)?; - Self::pack(t, input)?; - Ok(u) - } - /// Pack into slice fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError> { if dst.len() != Self::LEN { diff --git a/token/program-v3/src/processor.rs b/token/program-v3/src/processor.rs index 6f0c0c0e..03a13ca9 100644 --- a/token/program-v3/src/processor.rs +++ b/token/program-v3/src/processor.rs @@ -35,23 +35,23 @@ impl Processor { let mint_data_len = mint_info.data_len(); let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?; - let mut mint_data = mint_info.data.borrow_mut(); - Mint::unpack_unchecked_mut(&mut mint_data, &mut |mint: &mut Mint| { - if mint.is_initialized { - return Err(TokenError::AlreadyInUse.into()); - } + let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow())?; + if mint.is_initialized { + return Err(TokenError::AlreadyInUse.into()); + } - if !rent.is_exempt(mint_info.lamports(), mint_data_len) { - return Err(TokenError::NotRentExempt.into()); - } + if !rent.is_exempt(mint_info.lamports(), mint_data_len) { + return Err(TokenError::NotRentExempt.into()); + } - mint.mint_authority = COption::Some(mint_authority); - mint.decimals = decimals; - mint.is_initialized = true; - mint.freeze_authority = freeze_authority; + mint.mint_authority = COption::Some(mint_authority); + mint.decimals = decimals; + mint.is_initialized = true; + mint.freeze_authority = freeze_authority; - Ok(()) - }) + Mint::pack(mint, &mut mint_info.data.borrow_mut())?; + + Ok(()) } /// Processes an [InitializeAccount](enum.TokenInstruction.html) instruction. @@ -63,40 +63,40 @@ impl Processor { let new_account_info_data_len = new_account_info.data_len(); let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?; - let mut new_account_data = new_account_info.data.borrow_mut(); - Account::unpack_unchecked_mut(&mut new_account_data, &mut |account: &mut Account| { - if account.is_initialized() { - return Err(TokenError::AlreadyInUse.into()); - } + let mut account = Account::unpack_unchecked(&new_account_info.data.borrow())?; + if account.is_initialized() { + return Err(TokenError::AlreadyInUse.into()); + } - if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) { - return Err(TokenError::NotRentExempt.into()); - } + if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) { + return Err(TokenError::NotRentExempt.into()); + } - if *mint_info.key != crate::native_mint::id() { - let _ = Mint::unpack(&mint_info.data.borrow_mut()) - .map_err(|_| Into::::into(TokenError::InvalidMint))?; - } + if *mint_info.key != crate::native_mint::id() { + let _ = Mint::unpack(&mint_info.data.borrow_mut()) + .map_err(|_| Into::::into(TokenError::InvalidMint))?; + } - account.mint = *mint_info.key; - account.owner = *owner_info.key; - account.delegate = COption::None; - account.delegated_amount = 0; - account.state = AccountState::Initialized; - if *mint_info.key == crate::native_mint::id() { - let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len); - account.is_native = COption::Some(rent_exempt_reserve); - account.amount = new_account_info - .lamports() - .checked_sub(rent_exempt_reserve) - .ok_or(TokenError::Overflow)?; - } else { - account.is_native = COption::None; - account.amount = 0; - }; + account.mint = *mint_info.key; + account.owner = *owner_info.key; + account.delegate = COption::None; + account.delegated_amount = 0; + account.state = AccountState::Initialized; + if *mint_info.key == crate::native_mint::id() { + let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len); + account.is_native = COption::Some(rent_exempt_reserve); + account.amount = new_account_info + .lamports() + .checked_sub(rent_exempt_reserve) + .ok_or(TokenError::Overflow)?; + } else { + account.is_native = COption::None; + account.amount = 0; + }; - Ok(()) - }) + Account::pack(account, &mut new_account_info.data.borrow_mut())?; + + Ok(()) } /// Processes a [InitializeMultisig](enum.TokenInstruction.html) instruction. @@ -106,35 +106,32 @@ impl Processor { let multisig_info_data_len = multisig_info.data_len(); let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?; - let mut multisig_account_data = multisig_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut( - &mut multisig_account_data, - &mut |multisig: &mut Multisig| { - if multisig.is_initialized { - return Err(TokenError::AlreadyInUse.into()); - } + let mut multisig = Multisig::unpack_unchecked(&multisig_info.data.borrow())?; + if multisig.is_initialized { + return Err(TokenError::AlreadyInUse.into()); + } - if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) { - return Err(TokenError::NotRentExempt.into()); - } + if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) { + return Err(TokenError::NotRentExempt.into()); + } - let signer_infos = account_info_iter.as_slice(); - multisig.m = m; - multisig.n = signer_infos.len() as u8; - if !is_valid_signer_index(multisig.n as usize) { - return Err(TokenError::InvalidNumberOfProvidedSigners.into()); - } - if !is_valid_signer_index(multisig.m as usize) { - return Err(TokenError::InvalidNumberOfRequiredSigners.into()); - } - for (i, signer_info) in signer_infos.iter().enumerate() { - multisig.signers[i] = *signer_info.key; - } - multisig.is_initialized = true; + let signer_infos = account_info_iter.as_slice(); + multisig.m = m; + multisig.n = signer_infos.len() as u8; + if !is_valid_signer_index(multisig.n as usize) { + return Err(TokenError::InvalidNumberOfProvidedSigners.into()); + } + if !is_valid_signer_index(multisig.m as usize) { + return Err(TokenError::InvalidNumberOfRequiredSigners.into()); + } + for (i, signer_info) in signer_infos.iter().enumerate() { + multisig.signers[i] = *signer_info.key; + } + multisig.is_initialized = true; - Ok(()) - }, - ) + Multisig::pack(multisig, &mut multisig_info.data.borrow_mut())?; + + Ok(()) } /// Processes a [Transfer](enum.TokenInstruction.html) instruction. @@ -715,22 +712,20 @@ impl Processor { if program_id == owner_account_info.owner && owner_account_info.data_len() == Multisig::get_packed_len() { - let mut owner_data = owner_account_info.data.borrow_mut(); - Multisig::unpack_mut(&mut owner_data, &mut |multisig: &mut Multisig| { - let mut num_signers = 0; - for signer in signers.iter() { - if multisig.signers[0..multisig.n as usize].contains(signer.key) { - if !signer.is_signer { - return Err(ProgramError::MissingRequiredSignature); - } - num_signers += 1; + let multisig = Multisig::unpack(&owner_account_info.data.borrow())?; + let mut num_signers = 0; + for signer in signers.iter() { + if multisig.signers[0..multisig.n as usize].contains(signer.key) { + if !signer.is_signer { + return Err(ProgramError::MissingRequiredSignature); } + num_signers += 1; } - if num_signers < multisig.m { - return Err(ProgramError::MissingRequiredSignature); - } - Ok(()) - })?; + } + if num_signers < multisig.m { + return Err(ProgramError::MissingRequiredSignature); + } + return Ok(()); } else if !owner_account_info.is_signer { return Err(ProgramError::MissingRequiredSignature); } @@ -1011,11 +1006,8 @@ mod tests { vec![&mut mint2_account, &mut rent_sysvar], ) .unwrap(); - Mint::unpack_unchecked_mut(&mut mint2_account.data, &mut |mint: &mut Mint| { - assert_eq!(mint.freeze_authority, COption::Some(owner_key)); - Ok(()) - }) - .unwrap(); + let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap(); + assert_eq!(mint.freeze_authority, COption::Some(owner_key)); } #[test] @@ -1223,17 +1215,12 @@ mod tests { .unwrap(); // source-delegate transfer - Account::unpack_unchecked_mut( - &mut account1_info.data.borrow_mut(), - &mut |account: &mut Account| { - account.amount = 1000; - account.delegated_amount = 1000; - account.delegate = COption::Some(account1_key); - account.owner = owner_key; - Ok(()) - }, - ) - .unwrap(); + let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap(); + account.amount = 1000; + account.delegated_amount = 1000; + account.delegate = COption::Some(account1_key); + account.owner = owner_key; + Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( transfer( @@ -1499,11 +1486,9 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut mismatch_account.data, &mut |account: &mut Account| { - account.mint = mint2_key; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap(); + account.mint = mint2_key; + Account::pack(account, &mut mismatch_account.data).unwrap(); // mint to account do_process_instruction( @@ -1729,11 +1714,8 @@ mod tests { ) .unwrap() } - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 1000); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 1000); // insufficient funds assert_eq!( @@ -1890,20 +1872,17 @@ mod tests { vec![&mut mint_account, &mut rent_sysvar], ) .unwrap(); - Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |mint: &mut Mint| { - assert_eq!( - *mint, - Mint { - mint_authority: COption::Some(owner_key), - supply: 0, - decimals, - is_initialized: true, - freeze_authority: COption::None, - } - ); - Ok(()) - }) - .unwrap(); + let mint = Mint::unpack_unchecked(&mint_account.data).unwrap(); + assert_eq!( + mint, + Mint { + mint_authority: COption::Some(owner_key), + supply: 0, + decimals, + is_initialized: true, + freeze_authority: COption::None, + } + ); // create account do_process_instruction( @@ -1924,11 +1903,8 @@ mod tests { ) .unwrap(); let _ = Mint::unpack(&mut mint_account.data).unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 42); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 42); // mint to 2, with incorrect decimals assert_eq!( @@ -1949,11 +1925,8 @@ mod tests { ); let _ = Mint::unpack(&mut mint_account.data).unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 42); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 42); // mint to 2 do_process_instruction( @@ -1971,11 +1944,8 @@ mod tests { ) .unwrap(); let _ = Mint::unpack(&mut mint_account.data).unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 84); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 84); } #[test] @@ -2478,14 +2448,9 @@ mod tests { .unwrap(); // set close_authority when currently self - Account::unpack_unchecked_mut( - &mut account1_info.data.borrow_mut(), - &mut |account: &mut Account| { - account.close_authority = COption::Some(account1_key); - Ok(()) - }, - ) - .unwrap(); + let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap(); + account.close_authority = COption::Some(account1_key); + Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( set_authority( @@ -2896,11 +2861,9 @@ mod tests { .unwrap(); // mint_to when mint_authority is account owner - Mint::unpack_unchecked_mut(&mut mint_info.data.borrow_mut(), &mut |mint: &mut Mint| { - mint.mint_authority = COption::Some(account1_key); - Ok(()) - }) - .unwrap(); + let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow()).unwrap(); + mint.mint_authority = COption::Some(account1_key); + Mint::pack(mint, &mut mint_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( mint_to( &program_id, @@ -3036,11 +2999,9 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut mismatch_account.data, &mut |account: &mut Account| { - account.mint = mint2_key; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap(); + account.mint = mint2_key; + Account::pack(account, &mut mismatch_account.data).unwrap(); // mint to do_process_instruction( @@ -3049,16 +3010,10 @@ mod tests { ) .unwrap(); - Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |mint: &mut Mint| { - assert_eq!(mint.supply, 42); - Ok(()) - }) - .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 42); - Ok(()) - }) - .unwrap(); + let mint = Mint::unpack_unchecked(&mint_account.data).unwrap(); + assert_eq!(mint.supply, 42); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 42); // mint to another account to test supply accumulation do_process_instruction( @@ -3067,16 +3022,10 @@ mod tests { ) .unwrap(); - Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |mint: &mut Mint| { - assert_eq!(mint.supply, 84); - Ok(()) - }) - .unwrap(); - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 42); - Ok(()) - }) - .unwrap(); + let mint = Mint::unpack_unchecked(&mint_account.data).unwrap(); + assert_eq!(mint.supply, 84); + let account = Account::unpack_unchecked(&account2_account.data).unwrap(); + assert_eq!(account.amount, 42); // missing signer let mut instruction = @@ -3248,14 +3197,9 @@ mod tests { vec![mint_info.clone(), account1_info.clone(), owner_info.clone()], ) .unwrap(); - Account::unpack_unchecked_mut( - &mut account1_info.data.borrow_mut(), - &mut |account: &mut Account| { - account.owner = mint_key; - Ok(()) - }, - ) - .unwrap(); + let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap(); + account.owner = mint_key; + Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(), vec![account1_info.clone(), mint_info.clone(), mint_info.clone()], @@ -3284,16 +3228,11 @@ mod tests { vec![mint_info.clone(), account1_info.clone(), owner_info.clone()], ) .unwrap(); - Account::unpack_unchecked_mut( - &mut account1_info.data.borrow_mut(), - &mut |account: &mut Account| { - account.delegated_amount = 1000; - account.delegate = COption::Some(account1_key); - account.owner = owner_key; - Ok(()) - }, - ) - .unwrap(); + let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap(); + account.delegated_amount = 1000; + account.delegate = COption::Some(account1_key); + account.owner = owner_key; + Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( burn( &program_id, @@ -3338,16 +3277,11 @@ mod tests { vec![mint_info.clone(), account1_info.clone(), owner_info.clone()], ) .unwrap(); - Account::unpack_unchecked_mut( - &mut account1_info.data.borrow_mut(), - &mut |account: &mut Account| { - account.delegated_amount = 1000; - account.delegate = COption::Some(mint_key); - account.owner = owner_key; - Ok(()) - }, - ) - .unwrap(); + let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap(); + account.delegated_amount = 1000; + account.delegate = COption::Some(mint_key); + account.owner = owner_key; + Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(), vec![account1_info.clone(), mint_info.clone(), mint_info.clone()], @@ -3464,11 +3398,9 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut mismatch_account.data, &mut |account: &mut Account| { - account.mint = mint2_key; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap(); + account.mint = mint2_key; + Account::pack(account, &mut mismatch_account.data).unwrap(); // mint to account do_process_instruction( @@ -3534,17 +3466,10 @@ mod tests { ) .unwrap(); - Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |mint: &mut Mint| { - assert_eq!(mint.supply, 1000 - 42); - - Ok(()) - }) - .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 1000 - 42); - Ok(()) - }) - .unwrap(); + let mint = Mint::unpack_unchecked(&mint_account.data).unwrap(); + assert_eq!(mint.supply, 1000 - 42); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 1000 - 42); // insufficient funds assert_eq!( @@ -3611,16 +3536,10 @@ mod tests { .unwrap(); // match - Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |mint: &mut Mint| { - assert_eq!(mint.supply, 1000 - 42 - 84); - Ok(()) - }) - .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 1000 - 42 - 84); - Ok(()) - }) - .unwrap(); + let mint = Mint::unpack_unchecked(&mint_account.data).unwrap(); + assert_eq!(mint.supply, 1000 - 42 - 84); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 1000 - 42 - 84); // insufficient funds approved via delegate assert_eq!( @@ -4076,14 +3995,12 @@ mod tests { } let mut lamports = 0; let mut data = vec![0; Multisig::get_packed_len()]; - Multisig::unpack_unchecked_mut(&mut data, &mut |multisig: &mut Multisig| { - multisig.m = MAX_SIGNERS as u8; - multisig.n = MAX_SIGNERS as u8; - multisig.signers = signer_keys; - multisig.is_initialized = true; - Ok(()) - }) - .unwrap(); + let mut multisig = Multisig::unpack_unchecked(&data).unwrap(); + multisig.m = MAX_SIGNERS as u8; + multisig.n = MAX_SIGNERS as u8; + multisig.signers = signer_keys; + multisig.is_initialized = true; + Multisig::pack(multisig, &mut data).unwrap(); let owner_account_info = AccountInfo::new( &owner_key, false, @@ -4100,24 +4017,20 @@ mod tests { // 1 of 11 { - let mut data_ref_mut = owner_account_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut(&mut data_ref_mut, &mut |multisig: &mut Multisig| { - multisig.m = 1; - Ok(()) - }) - .unwrap(); + let mut multisig = + Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap(); + multisig.m = 1; + Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap(); } Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap(); // 2:1 { - let mut data_ref_mut = owner_account_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut(&mut data_ref_mut, &mut |multisig: &mut Multisig| { - multisig.m = 2; - multisig.n = 1; - Ok(()) - }) - .unwrap(); + let mut multisig = + Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap(); + multisig.m = 2; + multisig.n = 1; + Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap(); } assert_eq!( Err(ProgramError::MissingRequiredSignature), @@ -4126,25 +4039,21 @@ mod tests { // 0:11 { - let mut data_ref_mut = owner_account_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut(&mut data_ref_mut, &mut |multisig: &mut Multisig| { - multisig.m = 0; - multisig.n = 11; - Ok(()) - }) - .unwrap(); + let mut multisig = + Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap(); + multisig.m = 0; + multisig.n = 11; + Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap(); } Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap(); // 2:11 but 0 provided { - let mut data_ref_mut = owner_account_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut(&mut data_ref_mut, &mut |multisig: &mut Multisig| { - multisig.m = 2; - multisig.n = 11; - Ok(()) - }) - .unwrap(); + let mut multisig = + Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap(); + multisig.m = 2; + multisig.n = 11; + Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap(); } assert_eq!( Err(ProgramError::MissingRequiredSignature), @@ -4152,13 +4061,11 @@ mod tests { ); // 2:11 but 1 provided { - let mut data_ref_mut = owner_account_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut(&mut data_ref_mut, &mut |multisig: &mut Multisig| { - multisig.m = 2; - multisig.n = 11; - Ok(()) - }) - .unwrap(); + let mut multisig = + Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap(); + multisig.m = 2; + multisig.n = 11; + Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap(); } assert_eq!( Err(ProgramError::MissingRequiredSignature), @@ -4167,26 +4074,22 @@ mod tests { // 2:11, 2 from middle provided { - let mut data_ref_mut = owner_account_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut(&mut data_ref_mut, &mut |multisig: &mut Multisig| { - multisig.m = 2; - multisig.n = 11; - Ok(()) - }) - .unwrap(); + let mut multisig = + Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap(); + multisig.m = 2; + multisig.n = 11; + Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap(); } Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[5..7]) .unwrap(); // 11:11, one is not a signer { - let mut data_ref_mut = owner_account_info.data.borrow_mut(); - Multisig::unpack_unchecked_mut(&mut data_ref_mut, &mut |multisig: &mut Multisig| { - multisig.m = 2; // TODO 11? - multisig.n = 11; - Ok(()) - }) - .unwrap(); + let mut multisig = + Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap(); + multisig.m = 2; // TODO 11? + multisig.n = 11; + Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap(); } signers[5].is_signer = false; assert_eq!( @@ -4260,15 +4163,10 @@ mod tests { .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(); + let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap(); + account.close_authority = COption::Some(account1_key); + account.owner = owner_key; + Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( close_account( &program_id, @@ -4356,11 +4254,8 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 42); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 42); // initialize native account do_process_instruction( @@ -4379,12 +4274,9 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - assert!(account.is_native()); - assert_eq!(account.amount, 42); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account2_account.data).unwrap(); + assert!(account.is_native()); + assert_eq!(account.amount, 42); // close non-native account with balance assert_eq!( @@ -4432,11 +4324,8 @@ mod tests { .unwrap(); assert_eq!(account_account.lamports, 0); assert_eq!(account3_account.lamports, 2 * account_minimum_balance()); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 0); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 0); // fund and initialize new non-native account to test close authority let account_key = pubkey_rand(); @@ -4502,11 +4391,8 @@ mod tests { .unwrap(); assert_eq!(account_account.lamports, 0); assert_eq!(account3_account.lamports, 2 * account_minimum_balance() + 2); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, 0); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, 0); // close native account do_process_instruction( @@ -4518,17 +4404,14 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - assert!(account.is_native()); - assert_eq!(account_account.lamports, 0); - assert_eq!(account.amount, 0); - assert_eq!( - account3_account.lamports, - 3 * account_minimum_balance() + 2 + 42 - ); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account2_account.data).unwrap(); + assert!(account.is_native()); + assert_eq!(account_account.lamports, 0); + assert_eq!(account.amount, 0); + assert_eq!( + account3_account.lamports, + 3 * account_minimum_balance() + 2 + 42 + ); } #[test] @@ -4571,12 +4454,9 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert!(account.is_native()); - assert_eq!(account.amount, 40); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert!(account.is_native()); + assert_eq!(account.amount, 40); // initialize native account do_process_instruction( @@ -4595,12 +4475,9 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - assert!(account.is_native()); - assert_eq!(account.amount, 0); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account2_account.data).unwrap(); + assert!(account.is_native()); + assert_eq!(account.amount, 0); // mint_to unsupported assert_eq!( @@ -4689,19 +4566,13 @@ mod tests { ) .unwrap(); assert_eq!(account_account.lamports, account_minimum_balance()); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert!(account.is_native()); - assert_eq!(account.amount, 0); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert!(account.is_native()); + assert_eq!(account.amount, 0); assert_eq!(account2_account.lamports, account_minimum_balance() + 40); - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - assert!(account.is_native()); - assert_eq!(account.amount, 40); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account2_account.data).unwrap(); + assert!(account.is_native()); + assert_eq!(account.amount, 40); // close native account do_process_instruction( @@ -4715,12 +4586,9 @@ mod tests { .unwrap(); assert_eq!(account_account.lamports, 0); assert_eq!(account3_account.lamports, 2 * account_minimum_balance()); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert!(account.is_native()); - assert_eq!(account.amount, 0); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert!(account.is_native()); + assert_eq!(account.amount, 0); } #[test] @@ -4798,11 +4666,8 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, u64::MAX); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, u64::MAX); // attempt to mint one more to account assert_eq!( @@ -4824,11 +4689,8 @@ mod tests { ], ) ); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, u64::MAX); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, u64::MAX); // atttempt to mint one more to the other account assert_eq!( @@ -4857,11 +4719,8 @@ mod tests { vec![&mut account_account, &mut mint_account, &mut owner_account], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, u64::MAX - 100); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, u64::MAX - 100); do_process_instruction( mint_to( @@ -4880,18 +4739,13 @@ mod tests { ], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.amount, u64::MAX); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.amount, u64::MAX); // manipulate account balance to attempt overflow transfer - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - account.amount = 1; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&account2_account.data).unwrap(); + account.amount = 1; + Account::pack(account, &mut account2_account.data).unwrap(); assert_eq!( Err(TokenError::Overflow.into()), @@ -4975,11 +4829,9 @@ mod tests { .unwrap(); // no transfer if either account is frozen - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - account.state = AccountState::Frozen; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&account2_account.data).unwrap(); + account.state = AccountState::Frozen; + Account::pack(account, &mut account2_account.data).unwrap(); assert_eq!( Err(TokenError::AccountFrozen.into()), do_process_instruction( @@ -5000,16 +4852,12 @@ mod tests { ) ); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - account.state = AccountState::Initialized; - Ok(()) - }) - .unwrap(); - Account::unpack_unchecked_mut(&mut account2_account.data, &mut |account: &mut Account| { - account.state = AccountState::Frozen; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&account_account.data).unwrap(); + account.state = AccountState::Initialized; + Account::pack(account, &mut account_account.data).unwrap(); + let mut account = Account::unpack_unchecked(&account2_account.data).unwrap(); + account.state = AccountState::Frozen; + Account::pack(account, &mut account2_account.data).unwrap(); assert_eq!( Err(TokenError::AccountFrozen.into()), do_process_instruction( @@ -5031,11 +4879,9 @@ mod tests { ); // no approve if account is frozen - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - account.state = AccountState::Frozen; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&account_account.data).unwrap(); + account.state = AccountState::Frozen; + Account::pack(account, &mut account_account.data).unwrap(); let delegate_key = pubkey_rand(); let mut delegate_account = SolanaAccount::default(); assert_eq!( @@ -5059,12 +4905,10 @@ mod tests { ); // no revoke if account is frozen - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - account.delegate = COption::Some(delegate_key); - account.delegated_amount = 100; - Ok(()) - }) - .unwrap(); + let mut account = Account::unpack_unchecked(&account_account.data).unwrap(); + account.delegate = COption::Some(delegate_key); + account.delegated_amount = 100; + Account::pack(account, &mut account_account.data).unwrap(); assert_eq!( Err(TokenError::AccountFrozen.into()), do_process_instruction( @@ -5160,14 +5004,9 @@ mod tests { .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(); + let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap(); + account.state = AccountState::Frozen; + Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap(); do_process_instruction_dups( thaw_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(), vec![ @@ -5235,11 +5074,9 @@ mod tests { ); // missing freeze_authority - Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |mint: &mut Mint| { - mint.freeze_authority = COption::Some(owner_key); - Ok(()) - }) - .unwrap(); + let mut mint = Mint::unpack_unchecked(&mint_account.data).unwrap(); + mint.freeze_authority = COption::Some(owner_key); + Mint::pack(mint, &mut mint_account.data).unwrap(); assert_eq!( Err(TokenError::OwnerMismatch.into()), do_process_instruction( @@ -5263,11 +5100,8 @@ mod tests { vec![&mut account_account, &mut mint_account, &mut owner_account], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.state, AccountState::Frozen); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.state, AccountState::Frozen); // check explicit freeze assert_eq!( @@ -5293,10 +5127,7 @@ mod tests { vec![&mut account_account, &mut mint_account, &mut owner_account], ) .unwrap(); - Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| { - assert_eq!(account.state, AccountState::Initialized); - Ok(()) - }) - .unwrap(); + let account = Account::unpack_unchecked(&account_account.data).unwrap(); + assert_eq!(account.state, AccountState::Initialized); } }