Skip to content

Commit

Permalink
[Solana] More tests (#1263)
Browse files Browse the repository at this point in the history
* Checkpoint

* Checkpoint

* Cleanup

* Checkpoint, debug

* Go

* Checkpoint

* Fix

* Add new error and test

* Cleanup

* Add another test

* Keep adding errors

* Another test

* Add comment

* More

* Do it

* Again

* Nice (#1265)

* Test governance

* Fix
  • Loading branch information
guibescos authored Jan 31, 2024
1 parent 2ab72d9 commit 1871ca1
Show file tree
Hide file tree
Showing 12 changed files with 1,106 additions and 47 deletions.
50 changes: 44 additions & 6 deletions pythnet/pythnet_sdk/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use {
messages::{
Message,
PriceFeedMessage,
TwapMessage,
},
wire::{
to_vec,
Expand Down Expand Up @@ -110,24 +111,61 @@ pub fn create_dummy_price_feed_message(value: i64) -> Message {
Message::PriceFeedMessage(msg)
}

pub fn create_dummy_twap_message() -> Message {
let msg = TwapMessage {
feed_id: [0; 32],
cumulative_price: 0,
cumulative_conf: 0,
num_down_slots: 0,
exponent: 0,
publish_time: 0,
prev_publish_time: 0,
publish_slot: 0,
};
Message::TwapMessage(msg)
}

pub fn create_accumulator_message(
all_feeds: &[Message],
updates: &[Message],
corrupt_wormhole_message: bool,
corrupt_messages: bool,
) -> Vec<u8> {
let all_feeds_bytes: Vec<_> = all_feeds
let mut all_feeds_bytes: Vec<_> = all_feeds
.iter()
.map(|f| to_vec::<_, BigEndian>(f).unwrap())
.collect();

let mut updates_bytes: Vec<_> = updates
.iter()
.map(|f| to_vec::<_, BigEndian>(f).unwrap())
.collect();

if corrupt_messages {
all_feeds_bytes = all_feeds_bytes
.iter()
.map(|f| {
let mut f_copy = f.clone();
f_copy[0] = 255;
f_copy
})
.collect();
updates_bytes = updates_bytes
.iter()
.map(|f| {
let mut f_copy = f.clone();
f_copy[0] = 255;
f_copy
})
.collect();
}
let all_feeds_bytes_refs: Vec<_> = all_feeds_bytes.iter().map(|f| f.as_ref()).collect();
let tree = MerkleTree::<Keccak160>::new(all_feeds_bytes_refs.as_slice()).unwrap();
let mut price_updates: Vec<MerklePriceUpdate> = vec![];
for update in updates {
let proof = tree
.prove(&to_vec::<_, BigEndian>(update).unwrap())
.unwrap();
for update in updates_bytes {
let proof = tree.prove(&update).unwrap();
price_updates.push(MerklePriceUpdate {
message: PrefixedVec::from(to_vec::<_, BigEndian>(update).unwrap()),
message: PrefixedVec::from(update),
proof,
});
}
Expand Down
51 changes: 36 additions & 15 deletions target_chains/cosmwasm/contracts/pyth/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ mod test {
let feed1 = create_dummy_price_feed_message(100);
let feed2 = create_dummy_price_feed_message(200);
let feed3 = create_dummy_price_feed_message(300);
let data = create_accumulator_message(&[feed1, feed2, feed3], &[feed1], false);
let data = create_accumulator_message(&[feed1, feed2, feed3], &[feed1], false, false);
check_sufficient_fee(&deps.as_ref(), &[data.into()])
}

Expand Down Expand Up @@ -1246,13 +1246,13 @@ mod test {
let feed2 = create_dummy_price_feed_message(200);
let feed3 = create_dummy_price_feed_message(300);

let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed3], false);
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed3], false, false);
assert_eq!(
get_update_fee_amount(&deps.as_ref(), &[msg.into()]).unwrap(),
200
);

let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1], false);
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1], false, false);
assert_eq!(
get_update_fee_amount(&deps.as_ref(), &[msg.into()]).unwrap(),
100
Expand All @@ -1262,6 +1262,7 @@ mod test {
&[feed1, feed2, feed3],
&[feed1, feed2, feed3, feed1, feed3],
false,
false,
);
assert_eq!(
get_update_fee_amount(&deps.as_ref(), &[msg.into()]).unwrap(),
Expand All @@ -1270,7 +1271,12 @@ mod test {

let batch_msg =
create_batch_price_update_msg_from_attestations(vec![PriceAttestation::default()]);
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
let msg = create_accumulator_message(
&[feed1, feed2, feed3],
&[feed1, feed2, feed3],
false,
false,
);
assert_eq!(
get_update_fee_amount(&deps.as_ref(), &[msg.into(), batch_msg]).unwrap(),
400
Expand All @@ -1287,7 +1293,7 @@ mod test {

let feed1 = create_dummy_price_feed_message(100);
let feed2 = create_dummy_price_feed_message(200);
let msg = create_accumulator_message(&[feed1, feed2], &[feed1], false);
let msg = create_accumulator_message(&[feed1, feed2], &[feed1], false, false);
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
assert!(result.is_ok());
Expand All @@ -1304,7 +1310,7 @@ mod test {
for i in 0..10000 {
all_feeds.push(create_dummy_price_feed_message(i));
}
let msg = create_accumulator_message(&all_feeds, &all_feeds[100..110], false);
let msg = create_accumulator_message(&all_feeds, &all_feeds[100..110], false, false);
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
assert!(result.is_ok());
Expand All @@ -1331,15 +1337,24 @@ mod test {
let mut feed1 = create_dummy_price_feed_message(100);
let mut feed2 = create_dummy_price_feed_message(200);
let mut feed3 = create_dummy_price_feed_message(300);
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
let msg = create_accumulator_message(
&[feed1, feed2, feed3],
&[feed1, feed2, feed3],
false,
false,
);
as_mut_price_feed(&mut feed1).publish_time += 1;
as_mut_price_feed(&mut feed2).publish_time += 1;
as_mut_price_feed(&mut feed3).publish_time += 1;
as_mut_price_feed(&mut feed1).price *= 2;
as_mut_price_feed(&mut feed2).price *= 2;
as_mut_price_feed(&mut feed3).price *= 2;
let msg2 =
create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
let msg2 = create_accumulator_message(
&[feed1, feed2, feed3],
&[feed1, feed2, feed3],
false,
false,
);
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into(), msg2.into()]);

Expand All @@ -1360,7 +1375,12 @@ mod test {
let feed3 = create_dummy_price_feed_message(300);
as_mut_price_feed(&mut feed2).publish_time -= 1;
as_mut_price_feed(&mut feed2).price *= 2;
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
let msg = create_accumulator_message(
&[feed1, feed2, feed3],
&[feed1, feed2, feed3],
false,
false,
);
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);

Expand All @@ -1380,9 +1400,10 @@ mod test {
let feed3 = create_dummy_price_feed_message(300);
as_mut_price_feed(&mut feed2).publish_time -= 1;
as_mut_price_feed(&mut feed2).price *= 2;
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed3], false);
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed3], false, false);

let msg2 = create_accumulator_message(&[feed1, feed2, feed3], &[feed2, feed3], false);
let msg2 =
create_accumulator_message(&[feed1, feed2, feed3], &[feed2, feed3], false, false);
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into(), msg2.into()]);

