1#![no_std]
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8
9use bobcat_storage::{const_keccak256, keccak256};
10
11pub use bobcat_maths::U;
12
13type Address = [u8; 20];
14
15use bobcat_proxy::{make_minimal_proxy, make_beacon_proxy, make_beacon_sel_proxy_sel, make_upgradeable_beacon_proxy, make_multi3_proxy};
16
17use array_concat::concat_arrays;
18
19#[cfg(all(target_family = "wasm", target_os = "unknown"))]
20use bobcat_host as impls;
21
22#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
23mod impls {
24 pub(crate) unsafe fn create1(
27 _code: *const u8,
28 _code_len: usize,
29 _endowment: *const u8,
30 _contract: *mut u8,
31 _revert_data_len: *mut usize,
32 ) {
33 }
34
35 pub(crate) unsafe fn create2(
36 _code: *const u8,
37 _code_len: usize,
38 _endowment: *const u8,
39 _salt: *const u8,
40 _contract: *mut u8,
41 _revert_data_len: *mut usize,
42 ) {
43 }
44
45 pub(crate) unsafe fn read_return_data(_dest: *mut u8, _offset: usize, _size: usize) -> usize {
46 0
47 }
48}
49
50pub fn create1_partial(code: &[u8], endowment: U) -> (Address, usize) {
51 let mut addr = [0u8; 20];
52 let mut revert_len = 0;
53 unsafe {
54 impls::create1(
55 code.as_ptr(),
56 code.len(),
57 endowment.as_ptr(),
58 addr.as_mut_ptr(),
59 &mut revert_len as *mut usize,
60 )
61 }
62 (addr, revert_len)
63}
64
65pub fn create1_unit(code: &[u8], endowment: U) -> Option<Address> {
66 let (addr, _) = create1_partial(code, endowment);
67 if addr == [0u8; 20] {
68 return None;
69 }
70 Some(addr)
71}
72
73pub fn create1_slice<const REVERT_CAP: usize>(
74 code: &[u8],
75 endowment: U,
76) -> (Address, [u8; REVERT_CAP], usize) {
77 let (addr, i) = create1_partial(code, endowment);
78 let mut b = [0u8; REVERT_CAP];
79 let mut l = 0;
80 if addr != [0u8; 20] {
81 assert!(REVERT_CAP >= i, "create1 not enough space");
82 l = unsafe { impls::read_return_data(b.as_mut_ptr(), 0, i) };
83 }
84 (addr, b, l)
85}
86
87pub fn create1_slice_res<const REVERT_CAP: usize>(
88 code: &[u8],
89 endowment: U,
90) -> Result<Address, ([u8; REVERT_CAP], usize)> {
91 let (addr, b, l) = create1_slice(code, endowment);
92 if addr != [0u8; 20] {
93 Ok(addr)
94 } else {
95 Err((b, l))
96 }
97}
98
99#[cfg(feature = "alloc")]
100pub fn create1_vec(code: &[u8], endowment: U) -> (Address, Option<Vec<u8>>) {
101 let (addr, rd) = create1_partial(code, endowment);
102 if addr != [0u8; 20] {
103 (addr, None)
104 } else {
105 let mut b = Vec::with_capacity(rd);
106 unsafe { impls::read_return_data(b.as_mut_ptr(), 0, rd) };
107 unsafe { b.set_len(rd) }
108 (addr, Some(b))
109 }
110}
111
112pub fn create2_partial(code: &[u8], endowment: U, salt: U) -> (Address, usize) {
113 let mut addr = [0u8; 20];
114 let mut revert_len = 0;
115 unsafe {
116 impls::create2(
117 code.as_ptr(),
118 code.len(),
119 endowment.as_ptr(),
120 salt.as_ptr(),
121 addr.as_mut_ptr(),
122 &mut revert_len as *mut usize,
123 )
124 }
125 (addr, revert_len)
126}
127
128pub fn create2_slice<const REVERT_CAP: usize>(
129 code: &[u8],
130 endowment: U,
131 salt: U,
132) -> (Address, [u8; REVERT_CAP], usize) {
133 let (addr, rd) = create2_partial(code, endowment, salt);
134 let mut b = [0u8; REVERT_CAP];
135 if addr == [0u8; 20] {
136 assert!(REVERT_CAP >= rd, "create2 not enough space");
137 unsafe { impls::read_return_data(b.as_mut_ptr(), 0, rd) };
138 }
139 (addr, b, rd)
140}
141
142pub fn create2_slice_res<const REVERT_CAP: usize>(
143 code: &[u8],
144 endowment: U,
145 salt: U,
146) -> Result<Address, ([u8; REVERT_CAP], usize)> {
147 let (addr, b, l) = create2_slice(code, endowment, salt);
148 if addr != [0u8; 20] {
149 Ok(addr)
150 } else {
151 Err((b, l))
152 }
153}
154
155pub fn create2_post_unit(code: &[u8], endowment: U, salt_digest: U) -> Option<Address> {
156 let (addr, _) = create2_partial(code, endowment, salt_digest);
157 if addr == [0u8; 20] {
158 return None;
159 }
160 Some(addr)
161}
162
163pub fn create2_pre_unit(code: &[u8], endowment: U, salt_pre: &[u8]) -> Option<Address> {
164 create2_post_unit(code, endowment, keccak256(salt_pre))
165}
166
167#[cfg(feature = "alloc")]
168pub fn create2_post_vec(code: &[u8], endowment: U, salt: U) -> (Address, Option<Vec<u8>>) {
169 let (addr, rd) = create2_partial(code, endowment, salt);
170 if addr == [0u8; 20] {
171 let mut b = Vec::with_capacity(rd);
172 unsafe { impls::read_return_data(b.as_mut_ptr(), 0, rd) };
173 unsafe {
174 b.set_len(rd);
175 }
176 return (addr, Some(b));
177 }
178 (addr, None)
179}
180
181#[cfg(feature = "alloc")]
182pub fn create2_pre_vec(code: &[u8], endowment: U, salt_pre: &[u8]) -> (Address, Option<Vec<u8>>) {
183 create2_post_vec(code, endowment, kecak256(salt_pre))
184}
185
186pub fn create2_slice_pre_keccak256<const REVERT_CAP: usize>(
187 code: &[u8],
188 endowment: U,
189 salt_pre: &[u8],
190) -> (Address, [u8; REVERT_CAP], usize) {
191 create2_slice::<REVERT_CAP>(code, endowment, const_keccak256(salt_pre))
192}
193
194#[cfg(feature = "alloc")]
195pub fn create2_vec_pre_keccak256(
196 code: &[u8],
197 endowment: U,
198 salt_pre: &[u8],
199) -> (Address, Option<Vec<u8>>) {
200 create2_post_vec(code, endowment, keccak256(salt_pre))
201}
202
203pub fn const_estimate_addr_pre(factory: Address, initcode_pre: &[u8], salt_pre: &[u8]) -> Address {
204 const_estimate_addr_post(
205 factory,
206 const_keccak256(initcode_pre),
207 const_keccak256(salt_pre),
208 )
209}
210
211pub fn const_estimate_addr_post(factory: Address, initcode_digest: U, salt_digest: U) -> Address {
213 let b: [u8; 1 + 20 + 32 * 2] =
214 concat_arrays!([0xff], factory, salt_digest.0, initcode_digest.0);
215 const_keccak256(&b).into()
216}
217
218pub fn estimate_addr(factory: Address, initcode: U, salt: U) -> Address {
219 let b: [u8; 1 + 20 + 32 * 2] = concat_arrays!([0xff], factory, salt.0, initcode.0);
220 keccak256(&b).into()
221}
222
223pub fn estimate_addr_pre(factory: Address, initcode_pre: &[u8], salt_pre: &[u8]) -> Address {
225 estimate_addr(factory, keccak256(initcode_pre), keccak256(salt_pre))
226}
227
228pub fn deploy_minimal_proxy_endowment(addr: Address, endowment: U) -> Address {
230 create1_unit(&make_minimal_proxy(addr), endowment).unwrap()
231}
232
233pub fn deploy_beacon_proxy_endowment(beacon: Address, endowment: U) -> Address {
235 create1_unit(&make_beacon_proxy(beacon), endowment).unwrap()
236}
237
238pub fn deploy_upgradeable_beacon_proxy_endowment(beacon: Address, endowment: U) -> Address {
240 create1_unit(&make_upgradeable_beacon_proxy(beacon), endowment).unwrap()
241}
242
243pub fn deploy_multi3_proxy_endowment(
247 one: Address,
248 two: Address,
249 three: Address,
250 all: Address,
251 endowment: U,
252) -> Address {
253 create1_unit(&make_multi3_proxy(one, two, three, all), endowment).unwrap()
254}
255
256pub fn deploy_beacon_sel_proxy_sel_endowment(
259 sel: [u8; 4],
260 beacon: Address,
261 endowment: U,
262) -> Address {
263 create1_unit(&make_beacon_sel_proxy_sel(sel, beacon), endowment).unwrap()
264}
265
266pub fn deploy_minimal_proxy(addr: Address) -> Address {
268 deploy_minimal_proxy_endowment(addr, U::ZERO)
269}
270
271pub fn deploy_beacon_proxy(beacon: Address) -> Address {
273 deploy_beacon_proxy_endowment(beacon, U::ZERO)
274}
275
276pub fn deploy_upgradeable_beacon_proxy(beacon: Address) -> Address {
278 deploy_upgradeable_beacon_proxy_endowment(beacon, U::ZERO)
279}
280
281pub fn deploy_multi3_proxy(one: Address, two: Address, three: Address, all: Address) -> Address {
285 deploy_multi3_proxy_endowment(one, two, three, all, U::ZERO)
286}
287
288pub fn deploy_beacon_sel_proxy_sel(sel: [u8; 4], beacon: Address) -> Address {
291 deploy_beacon_sel_proxy_sel_endowment(sel, beacon, U::ZERO)
292}
293
294pub fn deploy_minimal_proxy_create2_endowment(addr: Address, endowment: U, salt: U) -> Address {
296 create2_post_unit(&make_minimal_proxy(addr), endowment, salt).unwrap()
297}
298
299pub fn deploy_beacon_proxy_create2_endowment(beacon: Address, endowment: U, salt: U) -> Address {
301 create2_post_unit(&make_beacon_proxy(beacon), endowment, salt).unwrap()
302}
303
304pub fn deploy_upgradeable_beacon_proxy_create2_endowment(
306 beacon: Address,
307 endowment: U,
308 salt: U,
309) -> Address {
310 create2_post_unit(&make_upgradeable_beacon_proxy(beacon), endowment, salt).unwrap()
311}
312
313pub fn deploy_multi3_proxy_create2_endowment(
317 one: Address,
318 two: Address,
319 three: Address,
320 all: Address,
321 endowment: U,
322 salt: U,
323) -> Address {
324 create2_post_unit(&make_multi3_proxy(one, two, three, all), endowment, salt).unwrap()
325}
326
327pub fn deploy_beacon_sel_proxy_sel_create2_endowment(
330 sel: [u8; 4],
331 beacon: Address,
332 endowment: U,
333 salt: U,
334) -> Address {
335 create2_post_unit(&make_beacon_sel_proxy_sel(sel, beacon), endowment, salt).unwrap()
336}
337
338pub fn deploy_minimal_proxy_create2(addr: Address, salt: U) -> Address {
340 deploy_minimal_proxy_create2_endowment(addr, U::ZERO, salt)
341}
342
343pub fn deploy_beacon_proxy_create2(beacon: Address, salt: U) -> Address {
345 deploy_beacon_proxy_create2_endowment(beacon, U::ZERO, salt)
346}
347
348pub fn deploy_upgradeable_beacon_proxy_create2(beacon: Address, salt: U) -> Address {
350 deploy_upgradeable_beacon_proxy_create2_endowment(beacon, U::ZERO, salt)
351}
352
353pub fn deploy_multi3_proxy_create2(
357 one: Address,
358 two: Address,
359 three: Address,
360 all: Address,
361 salt: U,
362) -> Address {
363 deploy_multi3_proxy_create2_endowment(one, two, three, all, U::ZERO, salt)
364}
365
366pub fn deploy_beacon_sel_proxy_sel_create2(sel: [u8; 4], beacon: Address, salt: U) -> Address {
369 deploy_beacon_sel_proxy_sel_create2_endowment(sel, beacon, U::ZERO, salt)
370}
371pub fn deploy_minimal_proxy_create2_pre_endowment(
375 addr: Address,
376 endowment: U,
377 salt_pre: &[u8],
378) -> Address {
379 deploy_minimal_proxy_create2_endowment(addr, endowment, keccak256(salt_pre))
380}
381
382pub fn deploy_beacon_proxy_create2_pre_endowment(
384 beacon: Address,
385 endowment: U,
386 salt_pre: &[u8],
387) -> Address {
388 deploy_beacon_proxy_create2_endowment(beacon, endowment, keccak256(salt_pre))
389}
390
391pub fn deploy_beacon_sel_proxy_sel_create2_pre_endowment(
394 sel: [u8; 4],
395 beacon: Address,
396 endowment: U,
397 salt_pre: &[u8],
398) -> Address {
399 deploy_beacon_sel_proxy_sel_create2_endowment(sel, beacon, endowment, keccak256(salt_pre))
400}
401
402pub fn deploy_upgradeable_beacon_proxy_create2_pre_endowment(
404 beacon: Address,
405 endowment: U,
406 salt_pre: &[u8],
407) -> Address {
408 deploy_upgradeable_beacon_proxy_create2_endowment(beacon, endowment, keccak256(salt_pre))
409}
410
411pub fn deploy_upgradeable_beacon_proxy_create2_pre(beacon: Address, salt_pre: &[u8]) -> Address {
413 deploy_upgradeable_beacon_proxy_create2_pre_endowment(beacon, U::ZERO, salt_pre)
414}
415
416pub fn deploy_multi3_proxy_create2_pre_endowment(
420 one: Address,
421 two: Address,
422 three: Address,
423 all: Address,
424 endowment: U,
425 salt_pre: &[u8],
426) -> Address {
427 deploy_multi3_proxy_create2_endowment(one, two, three, all, endowment, keccak256(salt_pre))
428}
429
430
431pub fn deploy_multi3_proxy_create2_pre(
435 one: Address,
436 two: Address,
437 three: Address,
438 all: Address,
439 salt_pre: &[u8],
440) -> Address {
441 deploy_multi3_proxy_create2_pre_endowment(one, two, three, all, U::ZERO, salt_pre)
442}
443
444pub fn deploy_beacon_sel_proxy_sel_create2_pre(
447 sel: [u8; 4],
448 beacon: Address,
449 salt_pre: &[u8],
450) -> Address {
451 deploy_beacon_sel_proxy_sel_create2_pre_endowment(sel, beacon, U::ZERO, salt_pre)
452}