Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 44ad2ff

Browse files
committed
Add InitializeMint2/InitializeMultisig2/InitializeAccount3 instructions
1 parent b4b9763 commit 44ad2ff

File tree

3 files changed

+390
-13
lines changed

3 files changed

+390
-13
lines changed

token/program/src/instruction.rs

Lines changed: 196 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,42 @@ pub enum TokenInstruction {
373373
///
374374
/// 0. `[writable]` The native token account to sync with its underlying lamports.
375375
SyncNative,
376+
/// Like InitializeAccount2, but does not require the Rent sysvar to be provided
377+
///
378+
/// Accounts expected by this instruction:
379+
///
380+
/// 0. `[writable]` The account to initialize.
381+
/// 1. `[]` The mint this account will be associated with.
382+
InitializeAccount3 {
383+
/// The new account's owner/multisignature.
384+
owner: Pubkey,
385+
},
386+
/// Like InitializeMultisig, but does not require the Rent sysvar to be provided
387+
///
388+
/// Accounts expected by this instruction:
389+
///
390+
/// 0. `[writable]` The multisignature account to initialize.
391+
/// 1. ..1+N. `[]` The signer accounts, must equal to N where 1 <= N <=
392+
/// 11.
393+
InitializeMultisig2 {
394+
/// The number of signers (M) required to validate this multisignature
395+
/// account.
396+
m: u8,
397+
},
398+
/// Like InitializeMint, but does not require the Rent sysvar to be provided
399+
///
400+
/// Accounts expected by this instruction:
401+
///
402+
/// 0. `[writable]` The mint to initialize.
403+
///
404+
InitializeMint2 {
405+
/// Number of base 10 digits to the right of the decimal place.
406+
decimals: u8,
407+
/// The authority/multisignature to mint tokens.
408+
mint_authority: Pubkey,
409+
/// The freeze authority/multisignature of the mint.
410+
freeze_authority: COption<Pubkey>,
411+
},
376412
}
377413
impl TokenInstruction {
378414
/// Unpacks a byte buffer into a [TokenInstruction](enum.TokenInstruction.html).
@@ -475,7 +511,24 @@ impl TokenInstruction {
475511
Self::InitializeAccount2 { owner }
476512
}
477513
17 => Self::SyncNative,
478-
514+
18 => {
515+
let (owner, _rest) = Self::unpack_pubkey(rest)?;
516+
Self::InitializeAccount3 { owner }
517+
}
518+
19 => {
519+
let &m = rest.get(0).ok_or(InvalidInstruction)?;
520+
Self::InitializeMultisig2 { m }
521+
}
522+
20 => {
523+
let (&decimals, rest) = rest.split_first().ok_or(InvalidInstruction)?;
524+
let (mint_authority, rest) = Self::unpack_pubkey(rest)?;
525+
let (freeze_authority, _rest) = Self::unpack_pubkey_option(rest)?;
526+
Self::InitializeMint2 {
527+
mint_authority,
528+
freeze_authority,
529+
decimals,
530+
}
531+
}
479532
_ => return Err(TokenError::InvalidInstruction.into()),
480533
})
481534
}
@@ -554,6 +607,24 @@ impl TokenInstruction {
554607
&Self::SyncNative => {
555608
buf.push(17);
556609
}
610+
&Self::InitializeAccount3 { owner } => {
611+
buf.push(18);
612+
buf.extend_from_slice(owner.as_ref());
613+
}
614+
&Self::InitializeMultisig2 { m } => {
615+
buf.push(19);
616+
buf.push(m);
617+
}
618+
&Self::InitializeMint2 {
619+
ref mint_authority,
620+
ref freeze_authority,
621+
decimals,
622+
} => {
623+
buf.push(20);
624+
buf.push(decimals);
625+
buf.extend_from_slice(mint_authority.as_ref());
626+
Self::pack_pubkey_option(freeze_authority, &mut buf);
627+
}
557628
};
558629
buf
559630
}
@@ -655,6 +726,32 @@ pub fn initialize_mint(
655726
})
656727
}
657728

729+
/// Creates a `InitializeMint2` instruction.
730+
pub fn initialize_mint2(
731+
token_program_id: &Pubkey,
732+
mint_pubkey: &Pubkey,
733+
mint_authority_pubkey: &Pubkey,
734+
freeze_authority_pubkey: Option<&Pubkey>,
735+
decimals: u8,
736+
) -> Result<Instruction, ProgramError> {
737+
check_program_account(token_program_id)?;
738+
let freeze_authority = freeze_authority_pubkey.cloned().into();
739+
let data = TokenInstruction::InitializeMint2 {
740+
mint_authority: *mint_authority_pubkey,
741+
freeze_authority,
742+
decimals,
743+
}
744+
.pack();
745+
746+
let accounts = vec![AccountMeta::new(*mint_pubkey, false)];
747+
748+
Ok(Instruction {
749+
program_id: *token_program_id,
750+
accounts,
751+
data,
752+
})
753+
}
754+
658755
/// Creates a `InitializeAccount` instruction.
659756
pub fn initialize_account(
660757
token_program_id: &Pubkey,
@@ -705,6 +802,31 @@ pub fn initialize_account2(
705802
})
706803
}
707804

805+
/// Creates a `InitializeAccount3` instruction.
806+
pub fn initialize_account3(
807+
token_program_id: &Pubkey,
808+
account_pubkey: &Pubkey,
809+
mint_pubkey: &Pubkey,
810+
owner_pubkey: &Pubkey,
811+
) -> Result<Instruction, ProgramError> {
812+
check_program_account(token_program_id)?;
813+
let data = TokenInstruction::InitializeAccount3 {
814+
owner: *owner_pubkey,
815+
}
816+
.pack();
817+
818+
let accounts = vec![
819+
AccountMeta::new(*account_pubkey, false),
820+
AccountMeta::new_readonly(*mint_pubkey, false),
821+
];
822+
823+
Ok(Instruction {
824+
program_id: *token_program_id,
825+
accounts,
826+
data,
827+
})
828+
}
829+
708830
/// Creates a `InitializeMultisig` instruction.
709831
pub fn initialize_multisig(
710832
token_program_id: &Pubkey,
@@ -735,6 +857,35 @@ pub fn initialize_multisig(
735857
})
736858
}
737859

860+
/// Creates a `InitializeMultisig2` instruction.
861+
pub fn initialize_multisig2(
862+
token_program_id: &Pubkey,
863+
multisig_pubkey: &Pubkey,
864+
signer_pubkeys: &[&Pubkey],
865+
m: u8,
866+
) -> Result<Instruction, ProgramError> {
867+
check_program_account(token_program_id)?;
868+
if !is_valid_signer_index(m as usize)
869+
|| !is_valid_signer_index(signer_pubkeys.len())
870+
|| m as usize > signer_pubkeys.len()
871+
{
872+
return Err(ProgramError::MissingRequiredSignature);
873+
}
874+
let data = TokenInstruction::InitializeMultisig2 { m }.pack();
875+
876+
let mut accounts = Vec::with_capacity(1 + 1 + signer_pubkeys.len());
877+
accounts.push(AccountMeta::new(*multisig_pubkey, false));
878+
for signer_pubkey in signer_pubkeys.iter() {
879+
accounts.push(AccountMeta::new_readonly(**signer_pubkey, false));
880+
}
881+
882+
Ok(Instruction {
883+
program_id: *token_program_id,
884+
accounts,
885+
data,
886+
})
887+
}
888+
738889
/// Creates a `Transfer` instruction.
739890
pub fn transfer(
740891
token_program_id: &Pubkey,
@@ -1323,5 +1474,49 @@ mod test {
13231474
assert_eq!(packed, expect);
13241475
let unpacked = TokenInstruction::unpack(&expect).unwrap();
13251476
assert_eq!(unpacked, check);
1477+
1478+
let check = TokenInstruction::InitializeAccount3 {
1479+
owner: Pubkey::new(&[2u8; 32]),
1480+
};
1481+
let packed = check.pack();
1482+
let mut expect = vec![18u8];
1483+
expect.extend_from_slice(&[2u8; 32]);
1484+
assert_eq!(packed, expect);
1485+
let unpacked = TokenInstruction::unpack(&expect).unwrap();
1486+
assert_eq!(unpacked, check);
1487+
1488+
let check = TokenInstruction::InitializeMultisig2 { m: 1 };
1489+
let packed = check.pack();
1490+
let expect = Vec::from([19u8, 1]);
1491+
assert_eq!(packed, expect);
1492+
let unpacked = TokenInstruction::unpack(&expect).unwrap();
1493+
assert_eq!(unpacked, check);
1494+
1495+
let check = TokenInstruction::InitializeMint2 {
1496+
decimals: 2,
1497+
mint_authority: Pubkey::new(&[1u8; 32]),
1498+
freeze_authority: COption::None,
1499+
};
1500+
let packed = check.pack();
1501+
let mut expect = Vec::from([20u8, 2]);
1502+
expect.extend_from_slice(&[1u8; 32]);
1503+
expect.extend_from_slice(&[0]);
1504+
assert_eq!(packed, expect);
1505+
let unpacked = TokenInstruction::unpack(&expect).unwrap();
1506+
assert_eq!(unpacked, check);
1507+
1508+
let check = TokenInstruction::InitializeMint2 {
1509+
decimals: 2,
1510+
mint_authority: Pubkey::new(&[2u8; 32]),
1511+
freeze_authority: COption::Some(Pubkey::new(&[3u8; 32])),
1512+
};
1513+
let packed = check.pack();
1514+
let mut expect = vec![20u8, 2];
1515+
expect.extend_from_slice(&[2u8; 32]);
1516+
expect.extend_from_slice(&[1]);
1517+
expect.extend_from_slice(&[3u8; 32]);
1518+
assert_eq!(packed, expect);
1519+
let unpacked = TokenInstruction::unpack(&expect).unwrap();
1520+
assert_eq!(unpacked, check);
13261521
}
13271522
}

token/program/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![deny(missing_docs)]
2-
#![forbid(unsafe_code)]
2+
#![cfg_attr(not(test), forbid(unsafe_code))]
33

44
//! An ERC20-like Token program for the Solana blockchain
55

0 commit comments

Comments
 (0)