Skip to content

Commit

Permalink
🧑‍💻 Setup error tracing in contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
doitian committed Feb 2, 2024
1 parent 1cb2b49 commit c12d54a
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 2 deletions.
52 changes: 52 additions & 0 deletions contracts/__tests__/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,54 @@
// Include your tests here
// See https://github.com/xxuejie/ckb-native-build-sample/blob/main/tests/src/tests.rs for examples

use crate::Loader;
use ckb_testtool::{
ckb_types::{bytes::Bytes, core::TransactionBuilder, packed, prelude::*},
context::Context,
};

include!("../../dao-action-verifier/src/error_code.rs");

const MAX_CYCLES: u64 = 10_000_000;

#[test]
fn test_fail() {
let loader = Loader::default();
let mut context = Context::default();

let bin = loader.load_binary("dao-action-verifier");
let out_point = context.deploy_cell(bin);

let lock_script = context
.build_script(&out_point, Default::default())
.expect("script");

let input_out_point = context.create_cell(
packed::CellOutput::new_builder()
.capacity(1000u64.pack())
.lock(lock_script.clone())
.build(),
Bytes::new(),
);
let input = packed::CellInput::new_builder()
.previous_output(input_out_point)
.build();

let outputs = vec![packed::CellOutput::new_builder()
.capacity(1000u64.pack())
.lock(lock_script.clone())
.build()];

let outputs_data = vec![Bytes::new()];

let tx = TransactionBuilder::default()
.input(input)
.outputs(outputs)
.outputs_data(outputs_data.pack())
.build();

let tx = context.complete_tx(tx);

let result = context.verify_tx(&tx, MAX_CYCLES);
assert!(result.is_err());
}
43 changes: 43 additions & 0 deletions contracts/dao-action-verifier/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::error_code::ErrorCode;
use ckb_std::error::SysError;

#[derive(Debug)]
pub enum Error {
CkbStd(SysError),
}

impl From<Error> for ErrorCode {
fn from(err: Error) -> ErrorCode {
match err {
Error::CkbStd(err) => match err {
SysError::IndexOutOfBound => ErrorCode::IndexOutOfBound,
SysError::ItemMissing => ErrorCode::ItemMissing,
SysError::LengthNotEnough(_) => ErrorCode::LengthNotEnough,
SysError::Encoding => ErrorCode::Encoding,
SysError::Unknown(_) => ErrorCode::Unknown,
},
}
}
}

impl From<Error> for i8 {
fn from(err: Error) -> i8 {
ErrorCode::from(err) as i8
}
}

impl From<SysError> for Error {
fn from(err: SysError) -> Self {
Error::CkbStd(err)
}
}

#[macro_export]
macro_rules! trace_error {
($err:expr, $message:literal) => {{
let err = $crate::error::Error::from($err);
#[cfg(debug_assertions)]
ckb_std::debug!("{}:{} {:?} {}", file!(), line!(), err, $message);
err
}};
}
9 changes: 9 additions & 0 deletions contracts/dao-action-verifier/src/error_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[cfg_attr(test, allow(dead_code))]
#[repr(i8)]
pub enum ErrorCode {
IndexOutOfBound = 16,
ItemMissing = 17,
LengthNotEnough = 18,
Encoding = 19,
Unknown = 20,
}
15 changes: 13 additions & 2 deletions contracts/dao-action-verifier/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@ ckb_std::entry!(program_entry);
#[cfg(all(target_arch = "riscv64", not(test)))]
default_alloc!();

use ckb_std::error::SysError;
mod error;
mod error_code;

use error::Error;

pub fn program_entry() -> i8 {
ckb_std::debug!("This is a sample contract!");
match verify() {
Ok(_) => 0,
Err(err) => err.into(),
}
}

0
pub fn verify() -> Result<(), Error> {
Err(trace_error!(SysError::IndexOutOfBound, "error"))
}

0 comments on commit c12d54a

Please sign in to comment.