diff --git a/target_chains/stylus/contracts/pyth-receiver/src/error.rs b/target_chains/stylus/contracts/pyth-receiver/src/error.rs new file mode 100644 index 0000000000..6b44614f9b --- /dev/null +++ b/target_chains/stylus/contracts/pyth-receiver/src/error.rs @@ -0,0 +1,19 @@ +use alloc::vec::Vec; + +pub enum PythReceiverError { + PriceUnavailable +} + +impl core::fmt::Debug for PythReceiverError { + fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Ok(()) + } +} + +impl From for Vec { + fn from(error: PythReceiverError) -> Vec { + vec![match error { + PythReceiverError::PriceUnavailable => 1, + }] + } +} \ No newline at end of file diff --git a/target_chains/stylus/contracts/pyth-receiver/src/lib.rs b/target_chains/stylus/contracts/pyth-receiver/src/lib.rs index 2cf9b7acb0..35fc43c127 100644 --- a/target_chains/stylus/contracts/pyth-receiver/src/lib.rs +++ b/target_chains/stylus/contracts/pyth-receiver/src/lib.rs @@ -6,6 +6,7 @@ extern crate alloc; mod structs; +mod error; use alloc::vec::Vec; use stylus_sdk::{alloy_primitives::{U256, U64, I32, I64, FixedBytes}, @@ -13,6 +14,7 @@ use stylus_sdk::{alloy_primitives::{U256, U64, I32, I64, FixedBytes}, storage::{StorageAddress, StorageVec, StorageMap, StorageUint, StorageBool, StorageU256}}; use structs::{DataSourceStorage, PriceInfoReturn, PriceInfoStorage}; +use error::{PythReceiverError}; #[storage] #[entrypoint] @@ -31,12 +33,31 @@ pub struct PythReceiver { #[public] impl PythReceiver { - pub fn get_price_unsafe(&self, _id: [u8; 32]) -> PriceInfoReturn { - (U64::ZERO, I32::ZERO, I64::ZERO, U64::ZERO, I64::ZERO, U64::ZERO) + pub fn get_price_unsafe(&self, _id: [u8; 32]) -> Result { + let id_fb = FixedBytes::<32>::from(_id); + + let price_info = self.latest_price_info.get(id_fb); + + if price_info.publish_time.get() == U64::ZERO { + return Err(PythReceiverError::PriceUnavailable); + } + + Ok(( + price_info.publish_time.get(), + price_info.expo.get(), + price_info.price.get(), + price_info.conf.get(), + price_info.ema_price.get(), + price_info.ema_conf.get(), + )) } - pub fn get_price_no_older_than(&self, _id: [u8; 32], _age: u64) -> PriceInfoReturn { - (U64::ZERO, I32::ZERO, I64::ZERO, U64::ZERO, I64::ZERO, U64::ZERO) + pub fn get_price_no_older_than(&self, _id: [u8; 32], _age: u64) -> Result { + let price_info = self.get_price_unsafe(_id)?; + if !self.is_no_older_than(price_info.0, _age) { + return Err(PythReceiverError::PriceUnavailable); + } + Ok(price_info) } pub fn get_ema_price_unsafe(&self, _id: [u8; 32]) -> PriceInfoReturn { @@ -108,4 +129,11 @@ impl PythReceiver { ) -> Vec { Vec::new() } + + fn is_no_older_than(&self, publish_time: U64, max_age: u64) -> bool { + let current_u64: u64 = self.vm().block_timestamp(); + let publish_time_u64: u64 = publish_time.to::(); + + current_u64.saturating_sub(publish_time_u64) <= max_age + } }