Skip to content

Commit

Permalink
feat: add generalized contract error with derive macro (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
cgorenflo authored Sep 19, 2023
1 parent 00377b8 commit 3ff39b3
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 16 deletions.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ error-stack = { version = "0.4.0", features = ["eyre"] }
events = { version = "^0.1.0", path = "packages/events" }
events-derive = { version = "^0.1.0", path = "packages/events-derive" }
axelar-wasm-std = { version = "^0.1.0", path = "packages/axelar-wasm-std" }
axelar-wasm-std-derive = { version = "^0.1.0", path = "packages/axelar-wasm-std-derive" }
itertools = "0.11.0"
voting-verifier = { version = "^0.1.0", path = "contracts/voting-verifier" }
multisig = { version = "^0.1.0", path = "contracts/multisig" }
Expand Down
16 changes: 16 additions & 0 deletions packages/axelar-wasm-std-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "axelar-wasm-std-derive"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
proc-macro = true

[dependencies]
axelar-wasm-std = { workspace = true }
error-stack = { workspace = true }
quote = "1.0.33"
report = { workspace = true }
syn = "2.0.29"
thiserror = { workspace = true }
25 changes: 25 additions & 0 deletions packages/axelar-wasm-std-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::DeriveInput;

#[proc_macro_derive(IntoContractError)]
pub fn into_contract_error_derive(input: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();

let name = &ast.ident;

let gen = quote! {
use axelar_wasm_std::ContractError as _ContractError;

impl From<#name> for _ContractError {
fn from(error: #name) -> Self {
use report::LoggableError;
use error_stack::report;

LoggableError::from(&report!(error)).into()
}
}
};

gen.into()
}
14 changes: 14 additions & 0 deletions packages/axelar-wasm-std-derive/tests/derive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use axelar_wasm_std::ContractError;
use axelar_wasm_std_derive::IntoContractError;
use thiserror::Error;

#[derive(Error, Debug, IntoContractError)]
enum TestError {
#[error("error")]
Something,
}

#[test]
fn can_convert_error() {
_ = ContractError::from(TestError::Something);
}
2 changes: 2 additions & 0 deletions packages/axelar-wasm-std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ cosmwasm-schema = "1.1.3"
cosmwasm-std = "1.2.1"
cosmwasm-storage = "1.1.3"
cw-storage-plus = "1.1.0"
error-stack = { workspace = true }
flagset = { version = "0.4.3", features = ["serde"] }
num-traits = { version = "0.2.14", default-features = false }
report = { workspace = true }
schemars = "0.8.10"
serde = { version = "1.0.145", default-features = false, features = ["derive"] }
serde_json = "1.0.89"
Expand Down
11 changes: 11 additions & 0 deletions packages/axelar-wasm-std/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use cosmwasm_std::StdError;
use report::LoggableError;
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
pub enum ContractError {
#[error(transparent)]
Std(#[from] StdError),
#[error(transparent)]
Structured(#[from] LoggableError),
}
2 changes: 2 additions & 0 deletions packages/axelar-wasm-std/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
pub use crate::{
error::ContractError,
fn_ext::FnExt,
snapshot::{Participant, Snapshot},
threshold::Threshold,
};

pub mod counter;
mod error;
pub mod flagset;
mod fn_ext;
pub mod nonempty;
Expand Down
32 changes: 16 additions & 16 deletions packages/report/src/loggable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ impl Display for LoggableError {

impl Error for LoggableError {}

#[derive(Valuable, PartialEq, Eq, Debug)]
pub struct LoggableBacktrace {
pub lines: Vec<String>,
}

impl<T> From<&Report<T>> for LoggableError {
fn from(report: &Report<T>) -> Self {
let mut errors: Vec<LoggableError> = Vec::new();
Expand Down Expand Up @@ -93,6 +88,22 @@ impl<T> From<&Report<T>> for LoggableError {
}
}

fn chain_causes(errors: Vec<LoggableError>) -> Option<LoggableError> {
errors
.into_iter()
// the outermost error appears first in the vector, so the iterator for the causal dependency needs to be reversed
.rev()
.fold(None, |acc: Option<LoggableError>, mut e: LoggableError| {
e.cause = acc.map(Box::new);
Some(e)
})
}

#[derive(Valuable, PartialEq, Eq, Debug)]
pub struct LoggableBacktrace {
pub lines: Vec<String>,
}

impl From<&Backtrace> for LoggableBacktrace {
fn from(backtrace: &Backtrace) -> Self {
LoggableBacktrace {
Expand All @@ -105,17 +116,6 @@ impl From<&Backtrace> for LoggableBacktrace {
}
}

fn chain_causes(errors: Vec<LoggableError>) -> Option<LoggableError> {
errors
.into_iter()
// the outermost error appears first in the vector, so the iterator for the causal dependency needs to be reversed
.rev()
.fold(None, |acc: Option<LoggableError>, mut e: LoggableError| {
e.cause = acc.map(Box::new);
Some(e)
})
}

enum FrameType<'a> {
Context(&'a dyn Context),
Location(&'a Location<'a>),
Expand Down

0 comments on commit 3ff39b3

Please sign in to comment.