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
More
  • Loading branch information
guibescos committed Jan 30, 2024
commit 14a8df567cb6ab1efddadbaa4e05774e10c0b6c2
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 @@ -105,6 +105,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_transation_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,16 +3,16 @@ 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("Received an invalid price update")]
InvalidPriceUpdate,
#[msg("An error occurred when deserializing the message")]
DeserializeMessageFailed,
#[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,
// Wormhole contract encoded vaa error (from post_updates)
Expand Down Expand Up @@ -48,4 +48,7 @@ pub enum ReceiverError {
TargetGovernanceAuthorityMismatch,
#[msg("The governance authority needs to request a transfer first")]
NonexistentGovernanceAuthorityTransferRequest,
// Price account permissions
#[msg("This signer can't write to price update account")]
WrongWriteAuthority,
}
4 changes: 2 additions & 2 deletions target_chains/solana/programs/pyth-solana-receiver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
34 changes: 33 additions & 1 deletion target_chains/solana/programs/pyth-solana-receiver/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use {
crate::{
accounts,
instruction,
state::config::Config,
state::config::{
Config,
DataSource,
},
PostUpdatesAtomicParams,
CONFIG_SEED,
ID,
Expand Down Expand Up @@ -141,6 +144,35 @@ impl instruction::PostUpdatesAtomic {
}


impl instruction::SetDataSources {
pub fn populate(payer: Pubkey, data_sources: Vec<DataSource>) -> Instruction {
let governance_accounts = accounts::Governance::populate(payer).to_account_metas(None);
Instruction {
program_id: ID,
accounts: governance_accounts,
data: instruction::SetDataSources {
valid_data_sources: data_sources,
}
.data(),
}
}
}

impl instruction::SetFee {
pub fn populate(payer: Pubkey, fee: u64) -> Instruction {
let governance_accounts = accounts::Governance::populate(payer).to_account_metas(None);
Instruction {
program_id: ID,
accounts: governance_accounts,
data: instruction::SetFee {
single_update_fee_in_lamports: fee,
}
.data(),
}
}
}


pub fn get_treasury_address() -> Pubkey {
Pubkey::find_program_address(&[TREASURY_SEED.as_ref()], &ID).0
}
Expand Down
Loading
Loading