Skip to content

Commit

Permalink
feat(zink): introduce assert for error handling (#290)
Browse files Browse the repository at this point in the history
* chore(zink-codegen): introduce assert in zink codegen

* feat(zink): introduce proc-macro assert
  • Loading branch information
clearloop authored Nov 30, 2024
1 parent d340f7e commit ba69acd
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 4 deletions.
11 changes: 10 additions & 1 deletion examples/revert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,25 @@ fn main() {}

/// check if the passing address is owner
#[zink::external]
pub fn run_revert() {
pub fn revert() {
zink::revert!("revert works")
}

/// check if the passing address is owner
#[zink::external]
pub fn assert() {
zink::assert!(false, "assert works");
}

#[test]
fn test_revert() -> anyhow::Result<()> {
use zint::Contract;
let mut contract = Contract::search("revert")?.compile()?;

let info = contract.execute(["revert()".as_bytes()])?;
assert_eq!(info.revert, Some("revert works".into()));

let info = contract.execute(["assert()".as_bytes()])?;
assert_eq!(info.revert, Some("assert works".into()));
Ok(())
}
14 changes: 13 additions & 1 deletion zink/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
extern crate proc_macro;

use proc_macro::TokenStream;
use syn::{parse_macro_input, Attribute, DeriveInput, ItemFn, ItemStruct, LitStr};
use proc_macro2::Span;
use quote::ToTokens;
use syn::{parse_macro_input, Attribute, DeriveInput, Expr, ItemFn, ItemStruct, LitStr};

mod event;
mod revert;
Expand All @@ -21,6 +23,16 @@ pub fn revert(input: TokenStream) -> TokenStream {
revert::parse(input)
}

/// Check and expression and revert with the input message
///
/// This is similar with the builtin `assert!` in rust, but the revert
/// message only support raw string.
#[proc_macro]
pub fn assert(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as revert::AssertInput);
revert::parse_assert(input)
}

/// Event logging interface
///
/// ```ignore
Expand Down
43 changes: 42 additions & 1 deletion zink/codegen/src/revert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
use proc_macro::TokenStream;
use proc_macro2::{Literal, Span};
use quote::{quote, ToTokens};
use syn::{Ident, LitStr};
use syn::{
parse::{Parse, ParseStream},
parse2, Expr, Ident, LitStr, Token,
};

/// Revert with message
pub fn parse(input: LitStr) -> TokenStream {
Expand Down Expand Up @@ -34,3 +37,41 @@ pub fn parse(input: LitStr) -> TokenStream {
}
.into()
}

/// Parse assert macro
pub fn parse_assert(input: AssertInput) -> TokenStream {
let cond = input.cond;
let revert: Expr = syn::parse2(
parse(
input
.message
.unwrap_or(LitStr::new("unknown error", Span::call_site())),
)
.into(),
)
.expect("Invalid revert message");

quote! {
if !#cond {
#revert
}
}
.into()
}

/// Assert input
pub struct AssertInput {
pub cond: Expr,
pub comma: Token![,],
pub message: Option<LitStr>,
}

impl Parse for AssertInput {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(AssertInput {
cond: input.parse()?,
comma: input.parse()?,
message: input.parse()?,
})
}
}
2 changes: 1 addition & 1 deletion zink/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub mod storage;

pub use self::{asm::Asm, event::Event};
pub use storage::{DoubleKeyMapping, Mapping, Storage};
pub use zink_codegen::{external, revert, storage, Event};
pub use zink_codegen::{assert, external, revert, storage, Event};

/// Generate a keccak hash of the input (sha3)
#[cfg(not(target_family = "wasm"))]
Expand Down

0 comments on commit ba69acd

Please sign in to comment.