neo_solidity/ir/expressions/calls/builtins/
member_syscalls.rs

1fn try_lower_syscalls_member_builtin(
2    base: &Identifier,
3    member: &Identifier,
4    args: &[Expression],
5    ctx: &mut LoweringContext,
6    instructions: &mut Vec<Instruction>,
7) -> Option<bool> {
8    if base.name != "Syscalls" {
9        return None;
10    }
11
12    match member.name.as_str() {
13        "getNotifications" => {
14            if args.is_empty() {
15                // System.Runtime.GetNotifications accepts a nullable hash; omit the argument
16                // by pushing Null to request all notifications.
17                instructions.push(Instruction::PushLiteral(LiteralValue::Null));
18                instructions.push(Instruction::CallBuiltin {
19                    builtin: BuiltinCall::Syscall("System.Runtime.GetNotifications".to_string()),
20                    arg_count: 1,
21                });
22                return Some(true);
23            }
24            None
25        }
26        "scriptHashToAddress" => {
27            if args.len() != 1 {
28                ctx.record_error(format!(
29                    "Syscalls.scriptHashToAddress requires 1 argument(s), got {}",
30                    args.len()
31                ));
32                return Some(false);
33            }
34
35            if let Some(arg_ty) = infer_type_from_expression(&args[0], ctx) {
36                if !matches!(
37                    arg_ty,
38                    ValueType::Address | ValueType::ByteArray { .. } | ValueType::Any
39                ) {
40                    ctx.record_error(format!(
41                        "Syscalls.scriptHashToAddress expects a 20-byte ByteArray/Hash160-like value, got {:?}",
42                        arg_ty
43                    ));
44                    return Some(false);
45                }
46            }
47
48            Some(lower_expression(&args[0], ctx, instructions))
49        }
50        "addressToScriptHash" => {
51            if args.len() != 1 {
52                ctx.record_error(format!(
53                    "Syscalls.addressToScriptHash requires 1 argument(s), got {}",
54                    args.len()
55                ));
56                return Some(false);
57            }
58
59            if let Some(arg_ty) = infer_type_from_expression(&args[0], ctx) {
60                if !matches!(
61                    arg_ty,
62                    ValueType::Address | ValueType::ByteArray { .. } | ValueType::Any
63                ) {
64                    ctx.record_error(format!(
65                        "Syscalls.addressToScriptHash expects an address/Hash160-like value, got {:?}",
66                        arg_ty
67                    ));
68                    return Some(false);
69                }
70            }
71
72            Some(lower_expression(&args[0], ctx, instructions))
73        }
74        "isValidAddress" => {
75            if args.len() != 1 {
76                ctx.record_error(format!(
77                    "Syscalls.isValidAddress requires 1 argument(s), got {}",
78                    args.len()
79                ));
80                return Some(false);
81            }
82
83            if let Some(arg_ty) = infer_type_from_expression(&args[0], ctx) {
84                if !matches!(
85                    arg_ty,
86                    ValueType::Address | ValueType::ByteArray { .. } | ValueType::Any
87                ) {
88                    ctx.record_error(format!(
89                        "Syscalls.isValidAddress expects an address/Hash160-like value, got {:?}",
90                        arg_ty
91                    ));
92                    return Some(false);
93                }
94            }
95
96            if !lower_expression(&args[0], ctx, instructions) {
97                return Some(false);
98            }
99
100            // Equivalent to Solidity `addr != address(0)`.
101            instructions.push(Instruction::PushLiteral(LiteralValue::Address(vec![
102                0u8; 20
103            ])));
104            instructions.push(Instruction::BinaryOp(BinaryOperator::Ne));
105            Some(true)
106        }
107        _ => None,
108    }
109}