Skip to content

Commit c505951

Browse files
authored
Merge pull request #2849 from pyth-network/pyth-stylus-final-functions
feat(stylus): implement queryPriceFeed, priceFeedExists functions, clean tests
2 parents b4cf10e + 2bae09e commit c505951

File tree

5 files changed

+284
-183
lines changed

5 files changed

+284
-183
lines changed

target_chains/stylus/contracts/pyth-receiver/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub enum PythReceiverError {
1919
TooManyUpdates,
2020
PriceFeedNotFoundWithinRange,
2121
NoFreshUpdate,
22+
PriceFeedNotFound,
2223
}
2324

2425
impl core::fmt::Debug for PythReceiverError {
@@ -47,6 +48,7 @@ impl From<PythReceiverError> for Vec<u8> {
4748
PythReceiverError::TooManyUpdates => 15,
4849
PythReceiverError::PriceFeedNotFoundWithinRange => 16,
4950
PythReceiverError::NoFreshUpdate => 17,
51+
PythReceiverError::PriceFeedNotFound => 18,
5052
}]
5153
}
5254
}

target_chains/stylus/contracts/pyth-receiver/src/integration_tests.rs

Lines changed: 120 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ mod test {
99
use pythnet_sdk::wire::v1::{AccumulatorUpdateData, Proof};
1010
use std::time::Duration;
1111
use wormhole_contract::WormholeContract;
12-
const TEST_PRICE_ID: [u8; 32] = [
13-
0xe6, 0x2d, 0xf6, 0xc8, 0xb4, 0xa8, 0x5f, 0xe1, 0xa6, 0x7d, 0xb4, 0x4d, 0xc1, 0x2d, 0xe5,
14-
0xdb, 0x33, 0x0f, 0x7a, 0xc6, 0x6b, 0x72, 0xdc, 0x65, 0x8a, 0xfe, 0xdf, 0x0f, 0x4a, 0x41,
15-
0x5b, 0x43,
16-
];
1712

1813
const PYTHNET_CHAIN_ID: u16 = 26;
1914
const PYTHNET_EMITTER_ADDRESS: [u8; 32] = [
@@ -102,7 +97,7 @@ mod test {
10297
) {
10398
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
10499

105-
let update_data = good_update1();
100+
let update_data = ban_usd_update();
106101
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
107102

108103
alice.fund(update_fee);
@@ -112,9 +107,11 @@ mod test {
112107
.update_price_feeds(update_data);
113108
assert!(result.is_ok());
114109

115-
let price_result = pyth_contract.sender(alice).get_price_unsafe(TEST_PRICE_ID);
110+
let price_result = pyth_contract
111+
.sender(alice)
112+
.get_price_unsafe(ban_usd_feed_id());
116113
assert!(price_result.is_ok());
117-
assert_eq!(price_result.unwrap(), good_update1_results());
114+
assert_eq!(price_result.unwrap(), ban_usd_results_get_price());
118115
}
119116

120117
#[motsu::test]
@@ -127,7 +124,7 @@ mod test {
127124

128125
alice.fund(U256::from(200));
129126

130-
let update_data = good_update1();
127+
let update_data = ban_usd_update();
131128
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
132129
let small_update_fee = update_fee / U256::from(2);
133130

@@ -146,10 +143,10 @@ mod test {
146143
) {
147144
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
148145

149-
let update_data1 = good_update1();
146+
let update_data1 = ban_usd_update();
150147
let update_fee1 = mock_get_update_fee(update_data1.clone()).unwrap();
151148

152-
let update_data2 = good_update2();
149+
let update_data2 = btc_usd_update();
153150
let update_fee2 = mock_get_update_fee(update_data2.clone()).unwrap();
154151

155152
alice.fund(update_fee1 + update_fee2);
@@ -164,9 +161,11 @@ mod test {
164161
.update_price_feeds(update_data2);
165162
assert!(result2.is_ok());
166163

167-
let price_result = pyth_contract.sender(alice).get_price_unsafe(TEST_PRICE_ID);
164+
let price_result = pyth_contract
165+
.sender(alice)
166+
.get_price_unsafe(ban_usd_feed_id());
168167
assert!(price_result.is_ok());
169-
assert_eq!(price_result.unwrap(), good_update2_results());
168+
assert_eq!(price_result.unwrap(), ban_usd_results_get_price());
170169
}
171170

172171
#[motsu::test]
@@ -177,7 +176,9 @@ mod test {
177176
) {
178177
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
179178

180-
let price_result = pyth_contract.sender(alice).get_price_unsafe(TEST_PRICE_ID);
179+
let price_result = pyth_contract
180+
.sender(alice)
181+
.get_price_unsafe(ban_usd_feed_id());
181182
assert!(price_result.is_err());
182183
assert_eq!(
183184
price_result.unwrap_err(),
@@ -219,7 +220,7 @@ mod test {
219220
MockClock::set_time(Duration::from_secs(1761573860));
220221
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
221222

222-
let update_data = good_update2();
223+
let update_data = btc_usd_update();
223224
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
224225

225226
alice.fund(update_fee);
@@ -231,9 +232,9 @@ mod test {
231232

232233
let price_result = pyth_contract
233234
.sender(alice)
234-
.get_price_no_older_than(TEST_PRICE_ID, u64::MAX);
235+
.get_price_no_older_than(btc_usd_feed_id(), u64::MAX);
235236
assert!(price_result.is_ok());
236-
assert_eq!(price_result.unwrap(), good_update2_results());
237+
assert_eq!(price_result.unwrap(), btc_usd_results_get_price());
237238
}
238239

239240
#[motsu::test]
@@ -245,7 +246,7 @@ mod test {
245246
MockClock::set_time(Duration::from_secs(1761573860));
246247
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
247248

248-
let update_data = good_update2();
249+
let update_data = btc_usd_update();
249250
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
250251

251252
alice.fund(update_fee);
@@ -257,7 +258,8 @@ mod test {
257258

258259
let price_result = pyth_contract
259260
.sender(alice)
260-
.get_price_no_older_than(TEST_PRICE_ID, 1);
261+
.get_price_no_older_than(btc_usd_feed_id(), 1);
262+
println!("Price result: {:?}", price_result);
261263
assert!(price_result.is_err());
262264
assert_eq!(
263265
price_result.unwrap_err(),
@@ -266,14 +268,14 @@ mod test {
266268
}
267269

268270
#[motsu::test]
269-
fn test_multiple_updates_in_same_vaa_different_ids_updates_both(
271+
fn test_multiple_updates_different_ids_updates_both(
270272
pyth_contract: Contract<PythReceiver>,
271273
wormhole_contract: Contract<WormholeContract>,
272274
alice: Address,
273275
) {
274276
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
275277

276-
let update_data = multiple_updates_same_vaa();
278+
let update_data = multiple_updates_diff_vaa();
277279
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
278280

279281
alice.fund(update_fee);
@@ -283,35 +285,38 @@ mod test {
283285
.update_price_feeds(update_data);
284286
assert!(result.is_ok());
285287

286-
let first_id: [u8; 32] = [
287-
0xe6, 0x2d, 0xf6, 0xc8, 0xb4, 0xa8, 0x5f, 0xe1, 0xa6, 0x7d, 0xb4, 0x4d, 0xc1, 0x2d,
288-
0xe5, 0xdb, 0x33, 0x0f, 0x7a, 0xc6, 0x6b, 0x72, 0xdc, 0x65, 0x8a, 0xfe, 0xdf, 0x0f,
289-
0x4a, 0x41, 0x5b, 0x43,
290-
];
291-
let second_id: [u8; 32] = [
292-
0xff, 0x61, 0x49, 0x1a, 0x93, 0x11, 0x12, 0xdd, 0xf1, 0xbd, 0x81, 0x47, 0xcd, 0x1b,
293-
0x64, 0x13, 0x75, 0xf7, 0x9f, 0x58, 0x25, 0x12, 0x6d, 0x66, 0x54, 0x80, 0x87, 0x46,
294-
0x34, 0xfd, 0x0a, 0xce,
295-
];
296-
297-
let first_price_result = pyth_contract.sender(alice).get_price_unsafe(first_id);
288+
let first_price_result = pyth_contract
289+
.sender(alice)
290+
.get_price_unsafe(ban_usd_feed_id());
298291
assert!(first_price_result.is_ok());
299-
assert_eq!(first_price_result.unwrap(), multiple_updates_results()[0]);
292+
assert_eq!(
293+
first_price_result.unwrap(),
294+
multiple_updates_diff_vaa_results_get_price()[0]
295+
);
300296

301-
let second_price_result = pyth_contract.sender(alice).get_price_unsafe(second_id);
297+
let second_price_result = pyth_contract
298+
.sender(alice)
299+
.get_price_unsafe(btc_usd_feed_id());
302300
assert!(second_price_result.is_ok());
303-
assert_eq!(second_price_result.unwrap(), multiple_updates_results()[1]);
301+
assert_eq!(
302+
second_price_result.unwrap(),
303+
multiple_updates_diff_vaa_results_get_price()[1]
304+
);
304305
}
305306

306307
#[motsu::test]
307-
fn test_multiple_updates_different_ids_updates_both(
308+
fn test_price_feed_exists(
308309
pyth_contract: Contract<PythReceiver>,
309310
wormhole_contract: Contract<WormholeContract>,
310311
alice: Address,
311312
) {
312313
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
313314

314-
let update_data = multiple_updates_diff_vaa();
315+
assert!(!pyth_contract
316+
.sender(alice)
317+
.price_feed_exists(ban_usd_feed_id()));
318+
319+
let update_data = ban_usd_update();
315320
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
316321

317322
alice.fund(update_fee);
@@ -321,35 +326,94 @@ mod test {
321326
.update_price_feeds(update_data);
322327
assert!(result.is_ok());
323328

324-
let first_id: [u8; 32] = [
325-
0x3f, 0xa4, 0x25, 0x28, 0x48, 0xf9, 0xf0, 0xa1, 0x48, 0x0b, 0xe6, 0x27, 0x45, 0xa4,
326-
0x62, 0x9d, 0x9e, 0xb1, 0x32, 0x2a, 0xeb, 0xab, 0x8a, 0x79, 0x1e, 0x34, 0x4b, 0x3b,
327-
0x9c, 0x1a, 0xdc, 0xf5,
328-
];
329-
let second_id: [u8; 32] = TEST_PRICE_ID;
329+
assert!(pyth_contract
330+
.sender(alice)
331+
.price_feed_exists(ban_usd_feed_id()));
332+
}
330333

331-
let first_price_result = pyth_contract.sender(alice).get_price_unsafe(first_id);
332-
assert!(first_price_result.is_ok());
333-
assert_eq!(
334-
first_price_result.unwrap(),
335-
multiple_updates_diff_vaa_results()[0]
336-
);
334+
#[motsu::test]
335+
fn test_query_price_feed_doesnt_exist(
336+
pyth_contract: Contract<PythReceiver>,
337+
wormhole_contract: Contract<WormholeContract>,
338+
alice: Address,
339+
) {
340+
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
337341

338-
let second_price_result = pyth_contract.sender(alice).get_price_unsafe(second_id);
339-
assert!(second_price_result.is_ok());
342+
let price_result = pyth_contract
343+
.sender(alice)
344+
.query_price_feed(ban_usd_feed_id());
345+
346+
assert!(price_result.is_err());
340347
assert_eq!(
341-
second_price_result.unwrap(),
342-
multiple_updates_diff_vaa_results()[1]
348+
price_result.unwrap_err(),
349+
PythReceiverError::PriceFeedNotFound
343350
);
344351
}
345352

346353
#[motsu::test]
347-
fn test_multiple_updates_same_id_updates_latest(
354+
fn test_query_price_feed_after_one_feed_update(
348355
pyth_contract: Contract<PythReceiver>,
349356
wormhole_contract: Contract<WormholeContract>,
350357
alice: Address,
351358
) {
352359
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
353-
alice.fund(U256::from(200));
360+
361+
let update_data = ban_usd_update();
362+
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
363+
364+
alice.fund(update_fee);
365+
366+
let result = pyth_contract
367+
.sender_and_value(alice, update_fee)
368+
.update_price_feeds(update_data);
369+
370+
assert!(result.is_ok());
371+
372+
let price_result = pyth_contract
373+
.sender(alice)
374+
.query_price_feed(ban_usd_feed_id());
375+
376+
assert!(price_result.is_ok());
377+
assert_eq!(price_result.unwrap(), ban_usd_results_full());
378+
}
379+
380+
#[motsu::test]
381+
fn test_query_price_feed_after_multiple_updates(
382+
pyth_contract: Contract<PythReceiver>,
383+
wormhole_contract: Contract<WormholeContract>,
384+
alice: Address,
385+
) {
386+
pyth_wormhole_init(&pyth_contract, &wormhole_contract, &alice);
387+
388+
let update_data = multiple_updates_diff_vaa();
389+
let update_fee = mock_get_update_fee(update_data.clone()).unwrap();
390+
391+
alice.fund(update_fee);
392+
393+
let result = pyth_contract
394+
.sender_and_value(alice, update_fee)
395+
.update_price_feeds(update_data);
396+
397+
assert!(result.is_ok());
398+
399+
let price_result1 = pyth_contract
400+
.sender(alice)
401+
.query_price_feed(ban_usd_feed_id());
402+
403+
assert!(price_result1.is_ok());
404+
assert_eq!(
405+
price_result1.unwrap(),
406+
multiple_updates_diff_vaa_results_full()[0]
407+
);
408+
409+
let price_result2 = pyth_contract
410+
.sender(alice)
411+
.query_price_feed(btc_usd_feed_id());
412+
413+
assert!(price_result2.is_ok());
414+
assert_eq!(
415+
price_result2.unwrap(),
416+
multiple_updates_diff_vaa_results_full()[1]
417+
);
354418
}
355419
}

0 commit comments

Comments
 (0)