Skip to content

Commit 1e5df85

Browse files
authored
feat: add posted slot (#1372)
* feat(solana): add posted slot * chore: run pre-commit * Go * Fix rebase * Fix test * Go
1 parent f79f205 commit 1e5df85

File tree

6 files changed

+86
-38
lines changed

6 files changed

+86
-38
lines changed

target_chains/solana/program_simulator/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use {
1818
ProgramTestBanksClientExt,
1919
},
2020
solana_sdk::{
21+
clock::Clock,
2122
compute_budget,
2223
signature::{
2324
Keypair,
@@ -111,6 +112,10 @@ impl ProgramSimulator {
111112
let lamports = self.banks_client.get_balance(pubkey).await.unwrap();
112113
Ok(lamports)
113114
}
115+
116+
pub async fn get_clock(&mut self) -> Result<Clock, BanksClientError> {
117+
self.banks_client.get_sysvar::<Clock>().await
118+
}
114119
}
115120

116121
pub fn into_transaction_error<T: Into<anchor_lang::prelude::Error>>(error: T) -> TransactionError {

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use {
77
DataSource,
88
},
99
price_update::{
10-
PriceUpdateV1,
10+
PriceUpdateV2,
1111
VerificationLevel,
1212
},
1313
},
@@ -122,7 +122,7 @@ pub mod pyth_solana_receiver {
122122
/// Post a price update using a VAA and a MerklePriceUpdate.
123123
/// This function allows you to post a price update in a single transaction.
124124
/// Compared to `post_update`, it only checks whatever signatures are present in the provided VAA and doesn't fail if the number of signatures is lower than the Wormhole quorum of two thirds of the guardians.
125-
/// The number of signatures that were in the VAA is stored in the `VerificationLevel` of the `PriceUpdateV1` account.
125+
/// The number of signatures that were in the VAA is stored in the `VerificationLevel` of the `PriceUpdateV2` account.
126126
///
127127
/// We recommend using `post_update_atomic` with 5 signatures. This is close to the maximum signatures you can verify in one transaction without exceeding the transaction size limit.
128128
///
@@ -225,7 +225,7 @@ pub mod pyth_solana_receiver {
225225
let write_authority: &Signer<'_> = &ctx.accounts.write_authority;
226226
let encoded_vaa = VaaAccount::load(&ctx.accounts.encoded_vaa)?; // IMPORTANT: This line checks that the encoded_vaa has ProcessingStatus::Verified. This check is critical otherwise the program could be tricked into accepting unverified VAAs.
227227
let treasury: &AccountInfo<'_> = &ctx.accounts.treasury;
228-
let price_update_account: &mut Account<'_, PriceUpdateV1> =
228+
let price_update_account: &mut Account<'_, PriceUpdateV2> =
229229
&mut ctx.accounts.price_update_account;
230230

231231
let vaa_components = VaaComponents {
@@ -303,8 +303,8 @@ pub struct PostUpdate<'info> {
303303
pub treasury: AccountInfo<'info>,
304304
/// The constraint is such that either the price_update_account is uninitialized or the write_authority is the write_authority.
305305
/// 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
306-
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == write_authority.key() @ ReceiverError::WrongWriteAuthority , payer =payer, space = PriceUpdateV1::LEN)]
307-
pub price_update_account: Account<'info, PriceUpdateV1>,
306+
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == write_authority.key() @ ReceiverError::WrongWriteAuthority , payer =payer, space = PriceUpdateV2::LEN)]
307+
pub price_update_account: Account<'info, PriceUpdateV2>,
308308
pub system_program: Program<'info, System>,
309309
pub write_authority: Signer<'info>,
310310
}
@@ -326,8 +326,8 @@ pub struct PostUpdateAtomic<'info> {
326326
pub treasury: AccountInfo<'info>,
327327
/// The constraint is such that either the price_update_account is uninitialized or the write_authority is the write_authority.
328328
/// 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
329-
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == write_authority.key() @ ReceiverError::WrongWriteAuthority, payer = payer, space = PriceUpdateV1::LEN)]
330-
pub price_update_account: Account<'info, PriceUpdateV1>,
329+
#[account(init_if_needed, constraint = price_update_account.write_authority == Pubkey::default() || price_update_account.write_authority == write_authority.key() @ ReceiverError::WrongWriteAuthority, payer = payer, space = PriceUpdateV2::LEN)]
330+
pub price_update_account: Account<'info, PriceUpdateV2>,
331331
pub system_program: Program<'info, System>,
332332
pub write_authority: Signer<'info>,
333333
}
@@ -337,7 +337,7 @@ pub struct ReclaimRent<'info> {
337337
#[account(mut)]
338338
pub payer: Signer<'info>,
339339
#[account(mut, close = payer, constraint = price_update_account.write_authority == payer.key() @ ReceiverError::WrongWriteAuthority)]
340-
pub price_update_account: Account<'info, PriceUpdateV1>,
340+
pub price_update_account: Account<'info, PriceUpdateV2>,
341341
}
342342

