diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index c081952889a5d..91c45f1da4630 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -1809,10 +1809,7 @@ impl SimpleCast { let func = get_func(sig)?; match encode_function_args(&func, args) { Ok(res) => Ok(hex::encode_prefixed(&res[4..])), - Err(e) => eyre::bail!( - "Could not ABI encode the function and arguments. Did you pass in the right types?\nError\n{}", - e - ), + Err(e) => eyre::bail!("Could not ABI encode the function and arguments: {}", e), } } @@ -1843,7 +1840,7 @@ impl SimpleCast { let encoded = match encode_function_args_packed(&func, args) { Ok(res) => hex::encode(res), Err(e) => eyre::bail!( - "Could not ABI encode the function and arguments. Did you pass in the right types?\nError\n{}", + "Could not ABI encode the function and arguments: {}", e ), }; diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index aee64473f135b..7f6710f5c7102 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -15,6 +15,12 @@ where I: IntoIterator, S: AsRef, { + let args: Vec = args.into_iter().collect(); + + if inputs.len() != args.len() { + eyre::bail!("encode length mismatch: expected {} types, got {}", inputs.len(), args.len()) + } + std::iter::zip(inputs, args) .map(|(input, arg)| coerce_value(&input.selector_type(), arg.as_ref())) .collect() @@ -47,6 +53,13 @@ where I: IntoIterator, S: AsRef, { + + let args: Vec = args.into_iter().collect(); + + if func.inputs.len() != args.len() { + eyre::bail!("encode length mismatch: expected {} types, got {}", func.inputs.len(), args.len()) + } + let params: Vec> = std::iter::zip(&func.inputs, args) .map(|(input, arg)| coerce_value(&input.selector_type(), arg.as_ref())) .collect::>>()? @@ -257,4 +270,43 @@ mod tests { assert_eq!(parsed.indexed[1], DynSolValue::Uint(U256::from_be_bytes([3; 32]), 256)); assert_eq!(parsed.indexed[2], DynSolValue::Address(Address::from_word(param2))); } + + #[test] + fn test_encode_args_length_validation() { + use alloy_json_abi::Param; + + let params = vec![ + Param { + name: "a".to_string(), + ty: "uint256".to_string(), + internal_type: None, + components: vec![], + }, + Param { + name: "b".to_string(), + ty: "address".to_string(), + internal_type: None, + components: vec![], + }, + ]; + + // Less arguments than parameters + let args = vec!["1"]; + let res = encode_args(¶ms, &args); + assert!(res.is_err()); + assert!(format!("{}", res.unwrap_err()).contains("encode length mismatch")); + + // Exact number of arguments and parameters + let args = vec!["1", "0x0000000000000000000000000000000000000001"]; + let res = encode_args(¶ms, &args); + assert!(res.is_ok()); + let values = res.unwrap(); + assert_eq!(values.len(), 2); + + // More arguments than parameters + let args = vec!["1", "0x0000000000000000000000000000000000000001", "extra"]; + let res = encode_args(¶ms, &args); + assert!(res.is_err()); + assert!(format!("{}", res.unwrap_err()).contains("encode length mismatch")); + } }