Skip to content

Commit e3e0047

Browse files
committed
convert tuple parameters correctly for dyn-abi
1 parent 2a74fd2 commit e3e0047

File tree

1 file changed

+52
-33
lines changed

1 file changed

+52
-33
lines changed

server/src/http/dyn_contract.rs

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use alloy::hex;
2+
use alloy::json_abi::Param;
23
use alloy::{
34
dyn_abi::{DynSolType, DynSolValue, JsonAbiExt},
45
json_abi::{Function, JsonAbi},
@@ -213,6 +214,54 @@ impl ContractCall {
213214
})
214215
}
215216

217+
fn json_to_sol(
218+
json_values: &[JsonValue],
219+
json_abi_params: &[Param],
220+
) -> Result<Vec<DynSolValue>, String> {
221+
if json_values.len() != json_abi_params.len() {
222+
return Err(format!(
223+
"Parameter count mismatch: expected {}, got {}",
224+
json_abi_params.len(),
225+
json_values.len()
226+
));
227+
}
228+
229+
let mut parsed_params = Vec::new();
230+
231+
for (json_value, json_abi_param) in json_values.iter().zip(json_abi_params.iter()) {
232+
if json_abi_param.is_complex_type() {
233+
let json_value = json_value
234+
.as_array()
235+
.ok_or_else(|| "Expected array for complex type".to_string())?;
236+
237+
let dyn_sol_value = Self::json_to_sol(json_value, &json_abi_param.components)?;
238+
239+
parsed_params.push(DynSolValue::Tuple(dyn_sol_value));
240+
} else {
241+
let sol_type: DynSolType = json_abi_param
242+
.ty
243+
.parse()
244+
.map_err(|e| format!("Invalid Solidity type '{}': {}", json_abi_param.ty, e))?;
245+
246+
let parsed_value: DynSolValue = sol_type
247+
.coerce_json(json_value)
248+
.map_err(|e| format!("Failed to parse parameter as DynSolValue: {}", e))?;
249+
250+
if !parsed_value.matches(&sol_type) {
251+
return Err(format!(
252+
"Parameter type mismatch: expected {}, got {:?}",
253+
json_abi_param.ty,
254+
parsed_value.as_type()
255+
));
256+
}
257+
258+
parsed_params.push(parsed_value);
259+
}
260+
}
261+
262+
Ok(parsed_params)
263+
}
264+
216265
/// Encodes parameters using serde to directly deserialize into DynSolValue
217266
pub fn encode_parameters(
218267
&self,
@@ -231,39 +280,9 @@ impl ContractCall {
231280
));
232281
}
233282

234-
let mut parsed_params = Vec::new();
235-
236-
for (param, input) in self.params.iter().zip(function.inputs.iter()) {
237-
let sol_type: DynSolType = input.ty.parse().map_err(|e| {
238-
EngineError::contract_preparation_error(
239-
Some(self.contract_address),
240-
chain_id,
241-
format!("Invalid Solidity type '{}': {}", input.ty, e),
242-
)
243-
})?;
244-
245-
let parsed_value: DynSolValue = sol_type.coerce_json(param).map_err(|e| {
246-
EngineError::contract_preparation_error(
247-
Some(self.contract_address),
248-
chain_id,
249-
format!("Failed to parse parameter as DynSolValue: {}", e),
250-
)
251-
})?;
252-
253-
if !parsed_value.matches(&sol_type) {
254-
return Err(EngineError::contract_preparation_error(
255-
Some(self.contract_address),
256-
chain_id,
257-
format!(
258-
"Parameter type mismatch: expected {}, got {:?}",
259-
input.ty,
260-
parsed_value.as_type()
261-
),
262-
));
263-
}
264-
265-
parsed_params.push(parsed_value);
266-
}
283+
let parsed_params = Self::json_to_sol(&self.params, &function.inputs).map_err(|e| {
284+
EngineError::contract_preparation_error(Some(self.contract_address), chain_id, e)
285+
})?;
267286

268287
function.abi_encode_input(&parsed_params).map_err(|e| {
269288
EngineError::contract_preparation_error(

0 commit comments

Comments
 (0)