oil_api/state/oracle.rs
1use serde::{Deserialize, Serialize};
2use steel::*;
3
4use crate::state::oil_oracle_pda;
5
6use super::OilAccount;
7
8/// OIL price oracle (Valiant-backed; updated by centralized authority).
9/// Price is stored as FOGO lamports per 1 OIL: fee_lamports = claimable_atomic * price * 35 / (100 * ONE_OIL).
10#[repr(C)]
11#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
12pub struct OilPriceOracle {
13 /// Price: FOGO lamports per 1 OIL (expo applied separately for scaling; here expo is 0 for this interpretation).
14 pub price: u64,
15 /// Exponent for price (e.g. -9 if price is in FOGO units with 9 decimals). Currently use price as lamports per 1 OIL, expo = 0.
16 pub expo: i32,
17 #[allow(dead_code)]
18 /// Padding for alignment (repr(C) after i32).
19 pub _pad: i32,
20 /// Confidence interval (optional; for future use).
21 pub conf: u64,
22 /// EMA price (optional; for future use).
23 pub ema: u64,
24 /// Unix timestamp when price was last updated.
25 pub publish_time: i64,
26 /// Authority allowed to call SetOilOraclePrice.
27 pub oracle_authority: Pubkey,
28}
29
30impl OilPriceOracle {
31 pub const LEN: usize = 8 + 8 + 4 + 4 + 8 + 8 + 8 + 32; // 8 discriminator? no - we use Pod. So 8+4+4+8+8+8+32 = 72
32
33 pub fn pda() -> (Pubkey, u8) {
34 oil_oracle_pda()
35 }
36
37 /// Set price data (called by SetOilOraclePrice).
38 pub fn set(&mut self, price: u64, expo: i32, conf: u64, ema: u64, publish_time: i64) {
39 self.price = price;
40 self.expo = expo;
41 self.conf = conf;
42 self.ema = ema;
43 self.publish_time = publish_time;
44 }
45
46 /// Required fee in lamports for a given claimable amount (atomic OIL).
47 /// fee = claimable_atomic * price * 35 / (100 * ONE_OIL). Uses expo if needed; with expo=0, price is lamports per 1 OIL.
48 pub fn required_fee_lamports(&self, claimable_atomic: u64) -> u64 {
49 if self.price == 0 {
50 return 0;
51 }
52 // required = claimable_atomic * price * 35 / (100 * ONE_OIL)
53 let one_oil = crate::consts::ONE_OIL as u128;
54 let num = (claimable_atomic as u128)
55 .saturating_mul(self.price as u128)
56 .saturating_mul(35);
57 let den = 100u128.saturating_mul(one_oil);
58 (num / den) as u64
59 }
60}
61
62account!(OilAccount, OilPriceOracle);