diff --git a/server/src/http/dyn_contract.rs b/server/src/http/dyn_contract.rs index 3114982..a9c8da7 100644 --- a/server/src/http/dyn_contract.rs +++ b/server/src/http/dyn_contract.rs @@ -1,4 +1,5 @@ use alloy::hex; +use alloy::json_abi::Param; use alloy::{ dyn_abi::{DynSolType, DynSolValue, JsonAbiExt}, json_abi::{Function, JsonAbi}, @@ -213,6 +214,54 @@ impl ContractCall { }) } + fn json_to_sol( + json_values: &[JsonValue], + json_abi_params: &[Param], + ) -> Result, String> { + if json_values.len() != json_abi_params.len() { + return Err(format!( + "Parameter count mismatch: expected {}, got {}", + json_abi_params.len(), + json_values.len() + )); + } + + let mut parsed_params = Vec::new(); + + for (json_value, json_abi_param) in json_values.iter().zip(json_abi_params.iter()) { + if json_abi_param.is_complex_type() { + let json_value = json_value + .as_array() + .ok_or_else(|| "Expected array for complex type".to_string())?; + + let dyn_sol_value = Self::json_to_sol(json_value, &json_abi_param.components)?; + + parsed_params.push(DynSolValue::Tuple(dyn_sol_value)); + } else { + let sol_type: DynSolType = json_abi_param + .ty + .parse() + .map_err(|e| format!("Invalid Solidity type '{}': {}", json_abi_param.ty, e))?; + + let parsed_value: DynSolValue = sol_type + .coerce_json(json_value) + .map_err(|e| format!("Failed to parse parameter as DynSolValue: {}", e))?; + + if !parsed_value.matches(&sol_type) { + return Err(format!( + "Parameter type mismatch: expected {}, got {:?}", + json_abi_param.ty, + parsed_value.as_type() + )); + } + + parsed_params.push(parsed_value); + } + } + + Ok(parsed_params) + } + /// Encodes parameters using serde to directly deserialize into DynSolValue pub fn encode_parameters( &self, @@ -231,39 +280,9 @@ impl ContractCall { )); } - let mut parsed_params = Vec::new(); - - for (param, input) in self.params.iter().zip(function.inputs.iter()) { - let sol_type: DynSolType = input.ty.parse().map_err(|e| { - EngineError::contract_preparation_error( - Some(self.contract_address), - chain_id, - format!("Invalid Solidity type '{}': {}", input.ty, e), - ) - })?; - - let parsed_value: DynSolValue = sol_type.coerce_json(param).map_err(|e| { - EngineError::contract_preparation_error( - Some(self.contract_address), - chain_id, - format!("Failed to parse parameter as DynSolValue: {}", e), - ) - })?; - - if !parsed_value.matches(&sol_type) { - return Err(EngineError::contract_preparation_error( - Some(self.contract_address), - chain_id, - format!( - "Parameter type mismatch: expected {}, got {:?}", - input.ty, - parsed_value.as_type() - ), - )); - } - - parsed_params.push(parsed_value); - } + let parsed_params = Self::json_to_sol(&self.params, &function.inputs).map_err(|e| { + EngineError::contract_preparation_error(Some(self.contract_address), chain_id, e) + })?; function.abi_encode_input(&parsed_params).map_err(|e| { EngineError::contract_preparation_error(