1#![no_std]
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8
9use bobcat_maths::U;
10
11pub type Address = [u8; 20];
12
13#[cfg(target_arch = "wasm32")]
14mod impls {
15 #[link(wasm_import_module = "vm_hooks")]
16 unsafe extern "C" {
17 pub(crate) fn create1(
18 code: *const u8,
19 code_len: usize,
20 endowment: *const u8,
21 contract: *mut u8,
22 revert_data_len: *mut usize,
23 );
24
25 pub(crate) fn create2(
26 code: *const u8,
27 code_len: usize,
28 endowment: *const u8,
29 salt: *const u8,
30 contract: *mut u8,
31 revert_data_len: *mut usize,
32 );
33
34 pub(crate) fn read_return_data(dest: *mut u8, offset: usize, size: usize) -> usize;
35 }
36}
37
38#[cfg(not(target_arch = "wasm32"))]
39mod impls {
40 pub(crate) unsafe fn create1(
43 _code: *const u8,
44 _code_len: usize,
45 _endowment: *const u8,
46 _contract: *mut u8,
47 _revert_data_len: *mut usize,
48 ) {
49 }
50
51 pub(crate) unsafe fn create2(
52 _code: *const u8,
53 _code_len: usize,
54 _endowment: *const u8,
55 _salt: *const u8,
56 _contract: *mut u8,
57 _revert_data_len: *mut usize,
58 ) {
59 }
60
61 pub(crate) fn read_return_data(_dest: *mut u8, _offset: usize, _size: usize) -> usize {
62 0
63 }
64}
65
66pub fn create1_partial(code: &[u8], endowment: U) -> Result<Address, usize> {
67 let mut addr = [0u8; 20];
68 let mut revert_len = 0;
69 unsafe {
70 impls::create1(
71 code.as_ptr(),
72 code.len(),
73 endowment.as_ptr(),
74 addr.as_mut_ptr(),
75 &mut revert_len as *mut usize,
76 )
77 }
78 if revert_len > 0 {
79 Err(revert_len)
80 } else {
81 Ok(addr)
82 }
83}
84
85pub fn create1_slice<const REVERT_CAP: usize>(
86 code: &[u8],
87 endowment: U,
88) -> Result<Address, ([u8; REVERT_CAP], usize)> {
89 create1_partial(code, endowment).map_err(|i| {
90 let mut b = [0u8; REVERT_CAP];
91 let l = unsafe { impls::read_return_data(b.as_mut_ptr(), 0, i) };
92 (b, l)
93 })
94}
95
96#[cfg(feature = "alloc")]
97pub fn create1_vec(code: &[u8], endowment: U) -> Result<Address, Vec<u8>> {
98 create1_partial(code, endowment).map_err(|i| {
99 let mut b = Vec::with_capacity(i);
100 b.set_len(unsafe { impls::read_return_data(b.as_mut_ptr(), 0, i) });
101 b
102 })
103}