Skip to main content

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);