bobcat_panic/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "panic-revert")]
4use bobcat_entry::{write_result_slice, U};
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8
9#[cfg(feature = "panic-revert")]
10use alloc::vec::Vec;
11
12#[cfg(feature = "panic-revert")]
13use core::fmt::{Result as FmtResult, Write};
14
15#[cfg(target_arch = "wasm32")]
16mod wasm {
17    #[link(wasm_import_module = "console")]
18    unsafe extern "C" {
19        pub(crate) fn log_txt(ptr: *const u8, len: usize);
20    }
21
22    #[link(wasm_import_module = "vm_hooks")]
23    #[allow(unused)]
24    unsafe extern "C" {
25        pub(crate) fn exit_early(code: i32) -> !;
26    }
27}
28
29#[cfg(feature = "panic-revert")]
30const ERROR_PREAMBLE: [u8; 32 + 4] = match const_hex::const_decode_to_array::<{ 32 + 4 }>(
31    b"08c379a00000000000000000000000000000000000000000000000000000000000000020",
32) {
33    Ok(v) => v,
34    Err(_) => panic!(),
35};
36
37#[cfg(feature = "panic-revert")]
38struct VecWriter<'a>(&'a mut Vec<u8>);
39
40#[cfg(feature = "panic-revert")]
41impl<'a> Write for VecWriter<'a> {
42    fn write_str(&mut self, s: &str) -> FmtResult {
43        self.0.extend_from_slice(s.as_bytes());
44        Ok(())
45    }
46}
47
48#[cfg(all(not(feature = "std"), target_arch = "wasm32"))]
49#[panic_handler]
50pub fn panic_handler(_msg: &core::panic::PanicInfo) -> ! {
51    #[cfg(feature = "console")]
52    {
53        let msg = alloc::format!("{_msg}");
54        unsafe { wasm::log_txt(msg.as_ptr(), msg.len()) }
55    }
56    let mut d = ERROR_PREAMBLE.to_vec();
57    let mut b = Vec::new();
58    #[cfg(feature = "panic-revert")]
59    {
60        write!(VecWriter(&mut b), "{_msg}").unwrap();
61        let l = b.len();
62        let p = (32 - (l % 32)) % 32;
63        d.extend_from_slice(&U::from(l).0);
64        d.append(&mut b);
65        d.resize(d.len() + p, 0);
66        write_result_slice(&d);
67        unsafe { wasm::exit_early(1) }
68    }
69    // Prefer the normal behaviour if the user hasn't opted into this
70    // feature. Maybe it's better to wipe out the revertdata if this happens,
71    // the other behaviour is different.
72    core::arch::wasm32::unreachable()
73}