Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Solana] Load balance treasury #1267

Merged
merged 22 commits into from
Feb 1, 2024
Merged
Prev Previous commit
Next Next commit
Keep adding errors
  • Loading branch information
guibescos committed Jan 30, 2024
commit b3510b02dc8b3e580a7ba727a074f899a023e5ec
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ pub enum ReceiverError {
// Wormhole signatures verification errors (from post_updates_atomic)
#[msg("An error occurred when deserializing the VAA.")]
DeserializeVaaFailed,
#[msg("The Guardian Set account doesn't match the PDA derivation")]
InvalidGuardianSetPda,
#[msg("The number of guardian signatures is below the minimum")]
InsufficientGuardianSignatures,
#[msg("Invalid VAA version")]
Expand All @@ -39,6 +37,10 @@ pub enum ReceiverError {
InvalidGuardianKeyRecovery,
#[msg("The guardian set account is owned by the wrong program")]
WrongGuardianSetOwner,
#[msg("The Guardian Set account doesn't match the PDA derivation")]
InvalidGuardianSetPda,
#[msg("The Guardian Set is expired")]
GuardianSetExpired,
// Governance errors
#[msg("The signer is not authorized to perform this governance action")]
GovernanceAuthorityMismatch,
Expand Down
6 changes: 6 additions & 0 deletions target_chains/solana/programs/pyth-solana-receiver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,12 @@ fn deserialize_guardian_set_checked(
ReceiverError::InvalidGuardianSetPda
);

let timestamp = Clock::get().map(Into::into)?;
require!(
guardian_set.inner().is_active(&timestamp),
ReceiverError::GuardianSetExpired
);

Ok(guardian_set)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use {
};

pub const DEFAULT_GUARDIAN_SET_INDEX: u32 = 0;
pub const WRONG_GUARDIAN_SET_INDEX: u32 = 1;

pub fn default_receiver_config() -> Config {
Config {
Expand All @@ -65,11 +66,20 @@ pub struct ProgramTestFixtures {
pub encoded_vaa_addresses: Vec<Pubkey>,
}

pub fn build_encoded_vaa_account_from_vaa(vaa: Vaa<&RawMessage>) -> Account {
pub fn build_encoded_vaa_account_from_vaa(
vaa: Vaa<&RawMessage>,
wrong_setup_option: WrongSetupOption,
) -> Account {
let encoded_vaa_data = (
<EncodedVaa as anchor_lang::Discriminator>::DISCRIMINATOR,
Header {
status: ProcessingStatus::Verified,
status: {
if matches!(wrong_setup_option, WrongSetupOption::UnverifiedEncodedVaa) {
ProcessingStatus::Writing
} else {
ProcessingStatus::Verified
}
},
write_authority: Pubkey::new_unique(),
version: 1,
},
Expand All @@ -87,9 +97,15 @@ pub fn build_encoded_vaa_account_from_vaa(vaa: Vaa<&RawMessage>) -> Account {
}
}

pub fn build_guardian_set_account() -> Account {
pub fn build_guardian_set_account(wrong_setup_option: WrongSetupOption) -> Account {
let guardian_set = GuardianSet {
index: DEFAULT_GUARDIAN_SET_INDEX,
index: {
if matches!(wrong_setup_option, WrongSetupOption::GuardianSetWrongIndex) {
WRONG_GUARDIAN_SET_INDEX
} else {
DEFAULT_GUARDIAN_SET_INDEX
}
},
keys: dummy_guardians()
.iter()
.map(|x| {
Expand All @@ -101,7 +117,14 @@ pub fn build_guardian_set_account() -> Account {
})
.collect::<Vec<[u8; 20]>>(),
creation_time: 0.into(),
expiration_time: 0.into(),
expiration_time: {
if matches!(wrong_setup_option, WrongSetupOption::GuardianSetExpired) {
1
} else {
0
}
}
.into(),
};

let guardian_set_data = (
Expand All @@ -119,24 +142,39 @@ pub fn build_guardian_set_account() -> Account {
rent_epoch: 0,
}
}

#[derive(Copy, Clone)]
pub enum WrongSetupOption {
None,
GuardianSetExpired,
GuardianSetWrongIndex,
UnverifiedEncodedVaa,
}

/**
* Setup to test the Pyth Receiver. The return values are a tuple composed of :
* - The program simulator, which is used to send transactions
* - The pubkeys of the encoded VAA accounts corresponding to the VAAs passed as argument, these accounts are prepopulated and can be used to test post_updates
*/
pub async fn setup_pyth_receiver(vaas: Vec<Vaa<&RawMessage>>) -> ProgramTestFixtures {
pub async fn setup_pyth_receiver(
vaas: Vec<Vaa<&RawMessage>>,
wrong_setup_option: WrongSetupOption,
) -> ProgramTestFixtures {
let mut program_test = ProgramTest::default();
program_test.add_program("pyth_solana_receiver", ID, None);

let mut encoded_vaa_addresses: Vec<Pubkey> = vec![];
for vaa in vaas {
let encoded_vaa_address = Pubkey::new_unique();
encoded_vaa_addresses.push(encoded_vaa_address);
program_test.add_account(encoded_vaa_address, build_encoded_vaa_account_from_vaa(vaa));
program_test.add_account(
encoded_vaa_address,
build_encoded_vaa_account_from_vaa(vaa, wrong_setup_option),
);
}
program_test.add_account(
get_guardian_set_address(BRIDGE_ID, DEFAULT_GUARDIAN_SET_INDEX),
build_guardian_set_account(),
build_guardian_set_account(wrong_setup_option),
);

let mut program_simulator = ProgramSimulator::start_from_program_test(program_test).await;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use {
crate::common::WrongSetupOption,
common::{
setup_pyth_receiver,
ProgramTestFixtures,
Expand Down Expand Up @@ -41,7 +42,11 @@ async fn test_post_updates() {
let ProgramTestFixtures {
mut program_simulator,
encoded_vaa_addresses,
} = setup_pyth_receiver(vec![serde_wormhole::from_slice(&vaa).unwrap()]).await;
} = setup_pyth_receiver(
vec![serde_wormhole::from_slice(&vaa).unwrap()],
WrongSetupOption::None,
)
.await;

let poster = program_simulator.get_funded_keypair().await.unwrap();
let price_update_keypair = Keypair::new();
Expand Down Expand Up @@ -110,7 +115,7 @@ async fn test_post_updates() {
}

#[tokio::test]
async fn test_post_updates_wrong_vaa() {
async fn test_post_updates_wrong_encoded_vaa_owner() {
let feed_1 = create_dummy_price_feed_message(100);
let feed_2 = create_dummy_price_feed_message(200);
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1, feed_2], false);
Expand All @@ -119,7 +124,11 @@ async fn test_post_updates_wrong_vaa() {
let ProgramTestFixtures {
mut program_simulator,
encoded_vaa_addresses: _,
} = setup_pyth_receiver(vec![serde_wormhole::from_slice(&vaa).unwrap()]).await;
} = setup_pyth_receiver(
vec![serde_wormhole::from_slice(&vaa).unwrap()],
WrongSetupOption::None,
)
.await;

let poster = program_simulator.get_funded_keypair().await.unwrap();
let price_update_keypair = Keypair::new();
Expand All @@ -142,3 +151,41 @@ async fn test_post_updates_wrong_vaa() {
into_transation_error(ReceiverError::WrongVaaOwner)
);
}

#[tokio::test]
async fn test_post_updates_wrong_setup() {
let feed_1 = create_dummy_price_feed_message(100);
let feed_2 = create_dummy_price_feed_message(200);
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1, feed_2], false);
let (vaa, merkle_price_updates) = deserialize_accumulator_update_data(message).unwrap();

let ProgramTestFixtures {
mut program_simulator,
encoded_vaa_addresses,
} = setup_pyth_receiver(
vec![serde_wormhole::from_slice(&vaa).unwrap()],
WrongSetupOption::UnverifiedEncodedVaa,
)
.await;

let poster = program_simulator.get_funded_keypair().await.unwrap();
let price_update_keypair = Keypair::new();

assert_eq!(
program_simulator
.process_ix(
PostUpdates::populate(
poster.pubkey(),
encoded_vaa_addresses[0],
price_update_keypair.pubkey(),
merkle_price_updates[0].clone(),
),
&vec![&poster, &price_update_keypair],
None,
)
.await
.unwrap_err()
.unwrap(),
into_transation_error(wormhole_core_bridge_solana::error::CoreBridgeError::UnverifiedVaa)
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use {
crate::common::DEFAULT_GUARDIAN_SET_INDEX,
crate::common::{
WrongSetupOption,
DEFAULT_GUARDIAN_SET_INDEX,
},
common::{
setup_pyth_receiver,
ProgramTestFixtures,
Expand Down Expand Up @@ -52,7 +55,7 @@ async fn test_post_updates_atomic() {
let ProgramTestFixtures {
mut program_simulator,
encoded_vaa_addresses: _,
} = setup_pyth_receiver(vec![]).await;
} = setup_pyth_receiver(vec![], WrongSetupOption::None).await;

let poster = program_simulator.get_funded_keypair().await.unwrap();
let price_update_keypair = Keypair::new();
Expand Down Expand Up @@ -134,7 +137,7 @@ async fn test_post_updates_atomic_wrong_vaa() {
let ProgramTestFixtures {
mut program_simulator,
encoded_vaa_addresses: _,
} = setup_pyth_receiver(vec![]).await;
} = setup_pyth_receiver(vec![], WrongSetupOption::None).await;

let poster = program_simulator.get_funded_keypair().await.unwrap();
let price_update_keypair = Keypair::new();
Expand Down Expand Up @@ -328,3 +331,64 @@ async fn test_post_updates_atomic_wrong_vaa() {
into_transation_error(ReceiverError::WrongGuardianSetOwner)
);
}


#[tokio::test]
async fn test_post_updates_atomic_wrong_setup() {
let feed_1 = create_dummy_price_feed_message(100);
let feed_2 = create_dummy_price_feed_message(200);
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1, feed_2], false);
let (vaa, merkle_price_updates) = deserialize_accumulator_update_data(message).unwrap();
let price_update_keypair = Keypair::new();

let ProgramTestFixtures {
mut program_simulator,
encoded_vaa_addresses: _,
} = setup_pyth_receiver(vec![], WrongSetupOption::GuardianSetWrongIndex).await;
let poster: Keypair = program_simulator.get_funded_keypair().await.unwrap();
assert_eq!(
program_simulator
.process_ix(
PostUpdatesAtomic::populate(
poster.pubkey(),
price_update_keypair.pubkey(),
BRIDGE_ID,
DEFAULT_GUARDIAN_SET_INDEX,
vaa.clone(),
merkle_price_updates[0].clone(),
),
&vec![&poster, &price_update_keypair],
None,
)
.await
.unwrap_err()
.unwrap(),
into_transation_error(ReceiverError::InvalidGuardianSetPda)
);


let ProgramTestFixtures {
mut program_simulator,
encoded_vaa_addresses: _,
} = setup_pyth_receiver(vec![], WrongSetupOption::GuardianSetExpired).await;
let poster = program_simulator.get_funded_keypair().await.unwrap();
assert_eq!(
program_simulator
.process_ix(
PostUpdatesAtomic::populate(
poster.pubkey(),
price_update_keypair.pubkey(),
BRIDGE_ID,
DEFAULT_GUARDIAN_SET_INDEX,
vaa.clone(),
merkle_price_updates[0].clone(),
),
&vec![&poster, &price_update_keypair],
None,
)
.await
.unwrap_err()
.unwrap(),
into_transation_error(ReceiverError::GuardianSetExpired)
);
}