1use crate::address::Address;
8use crate::error::ProgramError;
9
10#[repr(C)]
14#[derive(Clone, Copy, Debug, Default)]
15pub struct Clock {
16 pub slot: u64,
17 pub epoch_start_timestamp: i64,
18 pub epoch: u64,
19 pub leader_schedule_epoch: u64,
20 pub unix_timestamp: i64,
21}
22
23#[inline]
25pub fn get_clock() -> Result<Clock, ProgramError> {
26 #[allow(unused_mut)]
27 let mut clock = Clock::default();
28
29 #[cfg(target_os = "solana")]
30 {
31 let rc =
32 unsafe { crate::syscalls::sol_get_clock_sysvar(&mut clock as *mut Clock as *mut u8) };
33 if rc != 0 {
34 return Err(ProgramError::UnsupportedSysvar);
35 }
36 }
37
38 Ok(clock)
39}
40
41#[repr(C)]
45#[derive(Clone, Copy, Debug, Default)]
46pub struct Rent {
47 pub lamports_per_byte_year: u64,
48 pub exemption_threshold: f64,
49 pub burn_percent: u8,
50}
51
52#[inline]
54pub fn get_rent() -> Result<Rent, ProgramError> {
55 #[allow(unused_mut)]
56 let mut rent = Rent::default();
57
58 #[cfg(target_os = "solana")]
59 {
60 let rc = unsafe { crate::syscalls::sol_get_rent_sysvar(&mut rent as *mut Rent as *mut u8) };
61 if rc != 0 {
62 return Err(ProgramError::UnsupportedSysvar);
63 }
64 }
65
66 Ok(rent)
67}
68
69impl Rent {
70 #[inline]
72 pub fn minimum_balance(&self, data_len: usize) -> u64 {
73 let total_size = (data_len as u64).saturating_add(128);
75 let lamports =
76 (total_size as f64) * self.lamports_per_byte_year as f64 * self.exemption_threshold;
77 lamports as u64
78 }
79}
80
81#[repr(C)]
88#[derive(Clone, Copy, Debug, Default)]
89pub struct EpochSchedule {
90 pub slots_per_epoch: u64,
91 pub leader_schedule_slot_offset: u64,
92 pub warmup: bool,
93 pub first_normal_epoch: u64,
94 pub first_normal_slot: u64,
95}
96
97#[inline]
99pub fn get_epoch_schedule() -> Result<EpochSchedule, ProgramError> {
100 #[allow(unused_mut)]
101 let mut schedule = EpochSchedule::default();
102
103 #[cfg(target_os = "solana")]
104 {
105 let rc = unsafe {
106 crate::syscalls::sol_get_epoch_schedule_sysvar(
107 &mut schedule as *mut EpochSchedule as *mut u8,
108 )
109 };
110 if rc != 0 {
111 return Err(ProgramError::UnsupportedSysvar);
112 }
113 }
114
115 Ok(schedule)
116}
117
118impl EpochSchedule {
119 #[inline]
121 pub fn get_epoch(&self, slot: u64) -> u64 {
122 if slot < self.first_normal_slot {
123 if slot == 0 {
126 return 0;
127 }
128 let mut epoch_len: u64 = 32; let mut epoch: u64 = 0;
131 let mut slot_remaining = slot;
132 while slot_remaining >= epoch_len {
133 slot_remaining -= epoch_len;
134 epoch += 1;
135 epoch_len = epoch_len.saturating_mul(2);
136 }
137 epoch
138 } else {
139 let normal_slot_index = slot - self.first_normal_slot;
140 self.first_normal_epoch + normal_slot_index / self.slots_per_epoch
141 }
142 }
143
144 #[inline]
146 pub fn get_first_slot_in_epoch(&self, epoch: u64) -> u64 {
147 if epoch <= self.first_normal_epoch {
148 if epoch == 0 {
150 return 0;
151 }
152 let shift = epoch.min(63);
155 32_u64.saturating_mul((1_u64 << shift).saturating_sub(1))
156 } else {
157 let normal_epoch_index = epoch - self.first_normal_epoch;
158 self.first_normal_slot + normal_epoch_index * self.slots_per_epoch
159 }
160 }
161}
162
163pub const CLOCK_ID: Address = crate::address!("SysvarC1ock11111111111111111111111111111111");
167
168pub const RENT_ID: Address = crate::address!("SysvarRent111111111111111111111111111111111");
170
171pub const EPOCH_SCHEDULE_ID: Address =
173 crate::address!("SysvarEpochSchedu1e111111111111111111111111");