Skip to content

Commit a666702

Browse files
authored
feat(target_chains/starknet): add query_price_feed methods (#1627)
1 parent 8fc116c commit a666702

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

target_chains/starknet/contracts/src/pyth.cairo

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,41 @@ mod pyth {
204204
Result::Ok(price)
205205
}
206206

207+
fn query_price_feed_no_older_than(
208+
self: @ContractState, price_id: u256, age: u64
209+
) -> Result<PriceFeed, GetPriceNoOlderThanError> {
210+
let feed = self.query_price_feed_unsafe(price_id).map_err_into()?;
211+
if !is_no_older_than(feed.price.publish_time, age) {
212+
return Result::Err(GetPriceNoOlderThanError::StalePrice);
213+
}
214+
Result::Ok(feed)
215+
}
216+
217+
fn query_price_feed_unsafe(
218+
self: @ContractState, price_id: u256
219+
) -> Result<PriceFeed, GetPriceUnsafeError> {
220+
let info = self.latest_price_info.read(price_id);
221+
if info.publish_time == 0 {
222+
return Result::Err(GetPriceUnsafeError::PriceFeedNotFound);
223+
}
224+
let feed = PriceFeed {
225+
id: price_id,
226+
price: Price {
227+
price: info.price,
228+
conf: info.conf,
229+
expo: info.expo,
230+
publish_time: info.publish_time,
231+
},
232+
ema_price: Price {
233+
price: info.ema_price,
234+
conf: info.ema_conf,
235+
expo: info.expo,
236+
publish_time: info.publish_time,
237+
},
238+
};
239+
Result::Ok(feed)
240+
}
241+
207242
fn update_price_feeds(ref self: ContractState, data: ByteArray) {
208243
self.update_price_feeds_internal(data, array![], 0, 0, false);
209244
}

target_chains/starknet/contracts/src/pyth/interface.cairo

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ pub trait IPyth<T> {
1111
self: @T, price_id: u256, age: u64
1212
) -> Result<Price, GetPriceNoOlderThanError>;
1313
fn get_ema_price_unsafe(self: @T, price_id: u256) -> Result<Price, GetPriceUnsafeError>;
14+
fn query_price_feed_no_older_than(
15+
self: @T, price_id: u256, age: u64
16+
) -> Result<PriceFeed, GetPriceNoOlderThanError>;
17+
fn query_price_feed_unsafe(self: @T, price_id: u256) -> Result<PriceFeed, GetPriceUnsafeError>;
1418
fn update_price_feeds(ref self: T, data: ByteArray);
1519
fn update_price_feeds_if_necessary(
1620
ref self: T, update: ByteArray, required_publish_times: Array<PriceFeedPublishTime>

target_chains/starknet/contracts/tests/pyth.cairo

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use snforge_std::{
55
use pyth::pyth::{
66
IPythDispatcher, IPythDispatcherTrait, DataSource, Event as PythEvent, PriceFeedUpdated,
77
WormholeAddressSet, GovernanceDataSourceSet, ContractUpgraded, DataSourcesSet, FeeSet,
8-
PriceFeedPublishTime, GetPriceNoOlderThanError, Price, PriceFeed,
8+
PriceFeedPublishTime, GetPriceNoOlderThanError, Price, PriceFeed, GetPriceUnsafeError,
99
};
1010
use pyth::byte_array::{ByteArray, ByteArrayImpl};
1111
use pyth::util::{array_try_into, UnwrapWithFelt252};
@@ -131,6 +131,19 @@ fn update_price_feeds_works() {
131131
assert!(last_ema_price.conf == 4096812700);
132132
assert!(last_ema_price.expo == -8);
133133
assert!(last_ema_price.publish_time == 1712589206);
134+
135+
let feed = pyth
136+
.query_price_feed_unsafe(0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43)
137+
.unwrap_with_felt252();
138+
assert!(feed.id == 0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43);
139+
assert!(feed.price.price == 7192002930010);
140+
assert!(feed.price.conf == 3596501465);
141+
assert!(feed.price.expo == -8);
142+
assert!(feed.price.publish_time == 1712589206);
143+
assert!(feed.ema_price.price == 7181868900000);
144+
assert!(feed.ema_price.conf == 4096812700);
145+
assert!(feed.ema_price.expo == -8);
146+
assert!(feed.ema_price.publish_time == 1712589206);
134147
}
135148

136149
#[test]
@@ -407,10 +420,18 @@ fn test_get_no_older_works() {
407420
let fee_contract = deploy_fee_contract(user);
408421
let pyth = deploy_default(wormhole.contract_address, fee_contract.contract_address);
409422
let price_id = 0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43;
423+
let err = pyth.get_price_unsafe(price_id).unwrap_err();
424+
assert!(err == GetPriceUnsafeError::PriceFeedNotFound);
425+
let err = pyth.get_ema_price_unsafe(price_id).unwrap_err();
426+
assert!(err == GetPriceUnsafeError::PriceFeedNotFound);
427+
let err = pyth.query_price_feed_unsafe(price_id).unwrap_err();
428+
assert!(err == GetPriceUnsafeError::PriceFeedNotFound);
410429
let err = pyth.get_price_no_older_than(price_id, 100).unwrap_err();
411430
assert!(err == GetPriceNoOlderThanError::PriceFeedNotFound);
412431
let err = pyth.get_ema_price_no_older_than(price_id, 100).unwrap_err();
413432
assert!(err == GetPriceNoOlderThanError::PriceFeedNotFound);
433+
let err = pyth.query_price_feed_no_older_than(price_id, 100).unwrap_err();
434+
assert!(err == GetPriceNoOlderThanError::PriceFeedNotFound);
414435

415436
start_prank(CheatTarget::One(fee_contract.contract_address), user.try_into().unwrap());
416437
fee_contract.approve(pyth.contract_address, 10000);
@@ -425,6 +446,8 @@ fn test_get_no_older_works() {
425446
assert!(err == GetPriceNoOlderThanError::StalePrice);
426447
let err = pyth.get_ema_price_no_older_than(price_id, 3).unwrap_err();
427448
assert!(err == GetPriceNoOlderThanError::StalePrice);
449+
let err = pyth.query_price_feed_no_older_than(price_id, 3).unwrap_err();
450+
assert!(err == GetPriceNoOlderThanError::StalePrice);
428451

429452
start_warp(CheatTarget::One(pyth.contract_address), 1712589208);
430453
let val = pyth.get_price_no_older_than(price_id, 3).unwrap_with_felt252();
@@ -433,6 +456,9 @@ fn test_get_no_older_works() {
433456
let val = pyth.get_ema_price_no_older_than(price_id, 3).unwrap_with_felt252();
434457
assert!(val.publish_time == 1712589206);
435458
assert!(val.price == 7181868900000);
459+
let val = pyth.query_price_feed_no_older_than(price_id, 3).unwrap_with_felt252();
460+
assert!(val.price.publish_time == 1712589206);
461+
assert!(val.price.price == 7192002930010);
436462

437463
start_warp(CheatTarget::One(pyth.contract_address), 1712589204);
438464
let val = pyth.get_price_no_older_than(price_id, 3).unwrap_with_felt252();
@@ -441,6 +467,9 @@ fn test_get_no_older_works() {
441467
let val = pyth.get_ema_price_no_older_than(price_id, 3).unwrap_with_felt252();
442468
assert!(val.publish_time == 1712589206);
443469
assert!(val.price == 7181868900000);
470+
let val = pyth.query_price_feed_no_older_than(price_id, 3).unwrap_with_felt252();
471+
assert!(val.price.publish_time == 1712589206);
472+
assert!(val.price.price == 7192002930010);
444473

445474
stop_warp(CheatTarget::One(pyth.contract_address));
446475
}

0 commit comments

Comments
 (0)