Add InitializeMint2/InitializeMultisig2/InitializeAccount3 instructions
This commit is contained in:
parent
b4b9763a00
commit
44ad2ff5b4
|
@ -373,6 +373,42 @@ pub enum TokenInstruction {
|
|||
///
|
||||
/// 0. `[writable]` The native token account to sync with its underlying lamports.
|
||||
SyncNative,
|
||||
/// Like InitializeAccount2, but does not require the Rent sysvar to be provided
|
||||
///
|
||||
/// Accounts expected by this instruction:
|
||||
///
|
||||
/// 0. `[writable]` The account to initialize.
|
||||
/// 1. `[]` The mint this account will be associated with.
|
||||
InitializeAccount3 {
|
||||
/// The new account's owner/multisignature.
|
||||
owner: Pubkey,
|
||||
},
|
||||
/// Like InitializeMultisig, but does not require the Rent sysvar to be provided
|
||||
///
|
||||
/// Accounts expected by this instruction:
|
||||
///
|
||||
/// 0. `[writable]` The multisignature account to initialize.
|
||||
/// 1. ..1+N. `[]` The signer accounts, must equal to N where 1 <= N <=
|
||||
/// 11.
|
||||
InitializeMultisig2 {
|
||||
/// The number of signers (M) required to validate this multisignature
|
||||
/// account.
|
||||
m: u8,
|
||||
},
|
||||
/// Like InitializeMint, but does not require the Rent sysvar to be provided
|
||||
///
|
||||
/// Accounts expected by this instruction:
|
||||
///
|
||||
/// 0. `[writable]` The mint to initialize.
|
||||
///
|
||||
InitializeMint2 {
|
||||
/// Number of base 10 digits to the right of the decimal place.
|
||||
decimals: u8,
|
||||
/// The authority/multisignature to mint tokens.
|
||||
mint_authority: Pubkey,
|
||||
/// The freeze authority/multisignature of the mint.
|
||||
freeze_authority: COption<Pubkey>,
|
||||
},
|
||||
}
|
||||
impl TokenInstruction {
|
||||
/// Unpacks a byte buffer into a [TokenInstruction](enum.TokenInstruction.html).
|
||||
|
@ -475,7 +511,24 @@ impl TokenInstruction {
|
|||
Self::InitializeAccount2 { owner }
|
||||
}
|
||||
17 => Self::SyncNative,
|
||||
|
||||
18 => {
|
||||
let (owner, _rest) = Self::unpack_pubkey(rest)?;
|
||||
Self::InitializeAccount3 { owner }
|
||||
}
|
||||
19 => {
|
||||
let &m = rest.get(0).ok_or(InvalidInstruction)?;
|
||||
Self::InitializeMultisig2 { m }
|
||||
}
|
||||
20 => {
|
||||
let (&decimals, rest) = rest.split_first().ok_or(InvalidInstruction)?;
|
||||
let (mint_authority, rest) = Self::unpack_pubkey(rest)?;
|
||||
let (freeze_authority, _rest) = Self::unpack_pubkey_option(rest)?;
|
||||
Self::InitializeMint2 {
|
||||
mint_authority,
|
||||
freeze_authority,
|
||||
decimals,
|
||||
}
|
||||
}
|
||||
_ => return Err(TokenError::InvalidInstruction.into()),
|
||||
})
|
||||
}
|
||||
|
@ -554,6 +607,24 @@ impl TokenInstruction {
|
|||
&Self::SyncNative => {
|
||||
buf.push(17);
|
||||
}
|
||||
&Self::InitializeAccount3 { owner } => {
|
||||
buf.push(18);
|
||||
buf.extend_from_slice(owner.as_ref());
|
||||
}
|
||||
&Self::InitializeMultisig2 { m } => {
|
||||
buf.push(19);
|
||||
buf.push(m);
|
||||
}
|
||||
&Self::InitializeMint2 {
|
||||
ref mint_authority,
|
||||
ref freeze_authority,
|
||||
decimals,
|
||||
} => {
|
||||
buf.push(20);
|
||||
buf.push(decimals);
|
||||
buf.extend_from_slice(mint_authority.as_ref());
|
||||
Self::pack_pubkey_option(freeze_authority, &mut buf);
|
||||
}
|
||||
};
|
||||
buf
|
||||
}
|
||||
|
@ -655,6 +726,32 @@ pub fn initialize_mint(
|
|||
})
|
||||
}
|
||||
|
||||
/// Creates a `InitializeMint2` instruction.
|
||||
pub fn initialize_mint2(
|
||||
token_program_id: &Pubkey,
|
||||
mint_pubkey: &Pubkey,
|
||||
mint_authority_pubkey: &Pubkey,
|
||||
freeze_authority_pubkey: Option<&Pubkey>,
|
||||
decimals: u8,
|
||||
) -> Result<Instruction, ProgramError> {
|
||||
check_program_account(token_program_id)?;
|
||||
let freeze_authority = freeze_authority_pubkey.cloned().into();
|
||||
let data = TokenInstruction::InitializeMint2 {
|
||||
mint_authority: *mint_authority_pubkey,
|
||||
freeze_authority,
|
||||
decimals,
|
||||
}
|
||||
.pack();
|
||||
|
||||
let accounts = vec![AccountMeta::new(*mint_pubkey, false)];
|
||||
|
||||
Ok(Instruction {
|
||||
program_id: *token_program_id,
|
||||
accounts,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a `InitializeAccount` instruction.
|
||||
pub fn initialize_account(
|
||||
token_program_id: &Pubkey,
|
||||
|
@ -705,6 +802,31 @@ pub fn initialize_account2(
|
|||
})
|
||||
}
|
||||
|
||||
/// Creates a `InitializeAccount3` instruction.
|
||||
pub fn initialize_account3(
|
||||
token_program_id: &Pubkey,
|
||||
account_pubkey: &Pubkey,
|
||||
mint_pubkey: &Pubkey,
|
||||
owner_pubkey: &Pubkey,
|
||||
) -> Result<Instruction, ProgramError> {
|
||||
check_program_account(token_program_id)?;
|
||||
let data = TokenInstruction::InitializeAccount3 {
|
||||
owner: *owner_pubkey,
|
||||
}
|
||||
.pack();
|
||||
|
||||
let accounts = vec![
|
||||
AccountMeta::new(*account_pubkey, false),
|
||||
AccountMeta::new_readonly(*mint_pubkey, false),
|
||||
];
|
||||
|
||||
Ok(Instruction {
|
||||
program_id: *token_program_id,
|
||||
accounts,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a `InitializeMultisig` instruction.
|
||||
pub fn initialize_multisig(
|
||||
token_program_id: &Pubkey,
|
||||
|
@ -735,6 +857,35 @@ pub fn initialize_multisig(
|
|||
})
|
||||
}
|
||||
|
||||
/// Creates a `InitializeMultisig2` instruction.
|
||||
pub fn initialize_multisig2(
|
||||
token_program_id: &Pubkey,
|
||||
multisig_pubkey: &Pubkey,
|
||||
signer_pubkeys: &[&Pubkey],
|
||||
m: u8,
|
||||
) -> Result<Instruction, ProgramError> {
|
||||
check_program_account(token_program_id)?;
|
||||
if !is_valid_signer_index(m as usize)
|
||||
|| !is_valid_signer_index(signer_pubkeys.len())
|
||||
|| m as usize > signer_pubkeys.len()
|
||||
{
|
||||
return Err(ProgramError::MissingRequiredSignature);
|
||||
}
|
||||
let data = TokenInstruction::InitializeMultisig2 { m }.pack();
|
||||
|
||||
let mut accounts = Vec::with_capacity(1 + 1 + signer_pubkeys.len());
|
||||
accounts.push(AccountMeta::new(*multisig_pubkey, false));
|
||||
for signer_pubkey in signer_pubkeys.iter() {
|
||||
accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
|
||||
}
|
||||
|
||||
Ok(Instruction {
|
||||
program_id: *token_program_id,
|
||||
accounts,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a `Transfer` instruction.
|
||||
pub fn transfer(
|
||||
token_program_id: &Pubkey,
|
||||
|
@ -1323,5 +1474,49 @@ mod test {
|
|||
assert_eq!(packed, expect);
|
||||
let unpacked = TokenInstruction::unpack(&expect).unwrap();
|
||||
assert_eq!(unpacked, check);
|
||||
|
||||
let check = TokenInstruction::InitializeAccount3 {
|
||||
owner: Pubkey::new(&[2u8; 32]),
|
||||
};
|
||||
let packed = check.pack();
|
||||
let mut expect = vec![18u8];
|
||||
expect.extend_from_slice(&[2u8; 32]);
|
||||
assert_eq!(packed, expect);
|
||||
let unpacked = TokenInstruction::unpack(&expect).unwrap();
|
||||
assert_eq!(unpacked, check);
|
||||
|
||||
let check = TokenInstruction::InitializeMultisig2 { m: 1 };
|
||||
let packed = check.pack();
|
||||
let expect = Vec::from([19u8, 1]);
|
||||
assert_eq!(packed, expect);
|
||||
let unpacked = TokenInstruction::unpack(&expect).unwrap();
|
||||
assert_eq!(unpacked, check);
|
||||
|
||||
let check = TokenInstruction::InitializeMint2 {
|
||||
decimals: 2,
|
||||
mint_authority: Pubkey::new(&[1u8; 32]),
|
||||
freeze_authority: COption::None,
|
||||
};
|
||||
let packed = check.pack();
|
||||
let mut expect = Vec::from([20u8, 2]);
|
||||
expect.extend_from_slice(&[1u8; 32]);
|
||||
expect.extend_from_slice(&[0]);
|
||||
assert_eq!(packed, expect);
|
||||
let unpacked = TokenInstruction::unpack(&expect).unwrap();
|
||||
assert_eq!(unpacked, check);
|
||||
|
||||
let check = TokenInstruction::InitializeMint2 {
|
||||
decimals: 2,
|
||||
mint_authority: Pubkey::new(&[2u8; 32]),
|
||||
freeze_authority: COption::Some(Pubkey::new(&[3u8; 32])),
|
||||
};
|
||||
let packed = check.pack();
|
||||
let mut expect = vec![20u8, 2];
|
||||
expect.extend_from_slice(&[2u8; 32]);
|
||||
expect.extend_from_slice(&[1]);
|
||||
expect.extend_from_slice(&[3u8; 32]);
|
||||
assert_eq!(packed, expect);
|
||||
let unpacked = TokenInstruction::unpack(&expect).unwrap();
|
||||
assert_eq!(unpacked, check);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![deny(missing_docs)]
|
||||
#![forbid(unsafe_code)]
|
||||
#![cfg_attr(not(test), forbid(unsafe_code))]
|
||||
|
||||
//! An ERC20-like Token program for the Solana blockchain
|
||||
|
||||
|
|
|
@ -21,17 +21,21 @@ use solana_program::{
|
|||
/// Program state handler.
|
||||
pub struct Processor {}
|
||||
impl Processor {
|
||||
/// Processes an [InitializeMint](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_mint(
|
||||
fn _process_initialize_mint(
|
||||
accounts: &[AccountInfo],
|
||||
decimals: u8,
|
||||
mint_authority: Pubkey,
|
||||
freeze_authority: COption<Pubkey>,
|
||||
rent_sysvar_account: bool,
|
||||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let mint_info = next_account_info(account_info_iter)?;
|
||||
let mint_data_len = mint_info.data_len();
|
||||
let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
|
||||
let rent = if rent_sysvar_account {
|
||||
Rent::from_account_info(next_account_info(account_info_iter)?)?
|
||||
} else {
|
||||
Rent::get()?
|
||||
};
|
||||
|
||||
let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow())?;
|
||||
if mint.is_initialized {
|
||||
|
@ -52,9 +56,30 @@ impl Processor {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Processes an [InitializeMint](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_mint(
|
||||
accounts: &[AccountInfo],
|
||||
decimals: u8,
|
||||
mint_authority: Pubkey,
|
||||
freeze_authority: COption<Pubkey>,
|
||||
) -> ProgramResult {
|
||||
Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, true)
|
||||
}
|
||||
|
||||
/// Processes an [InitializeMint2](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_mint2(
|
||||
accounts: &[AccountInfo],
|
||||
decimals: u8,
|
||||
mint_authority: Pubkey,
|
||||
freeze_authority: COption<Pubkey>,
|
||||
) -> ProgramResult {
|
||||
Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, false)
|
||||
}
|
||||
|
||||
fn _process_initialize_account(
|
||||
accounts: &[AccountInfo],
|
||||
owner: Option<&Pubkey>,
|
||||
rent_sysvar_account: bool,
|
||||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let new_account_info = next_account_info(account_info_iter)?;
|
||||
|
@ -65,7 +90,11 @@ impl Processor {
|
|||
next_account_info(account_info_iter)?.key
|
||||
};
|
||||
let new_account_info_data_len = new_account_info.data_len();
|
||||
let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
|
||||
let rent = if rent_sysvar_account {
|
||||
Rent::from_account_info(next_account_info(account_info_iter)?)?
|
||||
} else {
|
||||
Rent::get()?
|
||||
};
|
||||
|
||||
let mut account = Account::unpack_unchecked(&new_account_info.data.borrow())?;
|
||||
if account.is_initialized() {
|
||||
|
@ -105,20 +134,32 @@ impl Processor {
|
|||
|
||||
/// Processes an [InitializeAccount](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_account(accounts: &[AccountInfo]) -> ProgramResult {
|
||||
Self::_process_initialize_account(accounts, None)
|
||||
Self::_process_initialize_account(accounts, None, true)
|
||||
}
|
||||
|
||||
/// Processes an [InitializeAccount2](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_account2(accounts: &[AccountInfo], owner: Pubkey) -> ProgramResult {
|
||||
Self::_process_initialize_account(accounts, Some(&owner))
|
||||
Self::_process_initialize_account(accounts, Some(&owner), true)
|
||||
}
|
||||
|
||||
/// Processes a [InitializeMultisig](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
|
||||
/// Processes an [InitializeAccount3](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_account3(accounts: &[AccountInfo], owner: Pubkey) -> ProgramResult {
|
||||
Self::_process_initialize_account(accounts, Some(&owner), false)
|
||||
}
|
||||
|
||||
fn _process_initialize_multisig(
|
||||
accounts: &[AccountInfo],
|
||||
m: u8,
|
||||
rent_sysvar_account: bool,
|
||||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let multisig_info = next_account_info(account_info_iter)?;
|
||||
let multisig_info_data_len = multisig_info.data_len();
|
||||
let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
|
||||
let rent = if rent_sysvar_account {
|
||||
Rent::from_account_info(next_account_info(account_info_iter)?)?
|
||||
} else {
|
||||
Rent::get()?
|
||||
};
|
||||
|
||||
let mut multisig = Multisig::unpack_unchecked(&multisig_info.data.borrow())?;
|
||||
if multisig.is_initialized {
|
||||
|
@ -148,6 +189,16 @@ impl Processor {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Processes a [InitializeMultisig](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
|
||||
Self::_process_initialize_multisig(accounts, m, true)
|
||||
}
|
||||
|
||||
/// Processes a [InitializeMultisig2](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_initialize_multisig2(accounts: &[AccountInfo], m: u8) -> ProgramResult {
|
||||
Self::_process_initialize_multisig(accounts, m, false)
|
||||
}
|
||||
|
||||
/// Processes a [Transfer](enum.TokenInstruction.html) instruction.
|
||||
pub fn process_transfer(
|
||||
program_id: &Pubkey,
|
||||
|
@ -688,6 +739,14 @@ impl Processor {
|
|||
msg!("Instruction: InitializeMint");
|
||||
Self::process_initialize_mint(accounts, decimals, mint_authority, freeze_authority)
|
||||
}
|
||||
TokenInstruction::InitializeMint2 {
|
||||
decimals,
|
||||
mint_authority,
|
||||
freeze_authority,
|
||||
} => {
|
||||
msg!("Instruction: InitializeMint2");
|
||||
Self::process_initialize_mint2(accounts, decimals, mint_authority, freeze_authority)
|
||||
}
|
||||
TokenInstruction::InitializeAccount => {
|
||||
msg!("Instruction: InitializeAccount");
|
||||
Self::process_initialize_account(accounts)
|
||||
|
@ -696,10 +755,18 @@ impl Processor {
|
|||
msg!("Instruction: InitializeAccount2");
|
||||
Self::process_initialize_account2(accounts, owner)
|
||||
}
|
||||
TokenInstruction::InitializeAccount3 { owner } => {
|
||||
msg!("Instruction: InitializeAccount3");
|
||||
Self::process_initialize_account3(accounts, owner)
|
||||
}
|
||||
TokenInstruction::InitializeMultisig { m } => {
|
||||
msg!("Instruction: InitializeMultisig");
|
||||
Self::process_initialize_multisig(accounts, m)
|
||||
}
|
||||
TokenInstruction::InitializeMultisig2 { m } => {
|
||||
msg!("Instruction: InitializeMultisig2");
|
||||
Self::process_initialize_multisig2(accounts, m)
|
||||
}
|
||||
TokenInstruction::Transfer { amount } => {
|
||||
msg!("Instruction: Transfer");
|
||||
Self::process_transfer(program_id, accounts, amount, None)
|
||||
|
@ -849,16 +916,60 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::instruction::*;
|
||||
use solana_program::{
|
||||
account_info::IntoAccountInfo, clock::Epoch, instruction::Instruction, sysvar::rent,
|
||||
account_info::IntoAccountInfo, clock::Epoch, instruction::Instruction, program_error,
|
||||
sysvar::rent,
|
||||
};
|
||||
use solana_sdk::account::{
|
||||
create_account_for_test, create_is_signer_account_infos, Account as SolanaAccount,
|
||||
};
|
||||
|
||||
struct SyscallStubs {}
|
||||
impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
||||
fn sol_log(&self, _message: &str) {}
|
||||
|
||||
fn sol_invoke_signed(
|
||||
&self,
|
||||
_instruction: &Instruction,
|
||||
_account_infos: &[AccountInfo],
|
||||
_signers_seeds: &[&[&[u8]]],
|
||||
) -> ProgramResult {
|
||||
Err(ProgramError::Custom(42)) // Not supported
|
||||
}
|
||||
|
||||
fn sol_get_clock_sysvar(&self, _var_addr: *mut u8) -> u64 {
|
||||
program_error::UNSUPPORTED_SYSVAR
|
||||
}
|
||||
|
||||
fn sol_get_epoch_schedule_sysvar(&self, _var_addr: *mut u8) -> u64 {
|
||||
program_error::UNSUPPORTED_SYSVAR
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn sol_get_fees_sysvar(&self, _var_addr: *mut u8) -> u64 {
|
||||
program_error::UNSUPPORTED_SYSVAR
|
||||
}
|
||||
|
||||
fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
|
||||
unsafe {
|
||||
*(var_addr as *mut _ as *mut Rent) = Rent::default();
|
||||
}
|
||||
solana_program::entrypoint::SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
fn do_process_instruction(
|
||||
instruction: Instruction,
|
||||
accounts: Vec<&mut SolanaAccount>,
|
||||
) -> ProgramResult {
|
||||
{
|
||||
use std::sync::Once;
|
||||
static ONCE: Once = Once::new();
|
||||
|
||||
ONCE.call_once(|| {
|
||||
solana_sdk::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
|
||||
});
|
||||
}
|
||||
|
||||
let mut meta = instruction
|
||||
.accounts
|
||||
.iter()
|
||||
|
@ -1072,6 +1183,53 @@ mod tests {
|
|||
assert_eq!(mint.freeze_authority, COption::Some(owner_key));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_initialize_mint2() {
|
||||
let program_id = crate::id();
|
||||
let owner_key = Pubkey::new_unique();
|
||||
let mint_key = Pubkey::new_unique();
|
||||
let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
|
||||
let mint2_key = Pubkey::new_unique();
|
||||
let mut mint2_account =
|
||||
SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
|
||||
|
||||
// mint is not rent exempt
|
||||
assert_eq!(
|
||||
Err(TokenError::NotRentExempt.into()),
|
||||
do_process_instruction(
|
||||
initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
|
||||
vec![&mut mint_account]
|
||||
)
|
||||
);
|
||||
|
||||
mint_account.lamports = mint_minimum_balance();
|
||||
|
||||
// create new mint
|
||||
do_process_instruction(
|
||||
initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
|
||||
vec![&mut mint_account],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// create twice
|
||||
assert_eq!(
|
||||
Err(TokenError::AlreadyInUse.into()),
|
||||
do_process_instruction(
|
||||
initialize_mint2(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
|
||||
vec![&mut mint_account]
|
||||
)
|
||||
);
|
||||
|
||||
// create another mint that can freeze
|
||||
do_process_instruction(
|
||||
initialize_mint2(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
|
||||
vec![&mut mint2_account],
|
||||
)
|
||||
.unwrap();
|
||||
let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
|
||||
assert_eq!(mint.freeze_authority, COption::Some(owner_key));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_initialize_mint_account() {
|
||||
let program_id = crate::id();
|
||||
|
@ -4216,6 +4374,17 @@ mod tests {
|
|||
],
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
Err(TokenError::NotRentExempt.into()),
|
||||
do_process_instruction(
|
||||
initialize_multisig2(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
|
||||
vec![
|
||||
&mut multisig_account,
|
||||
&mut rent_sysvar,
|
||||
&mut account_info_iter.next().unwrap(),
|
||||
],
|
||||
)
|
||||
);
|
||||
|
||||
multisig_account.lamports = multisig_minimum_balance();
|
||||
|
||||
|
@ -5806,7 +5975,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_initialize_account2() {
|
||||
fn test_initialize_account2_and_3() {
|
||||
let program_id = crate::id();
|
||||
let account_key = Pubkey::new_unique();
|
||||
let mut account_account = SolanaAccount::new(
|
||||
|
@ -5819,6 +5988,11 @@ mod tests {
|
|||
Account::get_packed_len(),
|
||||
&program_id,
|
||||
);
|
||||
let mut account3_account = SolanaAccount::new(
|
||||
account_minimum_balance(),
|
||||
Account::get_packed_len(),
|
||||
&program_id,
|
||||
);
|
||||
let owner_key = Pubkey::new_unique();
|
||||
let mut owner_account = SolanaAccount::default();
|
||||
let mint_key = Pubkey::new_unique();
|
||||
|
@ -5851,6 +6025,14 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
assert_eq!(account_account, account2_account);
|
||||
|
||||
do_process_instruction(
|
||||
initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
|
||||
vec![&mut account3_account, &mut mint_account, &mut rent_sysvar],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(account_account, account3_account);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in New Issue