neo_solidity/solidity/convert/
contract.rs1fn convert_contract(
2 contract: ContractIR,
3 inherited_events: &[EventMetadata],
4 contract_types: &[String],
5 selector_registry: std::sync::Arc<SelectorRegistry>,
6) -> ContractMetadata {
7 let structs: Vec<StructMetadata> = contract.structs.into_iter().map(convert_struct).collect();
8 let enums: Vec<EnumMetadata> = contract.enums.into_iter().map(convert_enum).collect();
9
10 let struct_type_info = structs_to_type_metadata(&structs);
11 let enum_type_info = enums_to_type_metadata(&enums);
12
13 let has_explicit_on_nep17_payment = contract.functions.iter().any(|function| {
19 !matches!(function.ty, FunctionTy::Receive) && function.name == "onNEP17Payment"
20 });
21
22 let mut methods: Vec<FunctionMetadata> = contract
23 .functions
24 .into_iter()
25 .filter(|function| {
26 matches!(
27 function.ty,
28 FunctionTy::Function
29 | FunctionTy::Constructor
30 | FunctionTy::Fallback
31 | FunctionTy::Receive
32 )
33 })
34 .map(|function| {
35 convert_function(
36 function,
37 &struct_type_info,
38 &enum_type_info,
39 contract_types,
40 has_explicit_on_nep17_payment,
41 &contract.type_aliases,
42 )
43 })
44 .collect();
45
46 use std::collections::HashMap;
52 let mut overloads: HashMap<String, Vec<usize>> = HashMap::new();
53 for (idx, method) in methods.iter().enumerate() {
54 if matches!(method.kind, FunctionKind::Regular) {
55 overloads.entry(method.name.clone()).or_default().push(idx);
56 }
57 }
58 for (name, indices) in overloads {
59 if indices.len() > 1 {
60 for index in indices {
61 let method = &mut methods[index];
62 let param_signatures: Vec<String> = method
63 .parameters
64 .iter()
65 .map(|param| canonical_param_type(¶m.ty))
66 .collect();
67 method.neo_name = if param_signatures.is_empty() {
68 format!("{name}()")
69 } else {
70 format!("{name}({})", param_signatures.join(","))
71 };
72 }
73 }
74 }
75
76 use std::collections::BTreeMap;
77 let mut event_map: BTreeMap<String, EventMetadata> = BTreeMap::new();
78 for event in inherited_events {
79 event_map
80 .entry(event.normalized_name.clone())
81 .or_insert_with(|| event.clone());
82 }
83 for event in contract.events.into_iter().map(convert_event) {
84 event_map.insert(event.normalized_name.clone(), event);
85 }
86 let events: Vec<EventMetadata> = event_map.into_values().collect();
87 let state_variables: Vec<StateVariableMetadata> = contract
88 .state_variables
89 .into_iter()
90 .map(|var| convert_state_variable(var, &struct_type_info, &enum_type_info, contract_types, &contract.type_aliases))
91 .collect();
92
93 synthesize_public_getters(&mut methods, &state_variables);
95
96 ContractMetadata {
97 name: contract.name,
98 is_abstract: matches!(contract.kind, ContractKind::AbstractContract),
99 is_library: matches!(contract.kind, ContractKind::Library),
100 methods,
101 events,
102 uses_storage: state_variables.iter().any(|state| !state.is_constant),
103 state_variables,
104 structs,
105 enums,
106 contract_types: contract_types.to_vec(),
107 selector_registry,
108 documentation: contract.doc.into(),
109 has_using_for_star: contract.has_using_for_star,
110 has_using_function_list: contract.has_using_function_list,
111 using_for_libraries: contract.using_for_libraries.clone(),
112 has_type_definitions: contract.has_type_definitions,
113 type_aliases: contract.type_aliases,
114 flatten_warnings: Vec::new(),
115 super_method_map: contract.super_method_map,
116 }
117}
118
119fn synthesize_public_getters(
120 methods: &mut Vec<FunctionMetadata>,
121 state_variables: &[StateVariableMetadata],
122) {
123 for state in state_variables {
124 if state
125 .visibility
126 .as_deref()
127 .map(|v| v.eq_ignore_ascii_case("public"))
128 != Some(true)
129 {
130 continue;
131 }
132
133 let name = match state.name.as_deref() {
134 Some(name) => name.to_string(),
135 None => continue,
136 };
137
138 let neotype = match state.neo_type.as_ref() {
139 Some(neo) => neo.clone(),
140 None => continue,
141 };
142
143 let (parameters, return_parameters, expr) = getter_signature_from_neotype(&name, &neotype);
144 let param_signatures: Vec<String> = parameters
145 .iter()
146 .map(|param| canonical_param_type(¶m.ty))
147 .collect();
148 let selector = compute_function_selector(&name, ¶m_signatures);
149
150 methods.push(FunctionMetadata {
151 name: name.clone(),
152 neo_name: name,
153 kind: FunctionKind::Regular,
154 parameters,
155 return_parameters,
156 state_mutability: StateMutability::View,
157 visibility: VisibilityKind::Public,
158 offset: 0,
159 body: Some(Statement::Return(Default::default(), Some(expr))),
160 selector,
161 is_virtual: false,
162 is_override: false,
163 documentation: NatspecDoc::default(),
164 });
165 }
166}
167
168fn convert_state_variable(
169 var: StateVariableIR,
170 struct_types: &[StructTypeMetadata],
171 enum_types: &[EnumTypeMetadata],
172 contract_types: &[String],
173 type_aliases: &std::collections::HashMap<String, String>,
174) -> StateVariableMetadata {
175 let ty = var.ty;
176 let neo_type = NeoType::from_solidity_with_aliases(&ty, struct_types, enum_types, contract_types, type_aliases).ok();
177 let initializer = var.initializer;
178 StateVariableMetadata {
179 name: var.name,
180 ty,
181 is_constant: var.is_constant,
182 is_immutable: var.is_immutable,
183 visibility: var.visibility,
184 neo_type,
185 has_initializer: initializer.is_some(),
186 initializer,
187 }
188}