What changed, and why it matters
This commit replaces the standard Money.parse() with a new Money.safeParse() when converting cryptocurrency buy/sell quote amounts. The change appears aimed at preventing parsing failures or incorrect handling of numeric strings that could arise from floating-point division results, which in a financial app could lead to wrong displayed prices or transaction amounts. There is no explicit security claim in the commit, and the patch is small and partial, so the security relevance is speculative.
Treat as a routine hardening change unless additional context shows Money.parse threw on attacker-controlled quote data. Review whether quote.rate, fiatConversionStore.prices, and fiatAmount are validated before double conversion, and confirm safeParse handles all expected edge cases (empty, null, extremely small/large values, non-numeric strings) without introducing silent truncation.
Security signals we found
Replacement of parse with 'safeParse' suggests prior parser could throw or mis-handle edge-case numeric strings
Financial amount conversion in buy/sell flow is security-sensitive (incorrect amounts, price manipulation, crash)
Use of double arithmetic before fixed-point Money parsing can introduce precision artifacts
No input validation changes are visible; only the parsing method is swapped
Evidence from the diff
A new factory constructor Money.safeParse() was added in cw_core/lib/amount/money.dart. It uses BigInt.parse for base-unit values or parseFixed on a decimal-normalized string for non-base-unit values. Two call sites in lib/view_model/buy/buy_sell_view_model.dart (amountForQuote and fiatAmountForQuote) were switched from Money.parse to Money.safeParse. The functions derive crypto and fiat amounts from a quote rate and fiatConversionStore prices, using double arithmetic and toStringAsFixed before parsing. The commit title ‘switch to safeParse’ implies the previous parse was considered unsafe, but no details are given about the specific failure mode.
Changed components
cw_core/lib/amount/money.dartlib/view_model/buy/buy_sell_view_model.dartInspect captured patch +10 / −4
diff --git a/cw_core/lib/amount/money.dart b/cw_core/lib/amount/money.dart
index de5483e4..9ac551da 100644
--- a/cw_core/lib/amount/money.dart
+++ b/cw_core/lib/amount/money.dart
@@ -25,6 +25,14 @@ class Money implements Comparable<Money> {
return Money(amount, currency);
}
+ factory Money.safeParse(source, Currency currency, {bool isBaseUnit = false}) {
+ final amount = isBaseUnit
+ ? BigInt.parse(source.toString())
+ : parseFixed(source.toString().withDecimals(currency.decimals), currency.decimals);
+
+ return Money(amount, currency);
+ }
+
/// Parse the [source] and turn it into [Money] if possible
///
/// As [parse] except that this method returns `null` if the input is not
diff --git a/lib/view_model/buy/buy_sell_view_model.dart b/lib/view_model/buy/buy_sell_view_model.dart
index 7f6ffd8f..18551649 100644
--- a/lib/view_model/buy/buy_sell_view_model.dart
+++ b/lib/view_model/buy/buy_sell_view_model.dart
@@ -171,17 +171,15 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
return maxAmount.toStringAsFixed(2);
}
- Money amountForQuote(Quote quote) => Money.parse(
+ Money amountForQuote(Quote quote) => Money.safeParse(
(double.parse(fiatAmount) / quote.rate).toStringAsFixed(cryptoCurrency.decimals),
cryptoCurrency);
- Money fiatAmountForQuote(Quote quote) {
- return Money.parse(
+ Money fiatAmountForQuote(Quote quote) => Money.safeParse(
(fiatConversionStore.prices[cryptoCurrency]! *
double.parse(amountForQuote(quote).toString()))
.toStringAsFixed(2),
fiatCurrency);
- }
// based on usd values, should have roughly equal worth (was done with ai though so it's subject to correction)
static final Map<FiatCurrency, List<String>> _defaultAmountsMap = {
Why this scored 33/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.