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::{
16 make_beacon_proxy, make_beacon_sel_proxy_sel, make_minimal_proxy, make_multi3_proxy,
17 make_upgradeable_beacon_proxy,
18};
19
20use array_concat::concat_arrays;
21
22#[cfg(all(target_family = "wasm", target_os = "unknown"))]
23use bobcat_host as impls;
24
25#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
26mod impls {
27 pub(crate) unsafe fn create1(
30 _code: *const u8,
31 _code_len: usize,
32 _endowment: *const u8,
33 _contract: *mut u8,
34 _revert_data_len: *mut usize,
35 ) {
36 }
37
38 pub(crate) unsafe fn create2(
39 _code: *const u8,
40 _code_len: usize,
41 _endowment: *const u8,
42 _salt: *const u8,
43 _contract: *mut u8,
44 _revert_data_len: *mut usize,
45 ) {
46 }
47
48 pub(crate) unsafe fn read_return_data(_dest: *mut u8, _offset: usize, _size: usize) -> usize {
49 0
50 }
51}
52
53pub fn create1_partial(code: &[u8], endowment: U) -> (Address, usize) {
54 let mut addr = [0u8; 20];
55 let mut revert_len = 0;
56 unsafe {
57 impls::create1(
58 code.as_ptr(),
59 code.len(),
60 endowment.as_ptr(),
61 addr.as_mut_ptr(),
62 &mut revert_len as *mut usize,
63 )
64 }
65 (addr, revert_len)
66}
67
68pub fn create1_unit(code: &[u8], endowment: U) -> Option<Address> {
69 let (addr, _) = create1_partial(code, endowment);
70 if addr == [0u8; 20] {
71 return None;
72 }
73 Some(addr)
74}
75
76pub fn create1_slice<const REVERT_CAP: usize>(
77 code: &[u8],
78 endowment: U,
79) -> (Address, [u8; REVERT_CAP], usize) {
80 let (addr, i) = create1_partial(code, endowment);
81 let mut b = [0u8; REVERT_CAP];
82 let mut l = 0;
83 if addr != [0u8; 20] {
84 assert!(REVERT_CAP >= i, "create1 not enough space");
85 l = unsafe { impls::read_return_data(b.as_mut_ptr(), 0, i) };
86 }
87 (addr, b, l)
88}
89
90pub fn create1_slice_res<const REVERT_CAP: usize>(
91 code: &[u8],
92 endowment: U,
93) -> Result<Address, ([u8; REVERT_CAP], usize)> {
94 let (addr, b, l) = create1_slice(code, endowment);
95 if addr != [0u8; 20] {
96 Ok(addr)
97 } else {
98 Err((b, l))
99 }
100}
101
102#[cfg(feature = "alloc")]
103pub fn create1_vec(code: &[u8], endowment: U) -> (Address, Option<Vec<u8>>) {
104 let (addr, rd) = create1_partial(code, endowment);
105 if addr != [0u8; 20] {
106 (addr, None)
107 } else {
108 let mut b = Vec::with_capacity(rd);
109 unsafe { impls::read_return_data(b.as_mut_ptr(), 0, rd) };
110 unsafe { b.set_len(rd) }
111 (addr, Some(b))
112 }
113}
114
115pub fn create2_partial(code: &[u8], endowment: U, salt: U) -> (Address, usize) {
116 let mut addr = [0u8; 20];
117 let mut revert_len = 0;
118 unsafe {
119 impls::create2(
120 code.as_ptr(),
121 code.len(),
122 endowment.as_ptr(),
123 salt.as_ptr(),
124 addr.as_mut_ptr(),
125 &mut revert_len as *mut usize,
126 )
127 }
128 (addr, revert_len)
129}
130
131pub fn create2_slice<const REVERT_CAP: usize>(
132 code: &[u8],
133 endowment: U,
134 salt: U,
135) -> (Address, [u8; REVERT_CAP], usize) {
136 let (addr, rd) = create2_partial(code, endowment, salt);
137 let mut b = [0u8; REVERT_CAP];
138 if addr == [0u8; 20] {
139 assert!(REVERT_CAP >= rd, "create2 not enough space");
140 unsafe { impls::read_return_data(b.as_mut_ptr(), 0, rd) };
141 }
142 (addr, b, rd)
143}
144
145pub fn create2_slice_res<const REVERT_CAP: usize>(
146 code: &[u8],
147 endowment: U,
148 salt: U,
149) -> Result<Address, ([u8; REVERT_CAP], usize)> {
150 let (addr, b, l) = create2_slice(code, endowment, salt);
151 if addr != [0u8; 20] {
152 Ok(addr)
153 } else {
154 Err((b, l))
155 }
156}
157
158pub fn create2_post_unit(code: &[u8], endowment: U, salt_digest: U) -> Option<Address> {
159 let (addr, _) = create2_partial(code, endowment, salt_digest);
160 if addr == [0u8; 20] {
161 return None;
162 }
163 Some(addr)
164}
165
166pub fn create2_pre_unit(code: &[u8], endowment: U, salt_pre: &[u8]) -> Option<Address> {
167 create2_post_unit(code, endowment, keccak256(salt_pre))
168}
169
170#[cfg(feature = "alloc")]
171pub fn create2_post_vec(code: &[u8], endowment: U, salt: U) -> (Address, Option<Vec<u8>>) {
172 let (addr, rd) = create2_partial(code, endowment, salt);
173 if addr == [0u8; 20] {
174 let mut b = Vec::with_capacity(rd);
175 unsafe { impls::read_return_data(b.as_mut_ptr(), 0, rd) };
176 unsafe {
177 b.set_len(rd);
178 }
179 return (addr, Some(b));
180 }
181 (addr, None)
182}
183
184#[cfg(feature = "alloc")]
185pub fn create2_pre_vec(code: &[u8], endowment: U, salt_pre: &[u8]) -> (Address, Option<Vec<u8>>) {
186 create2_post_vec(code, endowment, keccak256(salt_pre))
187}
188
189pub fn create2_slice_pre_keccak256<const REVERT_CAP: usize>(
190 code: &[u8],
191 endowment: U,
192 salt_pre: &[u8],
193) -> (Address, [u8; REVERT_CAP], usize) {
194 create2_slice::<REVERT_CAP>(code, endowment, const_keccak256(salt_pre))
195}
196
197#[cfg(feature = "alloc")]
198pub fn create2_vec_pre_keccak256(
199 code: &[u8],
200 endowment: U,
201 salt_pre: &[u8],
202) -> (Address, Option<Vec<u8>>) {
203 create2_post_vec(code, endowment, keccak256(salt_pre))
204}
205
206pub fn const_estimate_addr_pre(factory: Address, initcode_pre: &[u8], salt_pre: &[u8]) -> Address {
207 const_estimate_addr_post(
208 factory,
209 const_keccak256(initcode_pre),
210 const_keccak256(salt_pre),
211 )
212}
213
214pub fn const_estimate_addr_post(factory: Address, initcode_digest: U, salt_digest: U) -> Address {
216 let b: [u8; 1 + 20 + 32 * 2] =
217 concat_arrays!([0xff], factory, salt_digest.0, initcode_digest.0);
218 const_keccak256(&b).into()
219}
220
221pub fn estimate_addr(factory: Address, initcode: U, salt: U) -> Address {
222 let b: [u8; 1 + 20 + 32 * 2] = concat_arrays!([0xff], factory, salt.0, initcode.0);
223 keccak256(&b).into()
224}
225
226pub fn estimate_addr_pre(factory: Address, initcode_pre: &[u8], salt_pre: &[u8]) -> Address {
228 estimate_addr(factory, keccak256(initcode_pre), keccak256(salt_pre))
229}
230
231pub fn deploy_minimal_proxy_endowment(addr: Address, endowment: U) -> Address {
233 create1_unit(&make_minimal_proxy(addr), endowment).unwrap()
234}
235
236pub fn deploy_beacon_proxy_endowment(beacon: Address, endowment: U) -> Address {
238 create1_unit(&make_beacon_proxy(beacon), endowment).unwrap()
239}
240
241pub fn deploy_upgradeable_beacon_proxy_endowment(beacon: Address, endowment: U) -> Address {
243 create1_unit(&make_upgradeable_beacon_proxy(beacon), endowment).unwrap()
244}
245
246pub fn deploy_multi3_proxy_endowment(
250 one: Address,
251 two: Address,
252 three: Address,
253 all: Address,
254 endowment: U,
255) -> Address {
256 create1_unit(&make_multi3_proxy(one, two, three, all), endowment).unwrap()
257}
258
259pub fn deploy_beacon_sel_proxy_sel_endowment(
262 sel: [u8; 4],
263 beacon: Address,
264 endowment: U,
265) -> Address {
266 create1_unit(&make_beacon_sel_proxy_sel(sel, beacon), endowment).unwrap()
267}
268
269pub fn deploy_minimal_proxy(addr: Address) -> Address {
271 deploy_minimal_proxy_endowment(addr, U::ZERO)
272}
273
274pub fn deploy_beacon_proxy(beacon: Address) -> Address {
276 deploy_beacon_proxy_endowment(beacon, U::ZERO)
277}
278
279pub fn deploy_upgradeable_beacon_proxy(beacon: Address) -> Address {
281 deploy_upgradeable_beacon_proxy_endowment(beacon, U::ZERO)
282}
283
284pub fn deploy_multi3_proxy(one: Address, two: Address, three: Address, all: Address) -> Address {
288 deploy_multi3_proxy_endowment(one, two, three, all, U::ZERO)
289}
290
291pub fn deploy_beacon_sel_proxy_sel(sel: [u8; 4], beacon: Address) -> Address {
294 deploy_beacon_sel_proxy_sel_endowment(sel, beacon, U::ZERO)
295}
296
297pub fn deploy_minimal_proxy_create2_endowment(addr: Address, endowment: U, salt: U) -> Address {
299 create2_post_unit(&make_minimal_proxy(addr), endowment, salt).unwrap()
300}
301
302pub fn deploy_beacon_proxy_create2_endowment(beacon: Address, endowment: U, salt: U) -> Address {
304 create2_post_unit(&make_beacon_proxy(beacon), endowment, salt).unwrap()
305}
306
307pub fn deploy_upgradeable_beacon_proxy_create2_endowment(
309 beacon: Address,
310 endowment: U,
311 salt: U,
312) -> Address {
313 create2_post_unit(&make_upgradeable_beacon_proxy(beacon), endowment, salt).unwrap()
314}
315
316pub fn deploy_multi3_proxy_create2_endowment(
320 one: Address,
321 two: Address,
322 three: Address,
323 all: Address,
324 endowment: U,
325 salt: U,
326) -> Address {
327 create2_post_unit(&make_multi3_proxy(one, two, three, all), endowment, salt).unwrap()
328}
329
330pub fn deploy_beacon_sel_proxy_sel_create2_endowment(
333 sel: [u8; 4],
334 beacon: Address,
335 endowment: U,
336 salt: U,
337) -> Address {
338 create2_post_unit(&make_beacon_sel_proxy_sel(sel, beacon), endowment, salt).unwrap()
339}
340
341pub fn deploy_minimal_proxy_create2(addr: Address, salt: U) -> Address {
343 deploy_minimal_proxy_create2_endowment(addr, U::ZERO, salt)
344}
345
346pub fn deploy_beacon_proxy_create2(beacon: Address, salt: U) -> Address {
348 deploy_beacon_proxy_create2_endowment(beacon, U::ZERO, salt)
349}
350
351pub fn deploy_upgradeable_beacon_proxy_create2(beacon: Address, salt: U) -> Address {
353 deploy_upgradeable_beacon_proxy_create2_endowment(beacon, U::ZERO, salt)
354}
355
356pub fn deploy_multi3_proxy_create2(
360 one: Address,
361 two: Address,
362 three: Address,
363 all: Address,
364 salt: U,
365) -> Address {
366 deploy_multi3_proxy_create2_endowment(one, two, three, all, U::ZERO, salt)
367}
368
369pub fn deploy_beacon_sel_proxy_sel_create2(sel: [u8; 4], beacon: Address, salt: U) -> Address {
372 deploy_beacon_sel_proxy_sel_create2_endowment(sel, beacon, U::ZERO, salt)
373}
374pub fn deploy_minimal_proxy_create2_pre_endowment(
378 addr: Address,
379 endowment: U,
380 salt_pre: &[u8],
381) -> Address {
382 deploy_minimal_proxy_create2_endowment(addr, endowment, keccak256(salt_pre))
383}
384
385pub fn deploy_beacon_proxy_create2_pre_endowment(
387 beacon: Address,
388 endowment: U,
389 salt_pre: &[u8],
390) -> Address {
391 deploy_beacon_proxy_create2_endowment(beacon, endowment, keccak256(salt_pre))
392}
393
394pub fn deploy_beacon_sel_proxy_sel_create2_pre_endowment(
397 sel: [u8; 4],
398 beacon: Address,
399 endowment: U,
400 salt_pre: &[u8],
401) -> Address {
402 deploy_beacon_sel_proxy_sel_create2_endowment(sel, beacon, endowment, keccak256(salt_pre))
403}
404
405pub fn deploy_upgradeable_beacon_proxy_create2_pre_endowment(
407 beacon: Address,
408 endowment: U,
409 salt_pre: &[u8],
410) -> Address {
411 deploy_upgradeable_beacon_proxy_create2_endowment(beacon, endowment, keccak256(salt_pre))
412}
413
414pub fn deploy_upgradeable_beacon_proxy_create2_pre(beacon: Address, salt_pre: &[u8]) -> Address {
416 deploy_upgradeable_beacon_proxy_create2_pre_endowment(beacon, U::ZERO, salt_pre)
417}
418
419pub fn deploy_multi3_proxy_create2_pre_endowment(
423 one: Address,
424 two: Address,
425 three: Address,
426 all: Address,
427 endowment: U,
428 salt_pre: &[u8],
429) -> Address {
430 deploy_multi3_proxy_create2_endowment(one, two, three, all, endowment, keccak256(salt_pre))
431}
432
433pub fn deploy_multi3_proxy_create2_pre(
437 one: Address,
438 two: Address,
439 three: Address,
440 all: Address,
441 salt_pre: &[u8],
442) -> Address {
443 deploy_multi3_proxy_create2_pre_endowment(one, two, three, all, U::ZERO, salt_pre)
444}
445
446pub fn deploy_beacon_sel_proxy_sel_create2_pre(
449 sel: [u8; 4],
450 beacon: Address,
451 salt_pre: &[u8],
452) -> Address {
453 deploy_beacon_sel_proxy_sel_create2_pre_endowment(sel, beacon, U::ZERO, salt_pre)
454}