bobcat_create/
lib.rs

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    // Sorry -- on the host, these don't do anything.
41
42    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}