From 9d1c31c3cdd8ec5ebeed244ba5fc55bd233144ad Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 9 Nov 2023 19:55:59 +0100 Subject: [PATCH] fix: better error for non-hex-prefixed hex strings Closes #6070 Closes #6268 --- crates/cheatcodes/src/string.rs | 39 ++++++++++++++++++++++++++++++++- crates/forge/tests/it/repros.rs | 6 +++++ testdata/repros/Issue5808.t.sol | 7 +++--- testdata/repros/Issue6070.t.sol | 16 ++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 testdata/repros/Issue6070.t.sol diff --git a/crates/cheatcodes/src/string.rs b/crates/cheatcodes/src/string.rs index 09c7095a906c2..a4ffa208000e9 100644 --- a/crates/cheatcodes/src/string.rs +++ b/crates/cheatcodes/src/string.rs @@ -116,5 +116,42 @@ where } fn parse_value(s: &str, ty: &DynSolType) -> Result { - ty.coerce_str(s).map_err(|e| fmt_err!("failed parsing {s:?} as type `{ty}`: {e}")) + match ty.coerce_str(s) { + Ok(value) => Ok(value), + Err(e) => { + let base_err = format!("failed parsing {s:?} as type `{ty}`: "); + match parse_value_fallback(s, ty) { + Some(Ok(value)) => Ok(value), + Some(Err(e2)) => Err(fmt_err!("{base_err}{e2}")), + None => Err(fmt_err!("{base_err}{e}")), + } + } + } +} + +// More lenient parsers than `coerce_str`. +fn parse_value_fallback(s: &str, ty: &DynSolType) -> Option> { + match ty { + DynSolType::Bool => { + let b = match s { + "1" => true, + "0" => false, + s if s.eq_ignore_ascii_case("true") => true, + s if s.eq_ignore_ascii_case("false") => false, + _ => return None, + }; + return Some(Ok(DynSolValue::Bool(b))); + } + DynSolType::Int(_) | + DynSolType::Uint(_) | + DynSolType::FixedBytes(_) | + DynSolType::Bytes => { + if !s.starts_with("0x") && s.chars().all(|c| c.is_ascii_hexdigit()) { + return Some(Err("missing hex prefix (\"0x\") for hex string")) + } + } + DynSolType::String => return Some(Ok(DynSolValue::String(s.to_owned()))), + _ => {} + } + None } diff --git a/crates/forge/tests/it/repros.rs b/crates/forge/tests/it/repros.rs index 1cad2984c5ac7..cbc6cae8af12f 100644 --- a/crates/forge/tests/it/repros.rs +++ b/crates/forge/tests/it/repros.rs @@ -302,6 +302,12 @@ async fn test_issue_5808() { test_repro!("Issue5808"); } +// +#[tokio::test(flavor = "multi_thread")] +async fn test_issue_6070() { + test_repro!("Issue6070"); +} + // #[tokio::test(flavor = "multi_thread")] async fn test_issue_6115() { diff --git a/testdata/repros/Issue5808.t.sol b/testdata/repros/Issue5808.t.sol index b3b455b48c295..e2a6a20888307 100644 --- a/testdata/repros/Issue5808.t.sol +++ b/testdata/repros/Issue5808.t.sol @@ -9,10 +9,9 @@ contract Issue5808Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function testReadInt() public { - // TODO: blocked on https://github.com/alloy-rs/core/issues/387 - // string memory str1 = '["ffffffff","00000010"]'; - // vm.expectRevert(); - // int256[] memory ints1 = vm.parseJsonIntArray(str1, ""); + string memory str1 = '["ffffffff","00000010"]'; + vm.expectRevert(); + int256[] memory ints1 = vm.parseJsonIntArray(str1, ""); string memory str2 = '["0xffffffff","0x00000010"]'; int256[] memory ints2 = vm.parseJsonIntArray(str2, ""); diff --git a/testdata/repros/Issue6070.t.sol b/testdata/repros/Issue6070.t.sol new file mode 100644 index 0000000000000..8dc184075068c --- /dev/null +++ b/testdata/repros/Issue6070.t.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +import "ds-test/test.sol"; +import "../cheats/Vm.sol"; + +// https://github.com/foundry-rs/foundry/issues/6070 +contract Issue6066Test is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testNonPrefixed() public { + vm.setEnv("__FOUNDRY_ISSUE_6066", "abcd"); + vm.expectRevert("failed parsing \"abcd\" as type `uint256`: missing hex prefix (\"0x\") for hex string"); + uint256 x = vm.envUint("__FOUNDRY_ISSUE_6066"); + } +}