Skip to content

Commit e388281

Browse files
authored
[solana] Fix guardian set owner bug (#1214)
* Fix the owner bug * Remove seeds in context
1 parent c1cc712 commit e388281

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

target_chains/solana/programs/pyth-solana-receiver/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub enum ReceiverError {
3030
InsufficientFunds,
3131
#[msg("The number of guardian signatures is below the minimum")]
3232
InsufficientGuardianSignatures,
33+
#[msg("The Guardian Set account doesn't match the PDA derivation")]
34+
InvalidGuardianSetPda,
3335
// Wormhole errors
3436
#[msg("Invalid VAA version")]
3537
InvalidVaaVersion,

target_chains/solana/programs/pyth-solana-receiver/src/lib.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,17 @@ pub mod pyth_solana_receiver {
116116
ctx: Context<PostUpdatesAtomic>,
117117
params: PostUpdatesAtomicParams,
118118
) -> Result<()> {
119+
let config = &ctx.accounts.config;
120+
let guardian_set =
121+
deserialize_guardian_set_checked(&ctx.accounts.guardian_set, &config.wormhole)?;
122+
119123
// This section is borrowed from https://github.com/wormhole-foundation/wormhole/blob/wen/solana-rewrite/solana/programs/core-bridge/src/processor/parse_and_verify_vaa/verify_encoded_vaa_v1.rs#L59
120124
let vaa = Vaa::parse(&params.vaa).map_err(|_| ReceiverError::DeserializeVaaFailed)?;
121125
// Must be V1.
122126
require_eq!(vaa.version(), 1, ReceiverError::InvalidVaaVersion);
123127

124128
// Make sure the encoded guardian set index agrees with the guardian set account's index.
125-
let guardian_set = ctx.accounts.guardian_set.inner();
129+
let guardian_set = guardian_set.inner();
126130
require_eq!(
127131
vaa.guardian_set_index(),
128132
guardian_set.index,
@@ -156,7 +160,6 @@ pub mod pyth_solana_receiver {
156160
}
157161
// End borrowed section
158162

159-
let config = &ctx.accounts.config;
160163
let payer = &ctx.accounts.payer;
161164
let treasury = &ctx.accounts.treasury;
162165
let price_update_account = &mut ctx.accounts.price_update_account;
@@ -275,15 +278,11 @@ pub struct PostUpdates<'info> {
275278
pub struct PostUpdatesAtomic<'info> {
276279
#[account(mut)]
277280
pub payer: Signer<'info>,
281+
/// CHECK: We can't use AccountVariant::<GuardianSet> here because its owner is hardcoded as the "official" Wormhole program and we want to get the wormhole address from the config.
282+
/// Instead we do the same steps in deserialize_guardian_set_checked.
278283
#[account(
279-
seeds = [
280-
GuardianSet::SEED_PREFIX,
281-
guardian_set.inner().index.to_be_bytes().as_ref()
282-
],
283-
seeds::program = config.wormhole,
284-
bump,
285284
owner = config.wormhole)]
286-
pub guardian_set: Account<'info, AccountVariant<GuardianSet>>,
285+
pub guardian_set: AccountInfo<'info>,
287286
#[account(seeds = [CONFIG_SEED.as_ref()], bump)]
288287
pub config: Account<'info, Config>,
289288
#[account(mut, seeds = [TREASURY_SEED.as_ref()], bump)]
@@ -364,6 +363,32 @@ impl crate::accounts::Governance {
364363
}
365364
}
366365

366+
fn deserialize_guardian_set_checked(
367+
account_info: &AccountInfo<'_>,
368+
wormhole: &Pubkey,
369+
) -> Result<AccountVariant<GuardianSet>> {
370+
let mut guardian_set_data: &[u8] = &account_info.try_borrow_data()?;
371+
let guardian_set =
372+
AccountVariant::<GuardianSet>::try_deserialize_unchecked(&mut guardian_set_data)?;
373+
374+
let expected_address = Pubkey::find_program_address(
375+
&[
376+
GuardianSet::SEED_PREFIX,
377+
guardian_set.inner().index.to_be_bytes().as_ref(),
378+
],
379+
wormhole,
380+
)
381+
.0;
382+
383+
require!(
384+
expected_address == *account_info.key,
385+
ReceiverError::InvalidGuardianSetPda
386+
);
387+
388+
Ok(guardian_set)
389+
}
390+
391+
367392
struct VaaComponents {
368393
verification_level: VerificationLevel,
369394
emitter_address: [u8; 32],

0 commit comments

Comments
 (0)