343343
#[derive(Debug, AnchorSerialize, AnchorDeserialize, Clone)]
@@ -396,7 +396,7 @@ fn post_price_update_from_vaa<'info>(
396396
payer: &Signer<'info>,
397397
write_authority: &Signer<'info>,
398398
treasury: &AccountInfo<'info>,
399-
price_update_account: &mut Account<'_, PriceUpdateV1>,
399+
price_update_account: &mut Account<'_, PriceUpdateV2>,
400400
vaa_components: &VaaComponents,
401401
vaa_payload: &[u8],
402402
price_update: &MerklePriceUpdate,
@@ -450,6 +450,7 @@ fn post_price_update_from_vaa<'info>(
450450
price_update_account.write_authority = write_authority.key();
451451
price_update_account.verification_level = vaa_components.verification_level;
452452
price_update_account.price_message = price_feed_message;
453+
price_update_account.posted_slot = Clock::get()?.slot;
453454
}
454455
Message::TwapMessage(_) => {
455456
return err!(ReceiverError::UnsupportedMessageType);

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

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use {
2424
pyth_solana_receiver_sdk::{
2525
config::DataSource,
2626
price_update::{
27-
PriceUpdateV1,
27+
PriceUpdateV2,
2828
VerificationLevel,
2929
},
3030
},
@@ -352,7 +352,7 @@ async fn test_post_price_update_from_vaa() {
352352
.await;
353353

354354
let mut price_update_account = program_simulator
355-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
355+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
356356
.await
357357
.unwrap();
358358

@@ -365,6 +365,10 @@ async fn test_post_price_update_from_vaa() {
365365
Message::PriceFeedMessage(price_update_account.price_message),
366366
feed_1
367367
);
368+
assert_eq!(
369+
price_update_account.posted_slot,
370+
program_simulator.get_clock().await.unwrap().slot
371+
);
368372

369373
// Now poster_2 will pay
370374
program_simulator
@@ -393,7 +397,7 @@ async fn test_post_price_update_from_vaa() {
393397
.await;
394398

395399
price_update_account = program_simulator
396-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
400+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
397401
.await
398402
.unwrap();
399403

@@ -406,6 +410,10 @@ async fn test_post_price_update_from_vaa() {
406410
Message::PriceFeedMessage(price_update_account.price_message),
407411
feed_1
408412
);
413+
assert_eq!(
414+
price_update_account.posted_slot,
415+
program_simulator.get_clock().await.unwrap().slot
416+
);
409417

410418

411419
// Now change the fee!
@@ -456,7 +464,7 @@ async fn test_post_price_update_from_vaa() {
456464

457465
// Transaction failed, so the account should not have been updated
458466
price_update_account = program_simulator
459-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
467+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
460468
.await
461469
.unwrap();
462470
assert_eq!(price_update_account.write_authority, poster.pubkey());
@@ -468,6 +476,10 @@ async fn test_post_price_update_from_vaa() {
468476
Message::PriceFeedMessage(price_update_account.price_message),
469477
feed_1
470478
);
479+
assert_eq!(
480+
price_update_account.posted_slot,
481+
program_simulator.get_clock().await.unwrap().slot
482+
);
471483

472484

473485
// Airdrop more
@@ -510,7 +522,7 @@ async fn test_post_price_update_from_vaa() {
510522
.await;
511523

512524
price_update_account = program_simulator
513-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
525+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
514526
.await
515527
.unwrap();
516528
assert_eq!(price_update_account.write_authority, poster.pubkey());
@@ -522,6 +534,10 @@ async fn test_post_price_update_from_vaa() {
522534
Message::PriceFeedMessage(price_update_account.price_message),
523535
feed_2
524536
);
537+
assert_eq!(
538+
price_update_account.posted_slot,
539+
program_simulator.get_clock().await.unwrap().slot
540+
);
525541

526542
assert_eq!(
527543
program_simulator

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use {
2020
},
2121
},
2222
pyth_solana_receiver_sdk::price_update::{
23-
PriceUpdateV1,
23+
PriceUpdateV2,
2424
VerificationLevel,
2525
},
2626
pythnet_sdk::{
@@ -88,7 +88,7 @@ async fn test_post_update() {
8888
.await;
8989

9090
let mut price_update_account = program_simulator
91-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
91+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
9292
.await
9393
.unwrap();
9494

@@ -101,6 +101,10 @@ async fn test_post_update() {
101101
Message::PriceFeedMessage(price_update_account.price_message),
102102
feed_1
103103
);
104+
assert_eq!(
105+
price_update_account.posted_slot,
106+
program_simulator.get_clock().await.unwrap().slot
107+
);
104108

105109
// post another update to the same account
106110
program_simulator
@@ -126,7 +130,7 @@ async fn test_post_update() {
126130
.await;
127131

128132
price_update_account = program_simulator
129-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
133+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
130134
.await
131135
.unwrap();
132136

@@ -139,6 +143,11 @@ async fn test_post_update() {
139143
Message::PriceFeedMessage(price_update_account.price_message),
140144
feed_2
141145
);
146+
assert_eq!(
147+
price_update_account.posted_slot,
148+
program_simulator.get_clock().await.unwrap().slot
149+
);
150+
142151

143152
// This poster doesn't have the write authority
144153
let poster_2 = program_simulator.get_funded_keypair().await.unwrap();

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use {
2020
},
2121
},
2222
pyth_solana_receiver_sdk::price_update::{
23-
PriceUpdateV1,
23+
PriceUpdateV2,
2424
VerificationLevel,
2525
},
2626
pythnet_sdk::{
@@ -94,7 +94,7 @@ async fn test_post_update_atomic() {
9494
.await;
9595

9696
let mut price_update_account = program_simulator
97-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
97+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
9898
.await
9999
.unwrap();
100100

@@ -107,6 +107,10 @@ async fn test_post_update_atomic() {
107107
Message::PriceFeedMessage(price_update_account.price_message),
108108
feed_1
109109
);
110+
assert_eq!(
111+
price_update_account.posted_slot,
112+
program_simulator.get_clock().await.unwrap().slot
113+
);
110114

111115
// post another update to the same account
112116
program_simulator
@@ -136,7 +140,7 @@ async fn test_post_update_atomic() {
136140
assert_treasury_balance(&mut program_simulator, 0, SECONDARY_TREASURY_ID).await;
137141

138142
price_update_account = program_simulator
139-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
143+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
140144
.await
141145
.unwrap();
142146

@@ -149,6 +153,10 @@ async fn test_post_update_atomic() {
149153
Message::PriceFeedMessage(price_update_account.price_message),
150154
feed_2
151155
);
156+
assert_eq!(
157+
price_update_account.posted_slot,
158+
program_simulator.get_clock().await.unwrap().slot
159+
);
152160

153161
// use another treasury account
154162
program_simulator
@@ -183,7 +191,7 @@ async fn test_post_update_atomic() {
183191
.await;
184192

185193
price_update_account = program_simulator
186-
.get_anchor_account_data::<PriceUpdateV1>(price_update_keypair.pubkey())
194+
.get_anchor_account_data::<PriceUpdateV2>(price_update_keypair.pubkey())
187195
.await
188196
.unwrap();
189197
assert_eq!(price_update_account.write_authority, poster.pubkey());
@@ -195,6 +203,10 @@ async fn test_post_update_atomic() {
195203
Message::PriceFeedMessage(price_update_account.price_message),
196204
feed_1
197205
);
206+
assert_eq!(
207+
price_update_account.posted_slot,
208+
program_simulator.get_clock().await.unwrap().slot
209+
);
198210
}
199211

200212
#[tokio::test]

0 commit comments

Comments
 (0)