1mod container;
12mod types;
13
14pub use container::EvmcContainer;
15pub use evmc_sys as ffi;
16pub use types::*;
17
18pub trait EvmcVm {
20 fn init() -> Self;
22 fn execute<'a>(
24 &self,
25 revision: Revision,
26 code: &'a [u8],
27 message: &'a ExecutionMessage,
28 context: Option<&'a mut ExecutionContext<'a>>,
29 ) -> ExecutionResult;
30}
31
32#[derive(Debug)]
34pub struct ExecutionResult {
35 status_code: StatusCode,
36 gas_left: i64,
37 output: Option<Vec<u8>>,
38 create_address: Option<Address>,
39}
40
41#[derive(Debug)]
43pub struct ExecutionMessage {
44 kind: MessageKind,
45 flags: u32,
46 depth: i32,
47 gas: i64,
48 destination: Address,
49 sender: Address,
50 input: Option<Vec<u8>>,
51 value: Uint256,
52 create2_salt: Bytes32,
53}
54
55pub type ExecutionTxContext = ffi::evmc_tx_context;
57
58pub struct ExecutionContext<'a> {
61 host: &'a ffi::evmc_host_interface,
62 context: *mut ffi::evmc_host_context,
63 tx_context: ExecutionTxContext,
64}
65
66impl ExecutionResult {
67 pub fn new(_status_code: StatusCode, _gas_left: i64, _output: Option<&[u8]>) -> Self {
69 ExecutionResult {
70 status_code: _status_code,
71 gas_left: _gas_left,
72 output: if let Some(output) = _output {
73 Some(output.to_vec())
74 } else {
75 None
76 },
77 create_address: None,
78 }
79 }
80
81 pub fn failure() -> Self {
83 ExecutionResult::new(StatusCode::EVMC_FAILURE, 0, None)
84 }
85
86 pub fn revert(_gas_left: i64, _output: Option<&[u8]>) -> Self {
88 ExecutionResult::new(StatusCode::EVMC_REVERT, _gas_left, _output)
89 }
90
91 pub fn success(_gas_left: i64, _output: Option<&[u8]>) -> Self {
93 ExecutionResult::new(StatusCode::EVMC_SUCCESS, _gas_left, _output)
94 }
95
96 pub fn status_code(&self) -> StatusCode {
98 self.status_code
99 }
100
101 pub fn gas_left(&self) -> i64 {
103 self.gas_left
104 }
105
106 pub fn output(&self) -> Option<&Vec<u8>> {
108 self.output.as_ref()
109 }
110
111 pub fn create_address(&self) -> Option<&Address> {
114 self.create_address.as_ref()
115 }
116}
117
118impl ExecutionMessage {
119 pub fn new(
120 kind: MessageKind,
121 flags: u32,
122 depth: i32,
123 gas: i64,
124 destination: Address,
125 sender: Address,
126 input: Option<&[u8]>,
127 value: Uint256,
128 create2_salt: Bytes32,
129 ) -> Self {
130 ExecutionMessage {
131 kind,
132 flags,
133 depth,
134 gas,
135 destination,
136 sender,
137 input: if let Some(input) = input {
138 Some(input.to_vec())
139 } else {
140 None
141 },
142 value,
143 create2_salt,
144 }
145 }
146
147 pub fn kind(&self) -> MessageKind {
149 self.kind
150 }
151
152 pub fn flags(&self) -> u32 {
154 self.flags
155 }
156
157 pub fn depth(&self) -> i32 {
159 self.depth
160 }
161
162 pub fn gas(&self) -> i64 {
164 self.gas
165 }
166
167 pub fn destination(&self) -> &Address {
169 &self.destination
170 }
171
172 pub fn sender(&self) -> &Address {
174 &self.sender
175 }
176
177 pub fn input(&self) -> Option<&Vec<u8>> {
179 self.input.as_ref()
180 }
181
182 pub fn value(&self) -> &Uint256 {
184 &self.value
185 }
186
187 pub fn create2_salt(&self) -> &Bytes32 {
189 &self.create2_salt
190 }
191}
192
193impl<'a> ExecutionContext<'a> {
194 pub fn new(host: &'a ffi::evmc_host_interface, _context: *mut ffi::evmc_host_context) -> Self {
195 let _tx_context = unsafe {
196 assert!((*host).get_tx_context.is_some());
197 (*host).get_tx_context.unwrap()(_context)
198 };
199
200 ExecutionContext {
201 host: host,
202 context: _context,
203 tx_context: _tx_context,
204 }
205 }
206
207 pub fn get_tx_context(&self) -> &ExecutionTxContext {
209 &self.tx_context
210 }
211
212 pub fn account_exists(&self, address: &Address) -> bool {
214 unsafe {
215 assert!((*self.host).account_exists.is_some());
216 (*self.host).account_exists.unwrap()(self.context, address as *const Address)
217 }
218 }
219
220 pub fn get_storage(&self, address: &Address, key: &Bytes32) -> Bytes32 {
222 unsafe {
223 assert!((*self.host).get_storage.is_some());
224 (*self.host).get_storage.unwrap()(
225 self.context,
226 address as *const Address,
227 key as *const Bytes32,
228 )
229 }
230 }
231
232 pub fn set_storage(
234 &mut self,
235 address: &Address,
236 key: &Bytes32,
237 value: &Bytes32,
238 ) -> StorageStatus {
239 unsafe {
240 assert!((*self.host).set_storage.is_some());
241 (*self.host).set_storage.unwrap()(
242 self.context,
243 address as *const Address,
244 key as *const Bytes32,
245 value as *const Bytes32,
246 )
247 }
248 }
249
250 pub fn get_balance(&self, address: &Address) -> Uint256 {
252 unsafe {
253 assert!((*self.host).get_balance.is_some());
254 (*self.host).get_balance.unwrap()(self.context, address as *const Address)
255 }
256 }
257
258 pub fn get_code_size(&self, address: &Address) -> usize {
260 unsafe {
261 assert!((*self.host).get_code_size.is_some());
262 (*self.host).get_code_size.unwrap()(self.context, address as *const Address)
263 }
264 }
265
266 pub fn get_code_hash(&self, address: &Address) -> Bytes32 {
268 unsafe {
269 assert!((*self.host).get_code_size.is_some());
270 (*self.host).get_code_hash.unwrap()(self.context, address as *const Address)
271 }
272 }
273
274 pub fn copy_code(&self, address: &Address, code_offset: usize, buffer: &mut [u8]) -> usize {
276 unsafe {
277 assert!((*self.host).copy_code.is_some());
278 (*self.host).copy_code.unwrap()(
279 self.context,
280 address as *const Address,
281 code_offset,
282 buffer.as_mut_ptr(),
284 buffer.len(),
285 )
286 }
287 }
288
289 pub fn selfdestruct(&mut self, address: &Address, beneficiary: &Address) {
291 unsafe {
292 assert!((*self.host).selfdestruct.is_some());
293 (*self.host).selfdestruct.unwrap()(
294 self.context,
295 address as *const Address,
296 beneficiary as *const Address,
297 )
298 }
299 }
300
301 pub fn call(&mut self, message: &ExecutionMessage) -> ExecutionResult {
303 let input = message.input();
306 let input_size = if let Some(input) = input {
307 input.len()
308 } else {
309 0
310 };
311 let input_data = if let Some(input) = input {
312 input.as_ptr()
313 } else {
314 std::ptr::null() as *const u8
315 };
316 let message = ffi::evmc_message {
319 kind: message.kind(),
320 flags: message.flags(),
321 depth: message.depth(),
322 gas: message.gas(),
323 destination: *message.destination(),
324 sender: *message.sender(),
325 input_data: input_data,
326 input_size: input_size,
327 value: *message.value(),
328 create2_salt: *message.create2_salt(),
329 };
330 unsafe {
331 assert!((*self.host).call.is_some());
332 (*self.host).call.unwrap()(self.context, &message as *const ffi::evmc_message).into()
333 }
334 }
335
336 pub fn get_block_hash(&self, num: i64) -> Bytes32 {
338 unsafe {
339 assert!((*self.host).get_block_hash.is_some());
340 (*self.host).get_block_hash.unwrap()(self.context, num)
341 }
342 }
343
344 pub fn emit_log(&mut self, address: &Address, data: &[u8], topics: &[Bytes32]) {
346 unsafe {
347 assert!((*self.host).emit_log.is_some());
348 (*self.host).emit_log.unwrap()(
349 self.context,
350 address as *const Address,
351 data.as_ptr(),
353 data.len(),
354 topics.as_ptr(),
355 topics.len(),
356 )
357 }
358 }
359
360 pub fn access_account(&mut self, address: &Address) -> AccessStatus {
362 unsafe {
363 assert!((*self.host).access_account.is_some());
364 (*self.host).access_account.unwrap()(self.context, address as *const Address)
365 }
366 }
367
368 pub fn access_storage(&mut self, address: &Address, key: &Bytes32) -> AccessStatus {
370 unsafe {
371 assert!((*self.host).access_storage.is_some());
372 (*self.host).access_storage.unwrap()(
373 self.context,
374 address as *const Address,
375 key as *const Bytes32,
376 )
377 }
378 }
379}
380
381impl From<ffi::evmc_result> for ExecutionResult {
382 fn from(result: ffi::evmc_result) -> Self {
383 let ret = ExecutionResult {
384 status_code: result.status_code,
385 gas_left: result.gas_left,
386 output: if result.output_data.is_null() {
387 assert_eq!(result.output_size, 0);
388 None
389 } else if result.output_size == 0 {
390 None
391 } else {
392 Some(from_buf_raw::<u8>(result.output_data, result.output_size))
393 },
394 create_address: Some(result.create_address),
396 };
397
398 if result.release.is_some() {
400 unsafe {
401 result.release.unwrap()(&result as *const ffi::evmc_result);
402 }
403 }
404
405 ret
406 }
407}
408
409fn allocate_output_data(output: Option<&Vec<u8>>) -> (*const u8, usize) {
410 if let Some(buf) = output {
411 let buf_len = buf.len();
412
413 let memlayout = std::alloc::Layout::from_size_align(buf_len, 1).expect("Bad layout");
415 let new_buf = unsafe { std::alloc::alloc(memlayout) };
416 unsafe {
417 std::ptr::copy(buf.as_ptr(), new_buf, buf_len);
419 }
420
421 (new_buf as *const u8, buf_len)
422 } else {
423 (std::ptr::null(), 0)
424 }
425}
426
427unsafe fn deallocate_output_data(ptr: *const u8, size: usize) {
428 if !ptr.is_null() {
429 let buf_layout = std::alloc::Layout::from_size_align(size, 1).expect("Bad layout");
430 std::alloc::dealloc(ptr as *mut u8, buf_layout);
431 }
432}
433
434impl Into<*const ffi::evmc_result> for ExecutionResult {
436 fn into(self) -> *const ffi::evmc_result {
437 let mut result: ffi::evmc_result = self.into();
438 result.release = Some(release_heap_result);
439 Box::into_raw(Box::new(result))
440 }
441}
442
443extern "C" fn release_heap_result(result: *const ffi::evmc_result) {
445 unsafe {
446 let tmp = Box::from_raw(result as *mut ffi::evmc_result);
447 deallocate_output_data(tmp.output_data, tmp.output_size);
448 }
449}
450
451impl Into<ffi::evmc_result> for ExecutionResult {
453 fn into(self) -> ffi::evmc_result {
454 let (buffer, len) = allocate_output_data(self.output.as_ref());
455 ffi::evmc_result {
456 status_code: self.status_code,
457 gas_left: self.gas_left,
458 output_data: buffer,
459 output_size: len,
460 release: Some(release_stack_result),
461 create_address: if self.create_address.is_some() {
462 self.create_address.unwrap()
463 } else {
464 Address { bytes: [0u8; 20] }
465 },
466 padding: [0u8; 4],
467 }
468 }
469}
470
471extern "C" fn release_stack_result(result: *const ffi::evmc_result) {
473 unsafe {
474 let tmp = *result;
475 deallocate_output_data(tmp.output_data, tmp.output_size);
476 }
477}
478
479impl From<&ffi::evmc_message> for ExecutionMessage {
480 fn from(message: &ffi::evmc_message) -> Self {
481 ExecutionMessage {
482 kind: message.kind,
483 flags: message.flags,
484 depth: message.depth,
485 gas: message.gas,
486 destination: message.destination,
487 sender: message.sender,
488 input: if message.input_data.is_null() {
489 assert_eq!(message.input_size, 0);
490 None
491 } else if message.input_size == 0 {
492 None
493 } else {
494 Some(from_buf_raw::<u8>(message.input_data, message.input_size))
495 },
496 value: message.value,
497 create2_salt: message.create2_salt,
498 }
499 }
500}
501
502fn from_buf_raw<T>(ptr: *const T, size: usize) -> Vec<T> {
503 let mut buf = Vec::with_capacity(size);
505 unsafe {
506 buf.set_len(size);
508 std::ptr::copy(ptr, buf.as_mut_ptr(), size);
510 }
511 buf
512}
513
514#[cfg(test)]
515mod tests {
516 use super::*;
517
518 #[test]
519 fn result_new() {
520 let r = ExecutionResult::new(StatusCode::EVMC_FAILURE, 420, None);
521
522 assert_eq!(r.status_code(), StatusCode::EVMC_FAILURE);
523 assert_eq!(r.gas_left(), 420);
524 assert!(r.output().is_none());
525 assert!(r.create_address().is_none());
526 }
527
528 extern "C" fn test_result_dispose(result: *const ffi::evmc_result) {
530 unsafe {
531 if !result.is_null() {
532 let owned = *result;
533 Vec::from_raw_parts(
534 owned.output_data as *mut u8,
535 owned.output_size,
536 owned.output_size,
537 );
538 }
539 }
540 }
541
542 #[test]
543 fn result_from_ffi() {
544 let f = ffi::evmc_result {
545 status_code: StatusCode::EVMC_SUCCESS,
546 gas_left: 1337,
547 output_data: Box::into_raw(Box::new([0xde, 0xad, 0xbe, 0xef])) as *const u8,
548 output_size: 4,
549 release: Some(test_result_dispose),
550 create_address: Address { bytes: [0u8; 20] },
551 padding: [0u8; 4],
552 };
553
554 let r: ExecutionResult = f.into();
555
556 assert_eq!(r.status_code(), StatusCode::EVMC_SUCCESS);
557 assert_eq!(r.gas_left(), 1337);
558 assert!(r.output().is_some());
559 assert_eq!(r.output().unwrap().len(), 4);
560 assert!(r.create_address().is_some());
561 }
562
563 #[test]
564 fn result_into_heap_ffi() {
565 let r = ExecutionResult::new(
566 StatusCode::EVMC_FAILURE,
567 420,
568 Some(&[0xc0, 0xff, 0xee, 0x71, 0x75]),
569 );
570
571 let f: *const ffi::evmc_result = r.into();
572 assert!(!f.is_null());
573 unsafe {
574 assert_eq!((*f).status_code, StatusCode::EVMC_FAILURE);
575 assert_eq!((*f).gas_left, 420);
576 assert!(!(*f).output_data.is_null());
577 assert_eq!((*f).output_size, 5);
578 assert_eq!(
579 std::slice::from_raw_parts((*f).output_data, 5) as &[u8],
580 &[0xc0, 0xff, 0xee, 0x71, 0x75]
581 );
582 assert_eq!((*f).create_address.bytes, [0u8; 20]);
583 if (*f).release.is_some() {
584 (*f).release.unwrap()(f);
585 }
586 }
587 }
588
589 #[test]
590 fn result_into_heap_ffi_empty_data() {
591 let r = ExecutionResult::new(StatusCode::EVMC_FAILURE, 420, None);
592
593 let f: *const ffi::evmc_result = r.into();
594 assert!(!f.is_null());
595 unsafe {
596 assert_eq!((*f).status_code, StatusCode::EVMC_FAILURE);
597 assert_eq!((*f).gas_left, 420);
598 assert!((*f).output_data.is_null());
599 assert_eq!((*f).output_size, 0);
600 assert_eq!((*f).create_address.bytes, [0u8; 20]);
601 if (*f).release.is_some() {
602 (*f).release.unwrap()(f);
603 }
604 }
605 }
606
607 #[test]
608 fn result_into_stack_ffi() {
609 let r = ExecutionResult::new(
610 StatusCode::EVMC_FAILURE,
611 420,
612 Some(&[0xc0, 0xff, 0xee, 0x71, 0x75]),
613 );
614
615 let f: ffi::evmc_result = r.into();
616 unsafe {
617 assert_eq!(f.status_code, StatusCode::EVMC_FAILURE);
618 assert_eq!(f.gas_left, 420);
619 assert!(!f.output_data.is_null());
620 assert_eq!(f.output_size, 5);
621 assert_eq!(
622 std::slice::from_raw_parts(f.output_data, 5) as &[u8],
623 &[0xc0, 0xff, 0xee, 0x71, 0x75]
624 );
625 assert_eq!(f.create_address.bytes, [0u8; 20]);
626 if f.release.is_some() {
627 f.release.unwrap()(&f);
628 }
629 }
630 }
631
632 #[test]
633 fn result_into_stack_ffi_empty_data() {
634 let r = ExecutionResult::new(StatusCode::EVMC_FAILURE, 420, None);
635
636 let f: ffi::evmc_result = r.into();
637 unsafe {
638 assert_eq!(f.status_code, StatusCode::EVMC_FAILURE);
639 assert_eq!(f.gas_left, 420);
640 assert!(f.output_data.is_null());
641 assert_eq!(f.output_size, 0);
642 assert_eq!(f.create_address.bytes, [0u8; 20]);
643 if f.release.is_some() {
644 f.release.unwrap()(&f);
645 }
646 }
647 }
648
649 #[test]
650 fn message_new_with_input() {
651 let input = vec![0xc0, 0xff, 0xee];
652 let destination = Address { bytes: [32u8; 20] };
653 let sender = Address { bytes: [128u8; 20] };
654 let value = Uint256 { bytes: [0u8; 32] };
655 let create2_salt = Bytes32 { bytes: [255u8; 32] };
656
657 let ret = ExecutionMessage::new(
658 MessageKind::EVMC_CALL,
659 44,
660 66,
661 4466,
662 destination,
663 sender,
664 Some(&input),
665 value,
666 create2_salt,
667 );
668
669 assert_eq!(ret.kind(), MessageKind::EVMC_CALL);
670 assert_eq!(ret.flags(), 44);
671 assert_eq!(ret.depth(), 66);
672 assert_eq!(ret.gas(), 4466);
673 assert_eq!(*ret.destination(), destination);
674 assert_eq!(*ret.sender(), sender);
675 assert!(ret.input().is_some());
676 assert_eq!(*ret.input().unwrap(), input);
677 assert_eq!(*ret.value(), value);
678 assert_eq!(*ret.create2_salt(), create2_salt);
679 }
680
681 #[test]
682 fn message_from_ffi() {
683 let destination = Address { bytes: [32u8; 20] };
684 let sender = Address { bytes: [128u8; 20] };
685 let value = Uint256 { bytes: [0u8; 32] };
686 let create2_salt = Bytes32 { bytes: [255u8; 32] };
687
688 let msg = ffi::evmc_message {
689 kind: MessageKind::EVMC_CALL,
690 flags: 44,
691 depth: 66,
692 gas: 4466,
693 destination: destination,
694 sender: sender,
695 input_data: std::ptr::null(),
696 input_size: 0,
697 value: value,
698 create2_salt: create2_salt,
699 };
700
701 let ret: ExecutionMessage = (&msg).into();
702
703 assert_eq!(ret.kind(), msg.kind);
704 assert_eq!(ret.flags(), msg.flags);
705 assert_eq!(ret.depth(), msg.depth);
706 assert_eq!(ret.gas(), msg.gas);
707 assert_eq!(*ret.destination(), msg.destination);
708 assert_eq!(*ret.sender(), msg.sender);
709 assert!(ret.input().is_none());
710 assert_eq!(*ret.value(), msg.value);
711 assert_eq!(*ret.create2_salt(), msg.create2_salt);
712 }
713
714 #[test]
715 fn message_from_ffi_with_input() {
716 let input = vec![0xc0, 0xff, 0xee];
717 let destination = Address { bytes: [32u8; 20] };
718 let sender = Address { bytes: [128u8; 20] };
719 let value = Uint256 { bytes: [0u8; 32] };
720 let create2_salt = Bytes32 { bytes: [255u8; 32] };
721
722 let msg = ffi::evmc_message {
723 kind: MessageKind::EVMC_CALL,
724 flags: 44,
725 depth: 66,
726 gas: 4466,
727 destination: destination,
728 sender: sender,
729 input_data: input.as_ptr(),
730 input_size: input.len(),
731 value: value,
732 create2_salt: create2_salt,
733 };
734
735 let ret: ExecutionMessage = (&msg).into();
736
737 assert_eq!(ret.kind(), msg.kind);
738 assert_eq!(ret.flags(), msg.flags);
739 assert_eq!(ret.depth(), msg.depth);
740 assert_eq!(ret.gas(), msg.gas);
741 assert_eq!(*ret.destination(), msg.destination);
742 assert_eq!(*ret.sender(), msg.sender);
743 assert!(ret.input().is_some());
744 assert_eq!(*ret.input().unwrap(), input);
745 assert_eq!(*ret.value(), msg.value);
746 assert_eq!(*ret.create2_salt(), msg.create2_salt);
747 }
748
749 unsafe extern "C" fn get_dummy_tx_context(
750 _context: *mut ffi::evmc_host_context,
751 ) -> ffi::evmc_tx_context {
752 ffi::evmc_tx_context {
753 tx_gas_price: Uint256 { bytes: [0u8; 32] },
754 tx_origin: Address { bytes: [0u8; 20] },
755 block_coinbase: Address { bytes: [0u8; 20] },
756 block_number: 42,
757 block_timestamp: 235117,
758 block_gas_limit: 105023,
759 block_difficulty: Uint256 { bytes: [0xaa; 32] },
760 chain_id: Uint256::default(),
761 block_base_fee: Uint256::default(),
762 }
763 }
764
765 unsafe extern "C" fn get_dummy_code_size(
766 _context: *mut ffi::evmc_host_context,
767 _addr: *const Address,
768 ) -> usize {
769 105023 as usize
770 }
771
772 unsafe extern "C" fn execute_call(
773 _context: *mut ffi::evmc_host_context,
774 _msg: *const ffi::evmc_message,
775 ) -> ffi::evmc_result {
776 let msg = *_msg;
778 let success = if msg.input_size != 0 && msg.input_data == std::ptr::null() {
779 false
780 } else if msg.input_size == 0 && msg.input_data != std::ptr::null() {
781 false
782 } else {
783 true
784 };
785
786 ffi::evmc_result {
787 status_code: if success {
788 StatusCode::EVMC_SUCCESS
789 } else {
790 StatusCode::EVMC_INTERNAL_ERROR
791 },
792 gas_left: 2,
793 output_data: msg.input_data,
795 output_size: msg.input_size,
796 release: None,
797 create_address: Address::default(),
798 padding: [0u8; 4],
799 }
800 }
801
802 fn get_dummy_host_interface() -> ffi::evmc_host_interface {
804 ffi::evmc_host_interface {
805 account_exists: None,
806 get_storage: None,
807 set_storage: None,
808 get_balance: None,
809 get_code_size: Some(get_dummy_code_size),
810 get_code_hash: None,
811 copy_code: None,
812 selfdestruct: None,
813 call: Some(execute_call),
814 get_tx_context: Some(get_dummy_tx_context),
815 get_block_hash: None,
816 emit_log: None,
817 access_account: None,
818 access_storage: None,
819 }
820 }
821
822 #[test]
823 fn execution_context() {
824 let host_context = std::ptr::null_mut();
825 let host_interface = get_dummy_host_interface();
826 let exe_context = ExecutionContext::new(&host_interface, host_context);
827 let a = exe_context.get_tx_context();
828
829 let b = unsafe { get_dummy_tx_context(host_context) };
830
831 assert_eq!(a.block_gas_limit, b.block_gas_limit);
832 assert_eq!(a.block_timestamp, b.block_timestamp);
833 assert_eq!(a.block_number, b.block_number);
834 }
835
836 #[test]
837 fn get_code_size() {
838 let test_addr = Address { bytes: [0u8; 20] };
840 let host = get_dummy_host_interface();
841 let host_context = std::ptr::null_mut();
842
843 let mut exe_context = ExecutionContext::new(&host, host_context);
844
845 let a: usize = 105023;
846 let b = exe_context.get_code_size(&test_addr);
847
848 assert_eq!(a, b);
849 }
850
851 #[test]
852 fn test_call_empty_data() {
853 let test_addr = Address::default();
855 let host = get_dummy_host_interface();
856 let host_context = std::ptr::null_mut();
857 let mut exe_context = ExecutionContext::new(&host, host_context);
858
859 let message = ExecutionMessage::new(
860 MessageKind::EVMC_CALL,
861 0,
862 0,
863 6566,
864 test_addr,
865 test_addr,
866 None,
867 Uint256::default(),
868 Bytes32::default(),
869 );
870
871 let b = exe_context.call(&message);
872
873 assert_eq!(b.status_code(), StatusCode::EVMC_SUCCESS);
874 assert_eq!(b.gas_left(), 2);
875 assert!(b.output().is_none());
876 assert!(b.create_address().is_some());
877 assert_eq!(b.create_address().unwrap(), &Address::default());
878 }
879
880 #[test]
881 fn test_call_with_data() {
882 let test_addr = Address::default();
884 let host = get_dummy_host_interface();
885 let host_context = std::ptr::null_mut();
886 let mut exe_context = ExecutionContext::new(&host, host_context);
887
888 let data = vec![0xc0, 0xff, 0xfe];
889
890 let message = ExecutionMessage::new(
891 MessageKind::EVMC_CALL,
892 0,
893 0,
894 6566,
895 test_addr,
896 test_addr,
897 Some(&data),
898 Uint256::default(),
899 Bytes32::default(),
900 );
901
902 let b = exe_context.call(&message);
903
904 assert_eq!(b.status_code(), StatusCode::EVMC_SUCCESS);
905 assert_eq!(b.gas_left(), 2);
906 assert!(b.output().is_some());
907 assert_eq!(b.output().unwrap(), &data);
908 assert!(b.create_address().is_some());
909 assert_eq!(b.create_address().unwrap(), &Address::default());
910 }
911}