neo_solidity/ir/build/module/
helpers.rs

1fn build_enum_variant_map(enums: &[EnumMetadata]) -> HashMap<String, HashMap<String, u64>> {
2    let mut map = HashMap::new();
3
4    for enum_meta in enums {
5        let mut variants = HashMap::new();
6        for (index, variant) in enum_meta.values.iter().enumerate() {
7            variants.insert(variant.clone(), index as u64);
8        }
9        map.insert(enum_meta.name.clone(), variants);
10    }
11
12    map
13}
14
15fn manifest_type_from_solidity_type(solidity_type: &str) -> ManifestType {
16    let ty = solidity_type.trim().to_ascii_lowercase();
17
18    if ty.ends_with("[]") {
19        return ManifestType::Array;
20    }
21
22    if ty.starts_with("mapping") {
23        return ManifestType::Map;
24    }
25
26    if ty.starts_with("uint") || ty.starts_with("int") {
27        return ManifestType::Integer;
28    }
29
30    if ty == "bool" || ty == "boolean" {
31        return ManifestType::Boolean;
32    }
33
34    if ty == "string" {
35        return ManifestType::String;
36    }
37
38    if ty == "address" || ty == "address payable" || ty == "bytes20" || ty == "hash160" {
39        return ManifestType::Hash160;
40    }
41
42    if ty == "bytes32" || ty == "hash256" {
43        return ManifestType::Hash256;
44    }
45
46    if ty == "bytes" {
47        return ManifestType::ByteArray;
48    }
49
50    if ty.starts_with("bytes") {
51        if let Some(size_str) = ty.strip_prefix("bytes") {
52            if size_str.parse::<u8>().is_ok() {
53                return if size_str == "32" {
54                    ManifestType::Hash256
55                } else {
56                    ManifestType::ByteArray
57                };
58            }
59        }
60        return ManifestType::ByteArray;
61    }
62
63    if ty == "any" {
64        return ManifestType::Any;
65    }
66
67    ManifestType::Any
68}
69
70fn call_flags_allow_write_or_notify(flags: u8) -> bool {
71    // Neo N3 CallFlags:
72    // - ReadStates   = 0x01
73    // - WriteStates  = 0x02
74    // - AllowCall    = 0x04
75    // - AllowNotify  = 0x08
76    // Safe (view/pure) code must not grant WriteStates or AllowNotify.
77    flags & (0x02 | 0x08) != 0
78}
79
80fn parse_u8_literal(value: &BigInt) -> Option<u8> {
81    value.to_u8()
82}
83
84fn native_call_is_mutating(contract: NativeContract, method: &str) -> bool {
85    match contract {
86        NativeContract::Neo => matches!(
87            method,
88            "transfer"
89                | "vote"
90                | "registerCandidate"
91                | "unregisterCandidate"
92                | "setGasPerBlock"
93                | "setRegisterPrice"
94        ),
95        NativeContract::Gas => matches!(method, "transfer"),
96        NativeContract::ContractManagement => {
97            matches!(method, "deploy" | "update" | "destroy" | "setMinimumDeploymentFee")
98        }
99        NativeContract::Policy => matches!(
100            method,
101            "setFeePerByte"
102                | "setExecFeeFactor"
103                | "setStoragePrice"
104                | "setMillisecondsPerBlock"
105                | "setMaxValidUntilBlockIncrement"
106                | "setMaxTraceableBlocks"
107                | "setAttributeFee"
108                | "blockAccount"
109                | "unblockAccount"
110                | "recoverFund"
111                | "setWhitelistFeeContract"
112                | "removeWhitelistFeeContract"
113        ),
114        NativeContract::Oracle => matches!(method, "request" | "setPrice" | "finish"),
115        NativeContract::RoleManagement => matches!(method, "designateAsRole"),
116        NativeContract::Notary => {
117            matches!(
118                method,
119                "lockDepositUntil" | "withdraw" | "setMaxNotValidBeforeDelta" | "onNEP17Payment"
120            )
121        }
122        NativeContract::Treasury => false,
123        NativeContract::Ledger | NativeContract::CryptoLib | NativeContract::StdLib => false,
124    }
125}