Skip to main content

hopper_core/sysvar/
mod.rs

1//! Sysvar readers -- zero-copy Clock and Rent parsing.
2
3mod cache;
4
5pub use cache::{CachedClock, CachedRent, SysvarContext};
6
7use hopper_runtime::error::ProgramError;
8
9/// Clock sysvar fields (from Solana's runtime).
10#[derive(Clone, Copy)]
11pub struct Clock {
12    pub slot: u64,
13    pub epoch_start_timestamp: i64,
14    pub epoch: u64,
15    pub leader_schedule_epoch: u64,
16    pub unix_timestamp: i64,
17}
18
19/// Read the Clock sysvar from account data.
20///
21/// The Clock sysvar is 40 bytes:
22/// `[slot:8][epoch_start_timestamp:8][epoch:8][leader_schedule_epoch:8][unix_timestamp:8]`
23#[inline]
24pub fn read_clock(data: &[u8]) -> Result<Clock, ProgramError> {
25    if data.len() < 40 {
26        return Err(ProgramError::InvalidAccountData);
27    }
28    Ok(Clock {
29        slot: u64::from_le_bytes([
30            data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
31        ]),
32        epoch_start_timestamp: i64::from_le_bytes([
33            data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
34        ]),
35        epoch: u64::from_le_bytes([
36            data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23],
37        ]),
38        leader_schedule_epoch: u64::from_le_bytes([
39            data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31],
40        ]),
41        unix_timestamp: i64::from_le_bytes([
42            data[32], data[33], data[34], data[35], data[36], data[37], data[38], data[39],
43        ]),
44    })
45}
46
47/// Rent sysvar fields.
48#[derive(Clone, Copy)]
49pub struct Rent {
50    pub lamports_per_byte_year: u64,
51    pub exemption_threshold_num: u64,
52    pub exemption_threshold_den: u64,
53    pub burn_percent: u8,
54}
55
56/// Read the Rent sysvar from account data.
57#[inline]
58pub fn read_rent(data: &[u8]) -> Result<Rent, ProgramError> {
59    if data.len() < 25 {
60        return Err(ProgramError::InvalidAccountData);
61    }
62    Ok(Rent {
63        lamports_per_byte_year: u64::from_le_bytes([
64            data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
65        ]),
66        // The exemption threshold is stored as f64 in Solana,
67        // but we decompose to avoid floating-point on-chain.
68        // Standard value: 2.0 years -> we store as 2/1
69        exemption_threshold_num: 2,
70        exemption_threshold_den: 1,
71        burn_percent: data[16],
72    })
73}