@@ -17,19 +17,21 @@ use {
1717 } ,
1818 OracleError ,
1919 } ,
20+ bytemuck:: {
21+ Pod ,
22+ Zeroable ,
23+ } ,
2024 num_traits:: FromPrimitive ,
2125 solana_program:: {
2226 account_info:: AccountInfo ,
23- bpf_loader_upgradeable:: {
24- self ,
25- UpgradeableLoaderState ,
26- } ,
27+ bpf_loader_upgradeable,
2728 program:: invoke,
2829 program_error:: ProgramError ,
2930 pubkey:: Pubkey ,
3031 system_instruction:: transfer,
3132 sysvar:: rent:: Rent ,
3233 } ,
34+ std:: cell:: Ref ,
3335} ;
3436
3537
@@ -210,6 +212,23 @@ pub fn is_component_update(cmd_args: &UpdPriceArgs) -> Result<bool, OracleError>
210212 }
211213}
212214
215+ /// This struct represents UpgradeableLoaderState from bpf-upgradable-loader.
216+ /// Solana uses bincode for the struct. However the bincode crate is too big the space we have onchain,
217+ /// therefore we will use bytemuck for deserialization
218+ #[ repr( C ) ]
219+ #[ derive( Pod , Zeroable , Copy , Clone ) ]
220+ struct ProgramdataAccount {
221+ /// 3 is the variant for programdata
222+ pub account_type : u32 ,
223+ /// Space for slot of last upgrade (we don't use this field)
224+ pub slot : [ u32 ; 2 ] ,
225+ /// 0 if immutable, 1 if has upgrade authority
226+ pub has_upgrade_authority : u8 ,
227+ /// Upgrade authority of the program
228+ pub upgrade_authority : Pubkey ,
229+ /// Unused field needed for this struct to be Pod
230+ pub unused : [ u8 ; 3 ] ,
231+ }
213232
214233/// Check that `programdata_account` is actually the buffer for `program_id`.
215234/// Check that the authority in `programdata_account` matches `upgrade_authority_account`.
@@ -218,9 +237,8 @@ pub fn check_is_upgrade_authority_for_program(
218237 programdata_account : & AccountInfo ,
219238 program_id : & Pubkey ,
220239) -> Result < ( ) , ProgramError > {
221- let programdata_deserialized: UpgradeableLoaderState =
222- bincode:: deserialize ( & programdata_account. try_borrow_data ( ) ?)
223- . map_err ( |_| OracleError :: DeserializationError ) ?;
240+ let programdata_deserialized: Ref < ProgramdataAccount > =
241+ load_account_as :: < ProgramdataAccount > ( programdata_account) ?;
224242
225243 // 1. programdata_account is actually this program's buffer
226244 let ( programdata_address, _) =
@@ -233,18 +251,15 @@ pub fn check_is_upgrade_authority_for_program(
233251
234252
235253 // 2. upgrade_authority_account is actually the authority inside programdata_account
236- if let UpgradeableLoaderState :: ProgramData {
237- slot : _,
238- upgrade_authority_address : Some ( upgrade_authority_key) ,
239- } = programdata_deserialized
240- {
241- pyth_assert (
242- upgrade_authority_key. eq ( upgrade_authority_account. key ) ,
243- OracleError :: InvalidUpgradeAuthority . into ( ) ,
244- ) ?;
245- } else {
246- return Err ( OracleError :: InvalidUpgradeAuthority . into ( ) ) ;
247- }
254+ pyth_assert (
255+ programdata_deserialized
256+ . upgrade_authority
257+ . eq ( upgrade_authority_account. key )
258+ && programdata_deserialized. account_type == 3
259+ && programdata_deserialized. has_upgrade_authority == 1 ,
260+ OracleError :: InvalidUpgradeAuthority . into ( ) ,
261+ ) ?;
262+
248263 Ok ( ( ) )
249264}
250265
0 commit comments