foundry icon indicating copy to clipboard operation
foundry copied to clipboard

bug(`cheatcodes`): `vm.parseJsonUint` can't parse numbers with scientific notation

Open anajuliabit opened this issue 1 year ago • 5 comments

Component

Forge

Have you ensured that all of these are up to date?

  • [X] Foundry
  • [ ] Foundryup

What version of Foundry are you on?

forge 0.2.0 (VERGEN_IDEMPOTENT_OUTPUT 2024-07-15T11:19:03.935375000Z)

What command(s) is the bug in?

forge script

Operating System

macOS (Apple Silicon)

Describe the bug

With the following JSON:

    "1284": {
        "addRewardInfo": {
            "amount": 74258225772486694040708e18,
            "endTimestamp": 1725593400,
            "pid": 15,
            "rewardPerSec": 0.03069536448928848133e18,
            "target": "STELLASWAP_REWARDER"
        },
        ...

Using vm.parseJsonUint

       string memory key = ".1284.addRewardInfo.amount";
        uint parsedUint = vm.parseJsonUint(data, key);

Output:

    ├─ [0] VM::parseJsonUint("<stringified JSON>", ".1284.addRewardInfo.amount") [staticcall]
    │   └─ ← [Revert] failed parsing "74258.225772486694040708e18" as type `uint256`: parser error:
74258.225772486694040708e18

anajuliabit avatar Jul 30 '24 19:07 anajuliabit

When using vm.parseJson it's parse just fine

anajuliabit avatar Jul 30 '24 19:07 anajuliabit

I tried to replicate the issue but did not receive the same error message. Instead, I encountered the following: failed parsing "74258225772486694040708e18" as type uint256: missing hex prefix ("0x") for hex string. Nevertheless, I think it's something that needs to be fixed. Am I overlooking something? 👀

Expand to see the test contract
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.18;

import "ds-test/test.sol";
import "cheats/Vm.sol";

// https://github.com/foundry-rs/foundry/issues/8566
contract Issue8566Test is DSTest {
  Vm constant vm = Vm(HEVM_ADDRESS);

  function testParseJsonUint() public {
    string memory data = "{\"helper\": {\"myStruct\": {\"amount\": 74258225772486694040708000000000000000000000}}}";
    string memory key = ".helper.myStruct.amount";
    uint parsedUint = vm.parseJsonUint(data, key);
    assertEq(parsedUint, 74258225772486694040708000000000000000000000);
  }

  function testParseJsonUint2() public {
    string memory data = "{\"helper\": {\"myStruct\": {\"amount\": 74258225772486694040708e18}}}";
    string memory key = ".helper.myStruct.amount";
    uint parsedUint = vm.parseJsonUint(data, key);
    assertEq(parsedUint, 74258225772486694040708e18);
  }

  function testParseJson() pure public {
    string memory data = "{\"helper\": {\"myStruct\": {\"amount\": 74258225772486694040708000000000000000000000}}}";
    string memory key = ".helper.myStruct.amount";
    vm.parseJson(data, key);
  }

  function testParseJson2() pure public {
    string memory data = "{\"helper\": {\"myStruct\": {\"amount\": 74258225772486694040708e18}}}";
    string memory key = ".helper.myStruct.amount";
    vm.parseJson(data, key);
  }
}
Expand to see the output of the test
$ forge --version
forge 0.2.0 (6de15b0 2024-07-15T00:22:57.628408000Z)
$ forge test --match-contract Issue8566Test -vvvv
[⠊] Compiling...
[⠢] Compiling 1 files with Solc 0.8.18
[⠆] Solc 0.8.18 finished in 118.38ms
Compiler run successful with warnings:

Ran 4 tests for default/repros/Issue8566.t.sol:Issue8566Test
[PASS] testParseJson() (gas: 4344)
[PASS] testParseJson2() (gas: 4246)
[PASS] testParseJsonUint() (gas: 4001)
[FAIL. Reason: failed parsing "74258225772486694040708e18" as type `uint256`: missing hex prefix ("0x") for hex string] testParseJsonUint2() (gas: 3736)
Traces:
  [3736] DefaultTestContract::testParseJsonUint2()
    ├─ [0] VM::parseJsonUint("<stringified JSON>", ".helper.myStruct.amount") [staticcall]
    │   └─ ← [Revert] failed parsing "74258225772486694040708e18" as type `uint256`: missing hex prefix ("0x") for hex string
    └─ ← [Revert] failed parsing "74258225772486694040708e18" as type `uint256`: missing hex prefix ("0x") for hex string

Suite result: FAILED. 3 passed; 1 failed; 0 skipped; finished in 737.54µs (820.13µs CPU time)

Ran 1 test suite in 175.55ms (737.54µs CPU time): 3 tests passed, 1 failed, 0 skipped (4 total tests)

Failing tests:
Encountered 1 failing test in default/repros/Issue8566.t.sol:Issue8566Test
[FAIL. Reason: failed parsing "74258225772486694040708e18" as type `uint256`: missing hex prefix ("0x") for hex string] testParseJsonUint2() (gas: 3736)

Encountered a total of 1 failing tests, 3 tests succeeded

leovct avatar Aug 02 '24 10:08 leovct

The error is raised here

// More lenient parsers than `coerce_str`.
fn parse_value_fallback(s: &str, ty: &DynSolType) -> Option<Result<DynSolValue, &'static str>> {
    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"));
            }
        }
        _ => {}
    }
    None
}

the fallback is not able to convert scientific notation to U256. @zerosnacks should we fix this here in forge or should we open a pull request to alloy's types to fix this?

francesco-gaglione avatar Aug 09 '24 09:08 francesco-gaglione

Hi @francesco-gaglione, thanks for narrowing this down. I think the correct place to implement this would be alloy/core.

zerosnacks avatar Aug 09 '24 12:08 zerosnacks

I am applying to this issue via OnlyDust platform.

My background and how it can be leveraged

I have been working as fullstack developer for WEB2 for 3 years, I'll like to explore WEB3 world so looks like a fun and benefit project to start with 🙂

antonyjaen avatar Aug 26 '24 22:08 antonyjaen

potentially need to move this issue to https://github.com/alloy-rs/core

jenpaff avatar Sep 26 '24 11:09 jenpaff

keeping this open until alloy issue is created

grandizzy avatar Nov 14 '24 13:11 grandizzy

Opened https://github.com/alloy-rs/core/issues/816, but I would still like to keep this open for when this lands in Foundry.

DaniPopes avatar Dec 02 '24 15:12 DaniPopes

May I be assigned to this?

mimisavage avatar Dec 13 '24 09:12 mimisavage