Skip to content

Commit

Permalink
Allow revert with custom error
Browse files Browse the repository at this point in the history
  • Loading branch information
cburgdorf committed Jul 2, 2021
1 parent 05da3ea commit a2d0a06
Show file tree
Hide file tree
Showing 25 changed files with 736 additions and 113 deletions.
6 changes: 3 additions & 3 deletions crates/abi/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ use fe_common::utils::keccak;

/// Formats the name and fields and calculates the 32 byte keccak256 value of
/// the signature.
pub fn event_topic(name: &str, fields: Vec<String>) -> String {
pub fn event_topic(name: &str, fields: &[String]) -> String {
sign_event_or_func(name, fields, 32)
}
/// Formats the name and params and calculates the 4 byte keccak256 value of the
/// signature.
pub fn func_selector(name: &str, params: Vec<String>) -> String {
pub fn func_selector(name: &str, params: &[String]) -> String {
sign_event_or_func(name, params, 4)
}

fn sign_event_or_func(name: &str, params: Vec<String>, size: usize) -> String {
fn sign_event_or_func(name: &str, params: &[String], size: usize) -> String {
let signature = format!("{}({})", name, params.join(","));
keccak::partial(signature.as_bytes(), size)
}
5 changes: 5 additions & 0 deletions crates/analyzer/src/namespace/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ impl Struct {
.map(|(_, typ)| typ)
}

/// Return the types of all fields
pub fn get_field_types(&self) -> Vec<FixedSize> {
self.fields.iter().cloned().map(|(_, typ)| typ).collect()
}

/// Return the index of the given field name
pub fn get_field_index(&self, name: &str) -> Option<usize> {
self.fields.iter().position(|(field, _)| field == name)
Expand Down
28 changes: 27 additions & 1 deletion crates/analyzer/src/traversal/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ fn func_stmt(
Assert { .. } => assert(scope, context, stmt),
Expr { .. } => expr(scope, context, stmt),
Pass => Ok(()),
Revert { .. } => Ok(()),
Revert { .. } => revert(scope, context, stmt),
Break | Continue => {
loop_flow_statement(scope, context, stmt);
Ok(())
Expand Down Expand Up @@ -439,6 +439,32 @@ fn assert(
unreachable!()
}

fn revert(
scope: Shared<BlockScope>,
context: &mut Context,
stmt: &Node<fe::FuncStmt>,
) -> Result<(), FatalError> {
if let fe::FuncStmt::Revert { error } = &stmt.kind {
if let Some(error_expr) = error {
let error_attributes = expressions::expr(Rc::clone(&scope), context, error_expr, None)?;
if !matches!(error_attributes.typ, Type::Struct(_)) {
context.error(
"`revert` error must be a struct",
error_expr.span,
format!(
"this has type `{}`; expected a struct",
error_attributes.typ
),
);
}
}

return Ok(());
}

unreachable!()
}

fn func_return(
scope: Shared<BlockScope>,
context: &mut Context,
Expand Down
2 changes: 2 additions & 0 deletions crates/analyzer/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ test_file! { return_call_to_fn_with_param_type_mismatch }
test_file! { return_call_to_fn_without_return }
test_file! { return_from_init }
test_file! { return_lt_mixed_types }

test_stmt! { revert_reason_not_stuct, "revert 1" }
test_file! { strict_boolean_if_else }
test_file! { struct_call_bad_args }
test_file! { struct_call_without_kw_args }
Expand Down
Loading

0 comments on commit a2d0a06

Please sign in to comment.