1use crate::types::*;
4
5#[derive(Debug)]
7pub struct Error;
8
9mod eth {
10 extern "C" {
11 pub fn ccall(
13 gas: i64,
14 address: *const u8,
15 val_ptr: *const u8,
16 input_ptr: *const u8,
17 input_len: u32,
18 result_ptr: *mut u8,
19 result_len: u32,
20 ) -> i32;
21
22 pub fn dcall(
24 gas: i64,
25 address: *const u8,
26 input_ptr: *const u8,
27 input_len: u32,
28 result_ptr: *mut u8,
29 result_len: u32,
30 ) -> i32;
31
32 pub fn scall(
34 gas: i64,
35 address: *const u8,
36 input_ptr: *const u8,
37 input_len: u32,
38 result_ptr: *mut u8,
39 result_len: u32,
40 ) -> i32;
41
42 pub fn address(dest: *mut u8);
44 pub fn balance(address: *const u8, dest: *mut u8);
45 pub fn blockhash(number: i64, dest: *mut u8);
46 pub fn blocknumber() -> i64;
47 pub fn coinbase(dest: *mut u8);
48 pub fn create(
49 endowment: *const u8,
50 code_ptr: *const u8,
51 code_len: u32,
52 result_ptr: *mut u8,
53 ) -> i32;
54 pub fn create2(
55 endowment: *const u8,
56 salt: *const u8,
57 code_ptr: *const u8,
58 code_len: u32,
59 result_ptr: *mut u8,
60 ) -> i32;
61 pub fn difficulty(dest: *mut u8);
62 pub fn elog(topic_ptr: *const u8, topic_count: u32, data_ptr: *const u8, data_len: u32);
63 pub fn fetch_input(dst: *mut u8);
64 pub fn gasleft() -> i64;
65 pub fn gaslimit(dest: *mut u8);
66 pub fn input_length() -> u32;
67 pub fn origin(dest: *mut u8);
68 pub fn ret(ptr: *const u8, len: u32) -> !;
69 pub fn sender(dest: *mut u8);
70 pub fn suicide(refund: *const u8) -> !;
71 pub fn timestamp() -> i64;
72 pub fn value(dest: *mut u8);
73 }
74}
75
76extern "C" {
77 fn storage_read(key: *const u8, dst: *mut u8);
79 fn storage_write(key: *const u8, src: *const u8);
80}
81
82pub fn suicide(refund: &Address) -> ! {
86 unsafe {
87 eth::suicide(refund.as_ptr());
88 }
89}
90
91pub fn balance(address: &Address) -> U256 {
96 unsafe { fetch_u256(|x| eth::balance(address.as_ptr(), x)) }
97}
98
99pub fn create(endowment: U256, code: &[u8]) -> Result<Address, Error> {
107 let mut endowment_arr = [0u8; 32];
108 endowment.to_big_endian(&mut endowment_arr);
109 let mut result = Address::zero();
110 unsafe {
111 if eth::create(
112 endowment_arr.as_ptr(),
113 code.as_ptr(),
114 code.len() as u32,
115 (&mut result).as_mut_ptr(),
116 ) == 0
117 {
118 Ok(result)
119 } else {
120 Err(Error)
121 }
122 }
123}
124
125pub fn create2(endowment: U256, salt: H256, code: &[u8]) -> Result<Address, Error> {
133 let mut endowment_arr = [0u8; 32];
134 endowment.to_big_endian(&mut endowment_arr);
135 let mut result = Address::zero();
136 unsafe {
137 if eth::create2(
138 endowment_arr.as_ptr(),
139 salt.as_ptr(),
140 code.as_ptr(),
141 code.len() as u32,
142 (&mut result).as_mut_ptr(),
143 ) == 0
144 {
145 Ok(result)
146 } else {
147 Err(Error)
148 }
149 }
150}
151
152pub fn call(
166 gas: u64,
167 address: &Address,
168 value: U256,
169 input: &[u8],
170 result: &mut [u8],
171) -> Result<(), Error> {
172 let mut value_arr = [0u8; 32];
173 value.to_big_endian(&mut value_arr);
174 unsafe {
175 if eth::ccall(
176 gas as i64,
177 address.as_ptr(),
178 value_arr.as_ptr(),
179 input.as_ptr(),
180 input.len() as u32,
181 result.as_mut_ptr(),
182 result.len() as u32,
183 ) == 0
184 {
185 Ok(())
186 } else {
187 Err(Error)
188 }
189 }
190}
191
192pub fn call_code(
199 gas: u64,
200 address: &Address,
201 input: &[u8],
202 result: &mut [u8],
203) -> Result<(), Error> {
204 unsafe {
205 if eth::dcall(
206 gas as i64,
207 address.as_ptr(),
208 input.as_ptr(),
209 input.len() as u32,
210 result.as_mut_ptr(),
211 result.len() as u32,
212 ) == 0
213 {
214 Ok(())
215 } else {
216 Err(Error)
217 }
218 }
219}
220
221pub fn static_call(
227 gas: u64,
228 address: &Address,
229 input: &[u8],
230 result: &mut [u8],
231) -> Result<(), Error> {
232 unsafe {
233 if eth::scall(
234 gas as i64,
235 address.as_ptr(),
236 input.as_ptr(),
237 input.len() as u32,
238 result.as_mut_ptr(),
239 result.len() as u32,
240 ) == 0
241 {
242 Ok(())
243 } else {
244 Err(Error)
245 }
246 }
247}
248
249pub fn block_hash(block_number: u64) -> H256 {
254 let mut res = H256::zero();
255 unsafe { eth::blockhash(block_number as i64, res.as_mut_ptr()) }
256 res
257}
258
259pub fn coinbase() -> Address {
261 unsafe { fetch_address(|x| eth::coinbase(x)) }
262}
263
264pub fn timestamp() -> u64 {
269 unsafe { eth::timestamp() as u64 }
270}
271
272pub fn block_number() -> u64 {
277 unsafe { eth::blocknumber() as u64 }
278}
279
280pub fn difficulty() -> U256 {
282 unsafe { fetch_u256(|x| eth::difficulty(x)) }
283}
284
285pub fn gas_limit() -> U256 {
287 unsafe { fetch_u256(|x| eth::gaslimit(x)) }
288}
289
290pub fn gas_left() -> u64 {
292 unsafe { eth::gasleft() as u64 }
293}
294
295pub fn sender() -> Address {
300 unsafe { fetch_address(|x| eth::sender(x)) }
301}
302
303pub fn origin() -> Address {
308 unsafe { fetch_address(|x| eth::origin(x)) }
309}
310
311pub fn value() -> U256 {
313 unsafe { fetch_u256(|x| eth::value(x)) }
314}
315
316pub fn address() -> Address {
318 unsafe { fetch_address(|x| eth::address(x)) }
319}
320
321pub fn log(topics: &[H256], data: &[u8]) {
329 unsafe {
330 eth::elog(
331 topics.as_ptr() as *const u8,
332 topics.len() as u32,
333 data.as_ptr(),
334 data.len() as u32,
335 );
336 }
337}
338
339pub fn input() -> Vec<u8> {
343 let len = unsafe { eth::input_length() };
344
345 match len {
346 0 => Vec::new(),
347 non_zero => {
348 let mut data = Vec::with_capacity(non_zero as usize);
349 unsafe {
350 data.set_len(non_zero as usize);
351 eth::fetch_input(data.as_mut_ptr());
352 }
353 data
354 }
355 }
356}
357
358pub fn ret(data: &[u8]) -> ! {
363 unsafe {
364 eth::ret(data.as_ptr(), data.len() as u32);
365 }
366}
367
368pub fn read(key: &H256) -> [u8; 32] {
370 let mut dst = [0u8; 32];
371 unsafe {
372 storage_read(key.as_ptr(), dst.as_mut_ptr());
373 }
374 dst
375}
376
377pub fn write(key: &H256, val: &[u8; 32]) {
379 unsafe {
380 storage_write(key.as_ptr(), val.as_ptr());
381 }
382}
383
384unsafe fn fetch_address<F: Fn(*mut u8)>(f: F) -> Address {
385 let mut res = Address::zero();
386 f(res.as_mut_ptr());
387 res
388}
389
390unsafe fn fetch_u256<F: Fn(*mut u8)>(f: F) -> U256 {
391 let mut res = [0u8; 32];
392 f(res.as_mut_ptr());
393 U256::from_big_endian(&res)
394}