Expand All @@ -1399,7 +1420,7 @@ mod test {
.unwrap();

let feed1 = create_dummy_price_feed_message(100);
let mut msg = create_accumulator_message(&[feed1], &[feed1], false);
let mut msg = create_accumulator_message(&[feed1], &[feed1], false, false);
msg[4] = 3; // major version
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
Expand All @@ -1418,7 +1439,7 @@ mod test {
.unwrap();

let feed1 = create_dummy_price_feed_message(100);
let msg = create_accumulator_message(&[feed1], &[feed1], true);
let msg = create_accumulator_message(&[feed1], &[feed1], true, false);
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
assert!(result.is_err());
Expand Down Expand Up @@ -1446,7 +1467,7 @@ mod test {
prev_publish_time: 0,
publish_slot: 0,
});
let msg = create_accumulator_message(&[feed1], &[feed1], false);
let msg = create_accumulator_message(&[feed1], &[feed1], false, false);
let info = mock_info("123", &[]);
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
assert!(result.is_err());
Expand Down
2 changes: 1 addition & 1 deletion target_chains/near/receiver/tests/workspaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ async fn test_accumulator_updates() {
// Create a couple of test feeds.
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], false);
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1], false, false);
let message = hex::encode(message);

// Call the usual UpdatePriceFeed function.
Expand Down
5 changes: 5 additions & 0 deletions target_chains/solana/program_simulator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ impl ProgramSimulator {

Ok(T::deserialize(&mut &account.data[8..])?)
}

