Skip to content

fix(multisig): parse decimal amounts exactly, not via f64 - #179

Open
Kshot3000 wants to merge 1 commit into
Quantus-Network:mainfrom
Kshot3000:fix/multisig-parse-amount-exact
Open

Kshot3000 wants to merge 1 commit into
Quantus-Network:mainfrom
Kshot3000:fix/multisig-parse-amount-exact

Conversation

@Kshot3000

Copy link
Copy Markdown

Bug

parse_amount in src/cli/multisig.rs is the one amount parser in the CLI that goes through f64: it parses the input as a float, multiplies by 10^12 as a float, and truncates to u128. Every other entry point (send, multisend, NEAR) uses the exact string parser parse_amount_with_decimals in src/cli/send.rs. The float path is wrong on ordinary inputs:

  • "2.01" → 2_009_999_999_999 plancks instead of 2_010_000_000_000 (−1 planck). Sampling two-decimal amounts, roughly 6% come out short by a few plancks (e.g. "66240.40" is −8).
  • "0.0000000000001" (13 decimal places) → Ok(0): an amount the chain cannot represent is silently turned into a zero transfer instead of being refused.
  • "1e3" → read as 1000 QUAN. Scientific notation is not a plain decimal string, and nothing else in the CLI accepts it.

This parser feeds multisig proposal amounts (src/cli/multisig.rs, the propose flow), so a proposal can be created for a slightly different amount than the proposer typed — and the other approvers see the on-chain amount, not the typed one.

Fix

Route decimal inputs through the existing exact parser: parse_amount_with_decimals(amount, 12). That parser validates digit-only input, rejects more fractional digits than the chain supports, and uses checked integer math. The no-decimal-point paths (whole QUAN, and the documented raw base-units format for values ≥ 10^10) are unchanged.

Three regression tests: exactness on the discriminating amounts (2.01, 66240.40, plus guards), refusal of the inputs float would silently mangle (13 decimal places, 1e3, negatives, double dots), and the unchanged whole-number paths.

Verification

  • Red/green in this crate: SKIP_CIRCUIT_BUILD=1 cargo test --lib parse_amount — 2 of 3 new tests fail on the unpatched code with the exact wrong values above; 3/3 pass with the fix. (SKIP_CIRCUIT_BUILD is build.rs's documented flag for jobs that don't need the generated circuit binaries.)
  • cargo test --lib cli::multisig: 20/20. Full cargo test --lib: 424 passed; the only 2 failures (batch-verifier loading, one keystore migration test) fail identically on the unpatched tree in this environment and are unrelated to this change.
  • Disclosure per this repo's SECURITY.md: I used AI tooling to help find and write up this issue.

@Quantus-Network — flagging for the team.

Built by @Kshot9000 (https://x.com/kshot9000) · QTC donations: qznY8nwuvWcCCVys4da1oQdysyh8YUZYRjRqgk3S8Wos8kbau

multisig's parse_amount was the only amount parser in the CLI still
going through f64: '2.01' lost a planck, 13-decimal inputs silently
became 0, and '1e3' was read as 1000 QUAN. Route decimal inputs
through send::parse_amount_with_decimals like every other command;
whole-number and raw base-unit paths are unchanged. Regression tests
cover the discriminating cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant