11//! Program state processor
22
3- use mpl_token_metadata:: instruction:: { create_metadata_accounts_v3, update_metadata_accounts_v2} ;
4- use mpl_token_metadata:: state:: DataV2 ;
5-
63use {
74 crate :: {
85 error:: StakePoolError ,
1613 AUTHORITY_DEPOSIT , AUTHORITY_WITHDRAW , MINIMUM_ACTIVE_STAKE , TRANSIENT_STAKE_SEED_PREFIX ,
1714 } ,
1815 borsh:: { BorshDeserialize , BorshSerialize } ,
16+ mpl_token_metadata:: {
17+ instruction:: { create_metadata_accounts_v3, update_metadata_accounts_v2} ,
18+ pda:: find_metadata_account,
19+ state:: DataV2 ,
20+ } ,
1921 num_traits:: FromPrimitive ,
2022 solana_program:: {
2123 account_info:: { next_account_info, AccountInfo } ,
@@ -92,6 +94,19 @@ fn check_transient_stake_address(
9294 }
9395}
9496
97+ /// Check mpl metadata account address for the pool mint
98+ fn check_mpl_metadata_account_address (
99+ metadata_address : & Pubkey ,
100+ pool_mint : & Pubkey ,
101+ ) -> Result < ( ) , ProgramError > {
102+ let ( metadata_account_pubkey, _) = find_metadata_account ( pool_mint) ;
103+ if metadata_account_pubkey != * metadata_address {
104+ Err ( StakePoolError :: InvalidMetadataAccount . into ( ) )
105+ } else {
106+ Ok ( ( ) )
107+ }
108+ }
109+
95110/// Check system program address
96111fn check_system_program ( program_id : & Pubkey ) -> Result < ( ) , ProgramError > {
97112 if * program_id != system_program:: id ( ) {
@@ -120,6 +135,34 @@ fn check_stake_program(program_id: &Pubkey) -> Result<(), ProgramError> {
120135 }
121136}
122137
138+ /// Check mpl metadata program
139+ fn check_mpl_metadata_program ( program_id : & Pubkey ) -> Result < ( ) , ProgramError > {
140+ if * program_id != mpl_token_metadata:: id ( ) {
141+ msg ! (
142+ "Expected mpl metadata program {}, received {}" ,
143+ mpl_token_metadata:: id( ) ,
144+ program_id
145+ ) ;
146+ Err ( ProgramError :: IncorrectProgramId )
147+ } else {
148+ Ok ( ( ) )
149+ }
150+ }
151+
152+ /// Check rent sysvar correctness
153+ fn check_rent_sysvar ( sysvar_key : & Pubkey ) -> Result < ( ) , ProgramError > {
154+ if * sysvar_key != solana_program:: sysvar:: rent:: id ( ) {
155+ msg ! (
156+ "Expected rent sysvar {}, received {}" ,
157+ solana_program:: sysvar:: rent:: id( ) ,
158+ sysvar_key
159+ ) ;
160+ Err ( ProgramError :: InvalidArgument )
161+ } else {
162+ Ok ( ( ) )
163+ }
164+ }
165+
123166/// Check account owner is the given program
124167fn check_account_owner (
125168 account_info : & AccountInfo ,
@@ -2698,8 +2741,13 @@ impl Processor {
26982741 let system_program_info = next_account_info ( account_info_iter) ?;
26992742 let rent_sysvar_info = next_account_info ( account_info_iter) ?;
27002743
2744+ check_system_program ( system_program_info. key ) ?;
2745+ check_rent_sysvar ( rent_sysvar_info. key ) ?;
2746+ check_account_owner ( payer_info, & system_program:: id ( ) ) ?;
27012747 check_account_owner ( stake_pool_info, program_id) ?;
2702- let mut stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool_info. data . borrow ( ) ) ?;
2748+ check_mpl_metadata_program ( mpl_token_metadata_program_info. key ) ?;
2749+
2750+ let stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool_info. data . borrow ( ) ) ?;
27032751 if !stake_pool. is_valid ( ) {
27042752 return Err ( StakePoolError :: InvalidState . into ( ) ) ;
27052753 }
@@ -2711,21 +2759,18 @@ impl Processor {
27112759 stake_pool_info. key ,
27122760 ) ?;
27132761 stake_pool. check_mint ( pool_mint_info) ?;
2762+ check_mpl_metadata_account_address ( metadata_info. key , & stake_pool. pool_mint ) ?;
27142763
27152764 // Token mint authority for stake-pool token is stake-pool withdraw authority
27162765 let token_mint_authority = withdraw_authority_info;
2717- let mint_key = pool_mint_info. key . clone ( ) ;
2718- let token_mint_authority_key = token_mint_authority. key . clone ( ) ;
2719-
2720- let metadata_program_id = mpl_token_metadata_program_info. key . clone ( ) ;
27212766
27222767 let new_metadata_instruction = create_metadata_accounts_v3 (
2723- metadata_program_id ,
2724- metadata_info. key . clone ( ) ,
2725- mint_key ,
2726- token_mint_authority_key ,
2727- payer_info. key . clone ( ) ,
2728- token_mint_authority_key ,
2768+ * mpl_token_metadata_program_info . key ,
2769+ * metadata_info. key ,
2770+ * pool_mint_info . key ,
2771+ * token_mint_authority . key ,
2772+ * payer_info. key ,
2773+ * token_mint_authority . key ,
27292774 name,
27302775 symbol,
27312776 uri,
@@ -2782,7 +2827,10 @@ impl Processor {
27822827 let mpl_token_metadata_program_info = next_account_info ( account_info_iter) ?;
27832828
27842829 check_account_owner ( stake_pool_info, program_id) ?;
2785- let mut stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool_info. data . borrow ( ) ) ?;
2830+
2831+ check_mpl_metadata_program ( mpl_token_metadata_program_info. key ) ?;
2832+
2833+ let stake_pool = try_from_slice_unchecked :: < StakePool > ( & stake_pool_info. data . borrow ( ) ) ?;
27862834 if !stake_pool. is_valid ( ) {
27872835 return Err ( StakePoolError :: InvalidState . into ( ) ) ;
27882836 }
@@ -2793,17 +2841,15 @@ impl Processor {
27932841 program_id,
27942842 stake_pool_info. key ,
27952843 ) ?;
2844+ check_mpl_metadata_account_address ( metadata_info. key , & stake_pool. pool_mint ) ?;
27962845
27972846 // Token mint authority for stake-pool token is withdraw authority only
27982847 let token_mint_authority = withdraw_authority_info;
2799- let token_mint_authority_key = token_mint_authority. key . clone ( ) ;
2800-
2801- let metadata_program_id = mpl_token_metadata_program_info. key . clone ( ) ;
28022848
28032849 let update_metadata_accounts_instruction = update_metadata_accounts_v2 (
2804- metadata_program_id ,
2805- metadata_info. key . clone ( ) ,
2806- token_mint_authority_key ,
2850+ * mpl_token_metadata_program_info . key ,
2851+ * metadata_info. key ,
2852+ * token_mint_authority . key ,
28072853 None ,
28082854 Some ( DataV2 {
28092855 name,
@@ -3081,11 +3127,11 @@ impl Processor {
30813127 Self :: process_withdraw_sol ( program_id, accounts, pool_tokens)
30823128 }
30833129 StakePoolInstruction :: CreateTokenMetadata { name, symbol, uri } => {
3084- msg ! ( "Instruction: Create token metadata " ) ;
3130+ msg ! ( "Instruction: CreateTokenMetadata " ) ;
30853131 Self :: process_create_pool_token_metadata ( program_id, accounts, name, symbol, uri)
30863132 }
30873133 StakePoolInstruction :: UpdateTokenMetadata { name, symbol, uri } => {
3088- msg ! ( "Instruction: Create token metadata " ) ;
3134+ msg ! ( "Instruction: UpdateTokenMetadata " ) ;
30893135 Self :: process_update_pool_token_metadata ( program_id, accounts, name, symbol, uri)
30903136 }
30913137 }
@@ -3136,6 +3182,7 @@ impl PrintProgramError for StakePoolError {
31363182 StakePoolError :: TransientAccountInUse => msg ! ( "Error: Provided validator stake account already has a transient stake account in use" ) ,
31373183 StakePoolError :: InvalidSolWithdrawAuthority => msg ! ( "Error: Provided sol withdraw authority does not match the program's" ) ,
31383184 StakePoolError :: SolWithdrawalTooLarge => msg ! ( "Error: Too much SOL withdrawn from the stake pool's reserve account" ) ,
3185+ StakePoolError :: InvalidMetadataAccount => msg ! ( "Error: Metadata account derived from pool mint account does not match the one passed to program" )
31393186 }
31403187 }
31413188}
0 commit comments