pub async fn get_balance(&mut self, pubkey: Pubkey) -> Result<u64, BanksClientError> {
let lamports = self.banks_client.get_balance(pubkey).await.unwrap();
Ok(lamports)
}
}

pub fn into_transaction_error<T: Into<anchor_lang::prelude::Error>>(error: T) -> TransactionError {
Expand Down
11 changes: 7 additions & 4 deletions target_chains/solana/programs/pyth-solana-receiver/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ use anchor_lang::prelude::*;
#[error_code]
pub enum ReceiverError {
// Pyth payload errors
#[msg("The tuple emitter chain, emitter doesn't match one of the valid data sources.")]
InvalidDataSource,
#[msg("An error occurred when deserializing the message")]
DeserializeMessageFailed,
#[msg("Received an invalid wormhole message")]
InvalidWormholeMessage,
#[msg("An error occurred when deserializing the message")]
DeserializeMessageFailed,
#[msg("Received an invalid price update")]
InvalidPriceUpdate,
#[msg("This type of message is not supported currently")]
UnsupportedMessageType,
#[msg("The tuple emitter chain, emitter doesn't match one of the valid data sources.")]
InvalidDataSource,
#[msg("Funds are insufficient to pay the receiving fee")]
InsufficientFunds,
// Price account permissions
#[msg("This signer can't write to price update account")]
WrongWriteAuthority,
// Wormhole contract encoded vaa error (from post_updates)
#[msg("The posted VAA account has the wrong owner.")]
WrongVaaOwner,
Expand Down
12 changes: 6 additions & 6 deletions target_chains/solana/programs/pyth-solana-receiver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ pub mod pyth_solana_receiver {
Ok(())
}

pub fn authorize_governance_authority_transfer(
ctx: Context<AuthorizeGovernanceAuthorityTransfer>,
pub fn accept_governance_authority_transfer(
ctx: Context<AcceptGovernanceAuthorityTransfer>,
) -> Result<()> {
let config = &mut ctx.accounts.config;
config.governance_authority = config.target_governance_authority.ok_or(error!(
Expand Down Expand Up @@ -244,13 +244,13 @@ pub struct Governance<'info> {
}

#[derive(Accounts)]
pub struct AuthorizeGovernanceAuthorityTransfer<'info> {
pub struct AcceptGovernanceAuthorityTransfer<'info> {
#[account(constraint =
payer.key() == config.target_governance_authority.ok_or(error!(ReceiverError::NonexistentGovernanceAuthorityTransferRequest))? @
ReceiverError::TargetGovernanceAuthorityMismatch
)]
pub payer: Signer<'info>,
#[account(seeds = [CONFIG_SEED.as_ref()], bump)]
#[account(mut, seeds = [CONFIG_SEED.as_ref()], bump)]
pub config: Account<'info, Config>,
}

Expand All @@ -269,7 +269,7 @@ pub struct PostUpdates<'info> {
pub treasury: AccountInfo<'info>,
/// The contraint is such that either the price_update_account is uninitialized or the payer is the write_authority.
/// Pubkey::default() is the SystemProgram on Solana and it can't sign so it's impossible that price_update_account.write_authority == Pubkey::default() once the account is initialized
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == payer.key(), payer =payer, space = PriceUpdateV1::LEN)]
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == payer.key() @ ReceiverError::WrongWriteAuthority , payer =payer, space = PriceUpdateV1::LEN)]
pub price_update_account: Account<'info, PriceUpdateV1>,
pub system_program: Program<'info, System>,
}
Expand All @@ -290,7 +290,7 @@ pub struct PostUpdatesAtomic<'info> {
pub treasury: AccountInfo<'info>,
/// The contraint is such that either the price_update_account is uninitialized or the payer is the write_authority.
/// Pubkey::default() is the SystemProgram on Solana and it can't sign so it's impossible that price_update_account.write_authority == Pubkey::default() once the account is initialized
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == payer.key(), payer = payer, space = PriceUpdateV1::LEN)]
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == payer.key() @ ReceiverError::WrongWriteAuthority, payer = payer, space = PriceUpdateV1::LEN)]
pub price_update_account: Account<'info, PriceUpdateV1>,
pub system_program: Program<'info, System>,
}
Expand Down
Loading

0 comments on commit 1871ca1

Please sign in to comment.