Skip to content

Commit ddf0463

Browse files
authored
fix: solana audit 3 (#1334)
* Audit 3 * Go * Move it before sig verification * Comment
1 parent e0f94ee commit ddf0463

File tree

4 files changed

+118
-8
lines changed

4 files changed

+118
-8
lines changed

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use {
3838
state::GuardianSet,
3939
},
4040
wormhole_raw_vaas::{
41+
utils::quorum,
4142
GuardianSetSig,
4243
Vaa,
4344
},
@@ -52,6 +53,7 @@ declare_id!(pyth_solana_receiver_state::ID);
5253
pub mod pyth_solana_receiver {
5354
use super::*;
5455

56+
5557
pub fn initialize(ctx: Context<Initialize>, initial_config: Config) -> Result<()> {
5658
require!(
5759
initial_config.minimum_signatures > 0,
@@ -71,6 +73,12 @@ pub mod pyth_solana_receiver {
7173
Ok(())
7274
}
7375

76+
pub fn cancel_governance_authority_transfer(ctx: Context<Governance>) -> Result<()> {
77+
let config = &mut ctx.accounts.config;
78+
config.target_governance_authority = None;
79+
Ok(())
80+
}
81+
7482
pub fn accept_governance_authority_transfer(
7583
ctx: Context<AcceptGovernanceAuthorityTransfer>,
7684
) -> Result<()> {
@@ -82,6 +90,7 @@ pub mod pyth_solana_receiver {
8290
Ok(())
8391
}
8492

93+
8594
pub fn set_data_sources(
8695
ctx: Context<Governance>,
8796
valid_data_sources: Vec<DataSource>,
@@ -142,11 +151,19 @@ pub mod pyth_solana_receiver {
142151
);
143152

144153
let guardian_keys = &guardian_set.keys;
154+
let quorum = quorum(guardian_keys.len());
145155
require_gte!(
146156
vaa.signature_count(),
147157
config.minimum_signatures,
148158
ReceiverError::InsufficientGuardianSignatures
149159
);
160+
let verification_level = if usize::from(vaa.signature_count()) >= quorum {
161+
VerificationLevel::Full
162+
} else {
163+
VerificationLevel::Partial {
164+
num_signatures: vaa.signature_count(),
165+
}
166+
};
150167

151168
// Generate the same message hash (using keccak) that the Guardians used to generate their
152169
// signatures. This message hash will be hashed again to produce the digest for
@@ -178,11 +195,9 @@ pub mod pyth_solana_receiver {
178195
let price_update_account = &mut ctx.accounts.price_update_account;
179196

180197
let vaa_components = VaaComponents {
181-
verification_level: VerificationLevel::Partial {
182-
num_signatures: vaa.signature_count(),
183-
},
184-
emitter_address: vaa.body().emitter_address(),
185-
emitter_chain: vaa.body().emitter_chain(),
198+
verification_level,
199+
emitter_address: vaa.body().emitter_address(),
200+
emitter_chain: vaa.body().emitter_chain(),
186201
};
187202

188203
post_price_update_from_vaa(

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,17 @@ impl instruction::RequestGovernanceAuthorityTransfer {
238238
}
239239
}
240240

241+
impl instruction::CancelGovernanceAuthorityTransfer {
242+
pub fn populate(payer: Pubkey) -> Instruction {
243+
let governance_accounts = accounts::Governance::populate(payer).to_account_metas(None);
244+
Instruction {
245+
program_id: ID,
246+
accounts: governance_accounts,
247+
data: instruction::CancelGovernanceAuthorityTransfer.data(),
248+
}
249+
}
250+
}
251+
241252
impl instruction::AcceptGovernanceAuthorityTransfer {
242253
pub fn populate(payer: Pubkey) -> Instruction {
243254
let governance_accounts =

target_chains/solana/programs/pyth-solana-receiver/tests/test_governance.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use {
99
error::ReceiverError,
1010
instruction::{
1111
AcceptGovernanceAuthorityTransfer,
12+
CancelGovernanceAuthorityTransfer,
1213
RequestGovernanceAuthorityTransfer,
1314
SetDataSources,
1415
SetFee,
@@ -372,6 +373,81 @@ async fn test_governance() {
372373
into_transaction_error(ReceiverError::TargetGovernanceAuthorityMismatch)
373374
);
374375

376+
377+
// Undo the request
378+
program_simulator
379+
.process_ix_with_default_compute_limit(
380+
CancelGovernanceAuthorityTransfer::populate(governance_authority.pubkey()),
381+
&vec![&governance_authority],
382+
None,
383+
)
384+
.await
385+
.unwrap();
386+
387+
current_config = program_simulator
388+
.get_anchor_account_data::<Config>(get_config_address())
389+
.await
390+
.unwrap();
391+
assert_eq!(
392+
current_config.governance_authority,
393+
initial_config.governance_authority
394+
);
395+
assert_eq!(current_config.target_governance_authority, None);
396+
assert_eq!(current_config.wormhole, new_config.wormhole);
397+
assert_eq!(
398+
current_config.valid_data_sources,
399+
new_config.valid_data_sources
400+
);
401+
assert_eq!(
402+
current_config.single_update_fee_in_lamports,
403+
new_config.single_update_fee_in_lamports
404+
);
405+
assert_eq!(
406+
current_config.minimum_signatures,
407+
new_config.minimum_signatures
408+
);
409+
410+
411+
// Redo the request
412+
program_simulator
413+
.process_ix_with_default_compute_limit(
414+
RequestGovernanceAuthorityTransfer::populate(
415+
governance_authority.pubkey(),
416+
new_governance_authority.pubkey(),
417+
),
418+
&vec![&governance_authority],
419+
None,
420+
)
421+
.await
422+
.unwrap();
423+
424+
current_config = program_simulator
425+
.get_anchor_account_data::<Config>(get_config_address())
426+
.await
427+
.unwrap();
428+
assert_eq!(
429+
current_config.governance_authority,
430+
initial_config.governance_authority
431+
);
432+
assert_eq!(
433+
current_config.target_governance_authority,
434+
Some(new_governance_authority.pubkey())
435+
);
436+
assert_eq!(current_config.wormhole, new_config.wormhole);
437+
assert_eq!(
438+
current_config.valid_data_sources,
439+
new_config.valid_data_sources
440+
);
441+
assert_eq!(
442+
current_config.single_update_fee_in_lamports,
443+
new_config.single_update_fee_in_lamports
444+
);
445+
assert_eq!(
446+
current_config.minimum_signatures,
447+
new_config.minimum_signatures
448+
);
449+
450+
375451
// New authority can accept
376452
program_simulator
377453
.process_ix_with_default_compute_limit(

target_chains/solana/programs/pyth-solana-receiver/tests/test_post_price_update_from_vaa.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use {
3434
create_accumulator_message,
3535
create_dummy_price_feed_message,
3636
create_dummy_twap_message,
37+
trim_vaa_signatures,
3738
DEFAULT_DATA_SOURCE,
3839
SECONDARY_DATA_SOURCE,
3940
},
@@ -348,7 +349,7 @@ async fn test_post_price_update_from_vaa() {
348349
assert_eq!(price_update_account.write_authority, poster.pubkey());
349350
assert_eq!(
350351
price_update_account.verification_level,
351-
VerificationLevel::Partial { num_signatures: 13 }
352+
VerificationLevel::Full
352353
);
353354
assert_eq!(
354355
Message::PriceFeedMessage(price_update_account.price_message),
@@ -366,6 +367,12 @@ async fn test_post_price_update_from_vaa() {
366367
.await
367368
.unwrap();
368369

370+
// Change number of signatures too
371+
let vaa = serde_wormhole::to_vec(&trim_vaa_signatures(
372+
serde_wormhole::from_slice(&vaa).unwrap(),
373+
12,
374+
))
375+
.unwrap();
369376

370377
assert_eq!(
371378
program_simulator
@@ -395,14 +402,15 @@ async fn test_post_price_update_from_vaa() {
395402
)
396403
.await;
397404

405+
// Transaction failed, so the account should not have been updated
398406
price_update_account = program_simulator
399407
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
400408
.await
401409
.unwrap();
402410
assert_eq!(price_update_account.write_authority, poster.pubkey());
403411
assert_eq!(
404412
price_update_account.verification_level,
405-
VerificationLevel::Partial { num_signatures: 13 }
413+
VerificationLevel::Full
406414
);
407415
assert_eq!(
408416
Message::PriceFeedMessage(price_update_account.price_message),
@@ -455,7 +463,7 @@ async fn test_post_price_update_from_vaa() {
455463
assert_eq!(price_update_account.write_authority, poster.pubkey());
456464
assert_eq!(
457465
price_update_account.verification_level,
458-
VerificationLevel::Partial { num_signatures: 13 },
466+
VerificationLevel::Partial { num_signatures: 12 }
459467
);
460468
assert_eq!(
461469
Message::PriceFeedMessage(price_update_account.price_message),

0 commit comments

Comments
 (0)