Skip to content

Conversation

@0xferrous
Copy link
Contributor

@0xferrous 0xferrous commented Oct 11, 2025

Motivation

The current implementation dynamically tries to determine if the runtime value can fit in 64 bits, but this leads to inconsistent serialization. For instance if you were decoding an uint[], some of the values that fit in 64 bits will serialize as number while others serialize as string making it require special handling on the user that is consuming the json.

Solution

Use the type information to determine the serialization. So the user will always know that specific types will always serialize to a number or a string depending on the number of bits that type uses.

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

@0xferrous 0xferrous force-pushed the push-rtzzspzvvklr branch 2 times, most recently from d53b17f to 0543c04 Compare October 11, 2025 16:36
@0xferrous 0xferrous marked this pull request as ready for review October 11, 2025 16:38
@0xferrous 0xferrous marked this pull request as draft October 11, 2025 16:51
@0xferrous 0xferrous force-pushed the push-rtzzspzvvklr branch 2 times, most recently from c14e6a8 to 05f0bc9 Compare October 12, 2025 16:31
@0xferrous
Copy link
Contributor Author

Okay this set out to be lot more complicated than I initially thought since the serialize_value_as_json function is integrated into cheatcodes and in turn affects all the serialize/parseJson and serialize/parseToml cheatcodes. I think I have found a lesser complicated solution by adding a parameter to determine if it is strict encoding which is set to true when called from cast and set to false when called from elsewhere to not alter any forge behavior.

Let me know if the proptest test is not enough for this and if you'd like to see any other/more kind of testing.

@0xferrous 0xferrous marked this pull request as ready for review October 12, 2025 16:45
@0xferrous
Copy link
Contributor Author

bumping here

…type

The current implementation dynamically tries to determine if the runtime
value can fit in 64 bits, but this leads to inconsistent serialization.
For instance if you were decoding an `uint[]`, some of the values that
fit in 64 bits will serialize as number while others serialize as string
making it require special handling on the user that is consuming the
json. This change makes it so it uses the type information to determine
the serialization. So the user will always know that specific types
will always serialize to a number or a string depending on the number
of bits that type uses.
@0xrusowsky
Copy link
Contributor

0xrusowsky commented Oct 27, 2025

hey @0xferrous, thanks for the PR!

you're right that this is an oversight in the current impl. To give some context: the original approach was designed to work around serde's number conversion limitations. It tries to preserve values as JSON numbers when they fit within 64 bits, since most uint256 values in practice are much smaller and using numbers provides better ergonomics.

however, as u've pointed out, this creates inconsistency for arrays where elements serialize
heterogeneously based on runtime values (which i previously overlooked).

since this primarily impacts arrays, i'd prefer a more targeted fix solely focused towards array serialization:

  1. do a first pass through all elements to check if any require string
    representation
  2. if all fit within 64 bits, serialize the entire array as numbers; otherwise serialize all values as strings

imo this is superior as it ensures type uniformity within each array while preserving ergonomics for simple values + i don't think we need the new flag u introduced... wdyt?

@0xrusowsky 0xrusowsky self-assigned this Oct 27, 2025
@0xrusowsky 0xrusowsky moved this to In Progress in Foundry Oct 27, 2025
@0xrusowsky 0xrusowsky added this to the v1.5.0 milestone Oct 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants