Skip to content

Commit 256b91a

Browse files
committed
Allow revert with custom error
Closes argotorg#75
1 parent c409578 commit 256b91a

24 files changed

Lines changed: 735 additions & 112 deletions

crates/abi/src/utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ use fe_common::utils::keccak;
22

33
/// Formats the name and fields and calculates the 32 byte keccak256 value of
44
/// the signature.
5-
pub fn event_topic(name: &str, fields: Vec<String>) -> String {
5+
pub fn event_topic(name: &str, fields: &[String]) -> String {
66
sign_event_or_func(name, fields, 32)
77
}
88
/// Formats the name and params and calculates the 4 byte keccak256 value of the
99
/// signature.
10-
pub fn func_selector(name: &str, params: Vec<String>) -> String {
10+
pub fn func_selector(name: &str, params: &[String]) -> String {
1111
sign_event_or_func(name, params, 4)
1212
}
1313

14-
fn sign_event_or_func(name: &str, params: Vec<String>, size: usize) -> String {
14+
fn sign_event_or_func(name: &str, params: &[String], size: usize) -> String {
1515
let signature = format!("{}({})", name, params.join(","));
1616
keccak::partial(signature.as_bytes(), size)
1717
}

crates/analyzer/src/namespace/types.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ impl Struct {
220220
.map(|(_, typ)| typ)
221221
}
222222

223+
/// Return the types of all fields
224+
pub fn get_field_types(&self) -> Vec<FixedSize> {
225+
self.fields.iter().cloned().map(|(_, typ)| typ).collect()
226+
}
227+
223228
/// Return the index of the given field name
224229
pub fn get_field_index(&self, name: &str) -> Option<usize> {
225230
self.fields.iter().position(|(field, _)| field == name)

crates/analyzer/src/traversal/functions.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ fn func_stmt(
233233
Assert { .. } => assert(scope, context, stmt),
234234
Expr { .. } => expr(scope, context, stmt),
235235
Pass => Ok(()),
236-
Revert { .. } => Ok(()),
236+
Revert { .. } => revert(scope, context, stmt),
237237
Break | Continue => {
238238
loop_flow_statement(scope, context, stmt);
239239
Ok(())
@@ -439,6 +439,32 @@ fn assert(
439439
unreachable!()
440440
}
441441

442+
fn revert(
443+
scope: Shared<BlockScope>,
444+
context: &mut Context,
445+
stmt: &Node<fe::FuncStmt>,
446+
) -> Result<(), FatalError> {
447+
if let fe::FuncStmt::Revert { error } = &stmt.kind {
448+
if let Some(error_expr) = error {
449+
let error_attributes = expressions::expr(Rc::clone(&scope), context, error_expr, None)?;
450+
if !matches!(error_attributes.typ, Type::Struct(_)) {
451+
context.error(
452+
"`revert` error must be a struct",
453+
error_expr.span,
454+
format!(
455+
"this has type `{}`; expected a struct",
456+
error_attributes.typ
457+
),
458+
);
459+
}
460+
}
461+
462+
return Ok(());
463+
}
464+
465+
unreachable!()
466+
}
467+
442468
fn func_return(
443469
scope: Shared<BlockScope>,
444470
context: &mut Context,

crates/analyzer/tests/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ test_file! { return_call_to_fn_with_param_type_mismatch }
187187
test_file! { return_call_to_fn_without_return }
188188
test_file! { return_from_init }
189189
test_file! { return_lt_mixed_types }
190+
191+
test_stmt! { revert_reason_not_stuct, "revert 1" }
190192
test_file! { strict_boolean_if_else }
191193
test_file! { struct_call_bad_args }
192194
test_file! { struct_call_without_kw_args }

0 commit comments

Comments
 (0)