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