@@ -17,19 +17,21 @@ use {
17
17
} ,
18
18
OracleError ,
19
19
} ,
20
+ bytemuck:: {
21
+ Pod ,
22
+ Zeroable ,
23
+ } ,
20
24
num_traits:: FromPrimitive ,
21
25
solana_program:: {
22
26
account_info:: AccountInfo ,
23
- bpf_loader_upgradeable:: {
24
- self ,
25
- UpgradeableLoaderState ,
26
- } ,
27
+ bpf_loader_upgradeable,
27
28
program:: invoke,
28
29
program_error:: ProgramError ,
29
30
pubkey:: Pubkey ,
30
31
system_instruction:: transfer,
31
32
sysvar:: rent:: Rent ,
32
33
} ,
34
+ std:: cell:: Ref ,
33
35
} ;
34
36
35
37
@@ -210,6 +212,23 @@ pub fn is_component_update(cmd_args: &UpdPriceArgs) -> Result<bool, OracleError>
210
212
}
211
213
}
212
214
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
+ }
213
232
214
233
/// Check that `programdata_account` is actually the buffer for `program_id`.
215
234
/// Check that the authority in `programdata_account` matches `upgrade_authority_account`.
@@ -218,9 +237,8 @@ pub fn check_is_upgrade_authority_for_program(
218
237
programdata_account : & AccountInfo ,
219
238
program_id : & Pubkey ,
220
239
) -> 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) ?;
224
242
225
243
// 1. programdata_account is actually this program's buffer
226
244
let ( programdata_address, _) =
@@ -233,18 +251,15 @@ pub fn check_is_upgrade_authority_for_program(
233
251
234
252
235
253
// 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
+
248
263
Ok ( ( ) )
249
264
}
250
265
0 commit comments