Skip to content

fix(cast): normalize to-base output when input and output bases match - #17436

Open
ara-stock wants to merge 1 commit into
foundry-rs:masterfrom
ara-stock:fix/cast-to-base-same-base
Open

ara-stock wants to merge 1 commit into
foundry-rs:masterfrom
ara-stock:fix/cast-to-base-same-base

Conversation

@ara-stock

Copy link
Copy Markdown

Motivation

cast to-base / to-hex / to-dec return the input string unchanged whenever the input base equals the output base, because to_base short-circuits with return Ok(value.to_string()). The input is parsed (and validated) but the parsed value is thrown away, so the output is not normalized and is inconsistent with every other path:

$ cast to-hex --base-in 16 ff
ff                      # no 0x prefix (cast to-hex 255 prints 0xff)
$ cast to-hex 0XFF
0XFF
$ cast to-hex 0x00ff
0x00ff
$ cast to-hex +0x10
+0x10
$ cast to-dec 0010
0010
$ cast to-base 0b0011 bin
0b0011
$ cast to-hex -- -0x1
-0x1                    # but `cast to-hex -- -1` prints the two's complement 0xfff...f

(reproduced with cast 1.8.3 and on master a57bf18)

The negative case is the most surprising: the same number gives a two's-complement hex word when written in decimal, but a signed hex string when written in hex.

Solution

Drop the base_in == base_out early return in to_base, so the parsed NumberWithBase is always formatted with {:#?}. The input is already parsed before the early return, so this only changes the output, which is now the same as converting from any other base:

$ cast to-hex --base-in 16 ff
0xff
$ cast to-hex 0XFF
0xff
$ cast to-hex 0x00ff
0xff
$ cast to-hex +0x10
0x10
$ cast to-dec 0010
10
$ cast to-base 0b0011 bin
0b11
$ cast to-hex -- -0x1
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Added to_base_same_base_normalizes in crates/cast/tests/cli/conversions.rs. It fails with the args.rs change reverted and passes with it.

Note: leading zeros in a same-base input are no longer kept (0x00ff -> 0xff), matching what happens for a different-base input (cast to-hex 255 -> 0xff). cast to-uint256 / cast pad remain the way to get fixed-width output.

Tests run locally: cargo test -p cast --test cli -- conversions:: (46 passed), cargo clippy -p cast --all-targets (no warnings in cast), rustfmt check on the changed files.

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

I used an AI assistant while preparing this; I reproduced the bug and ran the tests myself.

🤖 Generated with Claude Code

`to_base` returned the raw input string whenever the input base equaled
the output base, so `cast to-hex --base-in 16 ff` printed `ff` without a
prefix, `cast to-hex 0x00ff` kept leading zeros and the `0X`/`+` forms,
and `cast to-hex -0x1` printed `-0x1` instead of the two's complement
that `cast to-hex -1` prints. Always format the parsed value instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@stevencartavia stevencartavia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we keep same-base output unchanged? @mattsse @grandizzy

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants