neo_solidity/solidity/analyse/modifiers/
expand.rs

1fn build_modifier_definition_map(
2    contract: &ContractIR,
3) -> std::collections::HashMap<(String, usize), FunctionIR> {
4    let mut map = std::collections::HashMap::new();
5    for func in &contract.functions {
6        if matches!(func.ty, FunctionTy::Modifier) {
7            map.insert((func.name.clone(), func.parameters.len()), func.clone());
8        }
9    }
10    map
11}
12
13fn apply_modifier_calls_to_body(
14    original_body: &Statement,
15    modifier_calls: &[Base],
16    modifier_defs: &std::collections::HashMap<(String, usize), FunctionIR>,
17) -> Result<Statement, SolidityError> {
18    let mut current = original_body.clone();
19
20    for modifier_call in modifier_calls.iter().rev() {
21        let Some(name) = base_last_name(modifier_call) else {
22            continue;
23        };
24        let arg_list: Vec<Expression> = modifier_call.args.clone().unwrap_or_default();
25        let key = (name.clone(), arg_list.len());
26        let Some(modifier_def) = modifier_defs.get(&key) else {
27            return Err(SolidityError::Analysis(format!(
28                "unresolved modifier '{name}' with {} argument(s)",
29                arg_list.len()
30            )));
31        };
32
33        let Some(modifier_body) = modifier_def.body.as_ref() else {
34            return Err(SolidityError::Analysis(format!(
35                "modifier '{name}' has no body"
36            )));
37        };
38
39        let substitutions = build_parameter_substitutions(&modifier_def.parameters, &arg_list)?;
40        current = rewrite_statement(modifier_body, &substitutions, Some(&current));
41    }
42
43    Ok(current)
44}
45
46fn statement_list_from_body(body: &Statement) -> Vec<Statement> {
47    match body {
48        Statement::Block { statements, .. } => statements.clone(),
49        stmt => vec![stmt.clone()],
50    }
51}