From 9a36c16674c46c3b1a6a56c38873f59bb4c008bf Mon Sep 17 00:00:00 2001 From: samsamtrum Date: Fri, 19 Jun 2026 18:40:48 +0700 Subject: [PATCH] Reject invalid price feed values --- venus/price-alert/src/lib.rs | 42 ++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/venus/price-alert/src/lib.rs b/venus/price-alert/src/lib.rs index a255a34..69d7e49 100644 --- a/venus/price-alert/src/lib.rs +++ b/venus/price-alert/src/lib.rs @@ -21,6 +21,16 @@ struct PriceResponse { timestamp: Option, } +pub fn price_to_cents(price: f64) -> Option { + let cents = (price * 100.0).round(); + + if cents.is_finite() && cents >= 0.0 && cents <= u64::MAX as f64 { + Some(cents as u64) + } else { + None + } +} + rialo! { workflow { state { @@ -67,7 +77,7 @@ rialo! { use rialo_rex_processor_interface::state::RexReport; use rialo_types::RexOutput; use rialo_s_program_error::ProgramError; - use crate::PriceResponse; + use crate::{price_to_cents, PriceResponse}; // ======================================================== // Initialization @@ -191,8 +201,11 @@ rialo! { match serde_json::from_slice::(data) { Ok(price_resp) => { - // Convert float price to integer (assuming 2 decimal places) - let price_cents = (price_resp.price * 100.0).round() as u64; + // Convert float price to integer (assuming 2 decimal places). + let Some(price_cents) = price_to_cents(price_resp.price) else { + msg!("⚠️ Invalid price value: {}", price_resp.price); + return Ok(()); + }; self.current_price = price_cents; msg!("📊 {} price: {} ({})", @@ -320,7 +333,10 @@ rialo! { if let Some(data) = response.response.as_raw() { match serde_json::from_slice::(data) { Ok(price_resp) => { - let price_cents = (price_resp.price * 100.0).round() as u64; + let Some(price_cents) = price_to_cents(price_resp.price) else { + msg!("⚠️ Invalid price value: {}", price_resp.price); + return Ok(()); + }; self.current_price = price_cents; msg!("📊 [Scheduled] {} price: {}", price_resp.symbol, price_resp.price); @@ -436,3 +452,21 @@ rialo! { } } } + +#[cfg(test)] +mod tests { + use super::price_to_cents; + + #[test] + fn price_to_cents_rejects_invalid_values() { + assert_eq!(price_to_cents(-1.0), None); + assert_eq!(price_to_cents(f64::NAN), None); + assert_eq!(price_to_cents(f64::INFINITY), None); + } + + #[test] + fn price_to_cents_preserves_valid_values() { + assert_eq!(price_to_cents(123.456), Some(12_346)); + assert_eq!(price_to_cents(0.0), Some(0)); + } +}