solana_bpf_loader_program/syscalls/
sysvar.rs1use super::*;
2
3fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
4 sysvar: Result<Arc<T>, InstructionError>,
5 var_addr: u64,
6 check_aligned: bool,
7 memory_mapping: &mut MemoryMapping,
8 invoke_context: &mut InvokeContext,
9) -> Result<u64, Error> {
10 consume_compute_meter(
11 invoke_context,
12 invoke_context
13 .get_compute_budget()
14 .sysvar_base_cost
15 .saturating_add(size_of::<T>() as u64),
16 )?;
17 let var = translate_type_mut::<T>(memory_mapping, var_addr, check_aligned)?;
18
19 let sysvar: Arc<T> = sysvar?;
24 *var = T::clone(sysvar.as_ref());
25
26 Ok(SUCCESS)
27}
28
29declare_builtin_function!(
30 SyscallGetClockSysvar,
32 fn rust(
33 invoke_context: &mut InvokeContext,
34 var_addr: u64,
35 _arg2: u64,
36 _arg3: u64,
37 _arg4: u64,
38 _arg5: u64,
39 memory_mapping: &mut MemoryMapping,
40 ) -> Result<u64, Error> {
41 get_sysvar(
42 invoke_context.get_sysvar_cache().get_clock(),
43 var_addr,
44 invoke_context.get_check_aligned(),
45 memory_mapping,
46 invoke_context,
47 )
48 }
49);
50
51declare_builtin_function!(
52 SyscallGetEpochScheduleSysvar,
54 fn rust(
55 invoke_context: &mut InvokeContext,
56 var_addr: u64,
57 _arg2: u64,
58 _arg3: u64,
59 _arg4: u64,
60 _arg5: u64,
61 memory_mapping: &mut MemoryMapping,
62 ) -> Result<u64, Error> {
63 get_sysvar(
64 invoke_context.get_sysvar_cache().get_epoch_schedule(),
65 var_addr,
66 invoke_context.get_check_aligned(),
67 memory_mapping,
68 invoke_context,
69 )
70 }
71);
72
73declare_builtin_function!(
74 SyscallGetEpochRewardsSysvar,
76 fn rust(
77 invoke_context: &mut InvokeContext,
78 var_addr: u64,
79 _arg2: u64,
80 _arg3: u64,
81 _arg4: u64,
82 _arg5: u64,
83 memory_mapping: &mut MemoryMapping,
84 ) -> Result<u64, Error> {
85 get_sysvar(
86 invoke_context.get_sysvar_cache().get_epoch_rewards(),
87 var_addr,
88 invoke_context.get_check_aligned(),
89 memory_mapping,
90 invoke_context,
91 )
92 }
93);
94
95declare_builtin_function!(
96 SyscallGetFeesSysvar,
98 fn rust(
99 invoke_context: &mut InvokeContext,
100 var_addr: u64,
101 _arg2: u64,
102 _arg3: u64,
103 _arg4: u64,
104 _arg5: u64,
105 memory_mapping: &mut MemoryMapping,
106 ) -> Result<u64, Error> {
107 #[allow(deprecated)]
108 {
109 get_sysvar(
110 invoke_context.get_sysvar_cache().get_fees(),
111 var_addr,
112 invoke_context.get_check_aligned(),
113 memory_mapping,
114 invoke_context,
115 )
116 }
117 }
118);
119
120declare_builtin_function!(
121 SyscallGetRentSysvar,
123 fn rust(
124 invoke_context: &mut InvokeContext,
125 var_addr: u64,
126 _arg2: u64,
127 _arg3: u64,
128 _arg4: u64,
129 _arg5: u64,
130 memory_mapping: &mut MemoryMapping,
131 ) -> Result<u64, Error> {
132 get_sysvar(
133 invoke_context.get_sysvar_cache().get_rent(),
134 var_addr,
135 invoke_context.get_check_aligned(),
136 memory_mapping,
137 invoke_context,
138 )
139 }
140);
141
142declare_builtin_function!(
143 SyscallGetLastRestartSlotSysvar,
145 fn rust(
146 invoke_context: &mut InvokeContext,
147 var_addr: u64,
148 _arg2: u64,
149 _arg3: u64,
150 _arg4: u64,
151 _arg5: u64,
152 memory_mapping: &mut MemoryMapping,
153 ) -> Result<u64, Error> {
154 get_sysvar(
155 invoke_context.get_sysvar_cache().get_last_restart_slot(),
156 var_addr,
157 invoke_context.get_check_aligned(),
158 memory_mapping,
159 invoke_context,
160 )
161 }
162);
163
164const SYSVAR_NOT_FOUND: u64 = 2;
165const OFFSET_LENGTH_EXCEEDS_SYSVAR: u64 = 1;
166
167declare_builtin_function!(
170 SyscallGetSysvar,
172 fn rust(
173 invoke_context: &mut InvokeContext,
174 sysvar_id_addr: u64,
175 var_addr: u64,
176 offset: u64,
177 length: u64,
178 _arg5: u64,
179 memory_mapping: &mut MemoryMapping,
180 ) -> Result<u64, Error> {
181 let check_aligned = invoke_context.get_check_aligned();
182 let ComputeBudget {
183 sysvar_base_cost,
184 cpi_bytes_per_unit,
185 mem_op_base_cost,
186 ..
187 } = *invoke_context.get_compute_budget();
188
189 let sysvar_id_cost = 32_u64.checked_div(cpi_bytes_per_unit).unwrap_or(0);
191 let sysvar_buf_cost = length.checked_div(cpi_bytes_per_unit).unwrap_or(0);
192 consume_compute_meter(
193 invoke_context,
194 sysvar_base_cost
195 .saturating_add(sysvar_id_cost)
196 .saturating_add(std::cmp::max(sysvar_buf_cost, mem_op_base_cost)),
197 )?;
198
199 let sysvar_id = translate_type::<Pubkey>(memory_mapping, sysvar_id_addr, check_aligned)?;
201
202 let var = translate_slice_mut::<u8>(memory_mapping, var_addr, length, check_aligned)?;
204
205 let offset_length = offset
207 .checked_add(length)
208 .ok_or(InstructionError::ArithmeticOverflow)?;
209
210 let _ = var_addr
212 .checked_add(length)
213 .ok_or(InstructionError::ArithmeticOverflow)?;
214
215 let cache = invoke_context.get_sysvar_cache();
216
217 let sysvar_buf = match cache.sysvar_id_to_buffer(sysvar_id) {
219 None => return Ok(SYSVAR_NOT_FOUND),
220 Some(ref sysvar_buf) => sysvar_buf,
221 };
222
223 if let Some(sysvar_slice) = sysvar_buf.get(offset as usize..offset_length as usize) {
225 var.copy_from_slice(sysvar_slice);
226 } else {
227 return Ok(OFFSET_LENGTH_EXCEEDS_SYSVAR);
228 }
229
230 Ok(SUCCESS)
231 }
232);