What changed, and why it matters
This commit fixes a simple math bug that could occur when a cryptocurrency wallet tries to show how far along a restore/sync is, but the current blockchain height is reported as zero. Previously, dividing by zero could produce an invalid result (infinity or 'not a number'). The change makes the progress show 0% until a real chain height is known. It is a robustness fix, not a security vulnerability that an attacker can exploit.
No urgent action required. Treat as a normal bug-fix/robustness improvement. Review whether other wallet implementations perform similar unguarded division and consider applying the same helper.
Security signals we found
Division-by-zero guard added in wallet restore progress calculation
New shared helper centralizes progress math for Epic Cash and Mimblewimblecoin wallets
Unit test added verifying zero-chain-height behavior
Evidence from the diff
The patch extracts restore-progress calculation into a shared helper, calculateRestoreProgress, which guards against division by zero when chainHeight is <= 0. It updates Epic Cash and Mimblewimblecoin wallet sync-percent getters to use the helper and adds a unit test. The prior code performed lastScannedBlock / _chainHeight directly, which in Dart yields double.infinity or double.nan when _chainHeight is 0. This could propagate into UI/event-bus state and potentially cause downstream assertions or display issues, but it is not a memory-safety or authorization bug.
Changed components
lib/wallets/wallet/impl/epiccash_wallet.dartlib/wallets/wallet/impl/mimblewimblecoin_wallet.dartlib/wallets/wallet/supporting/restore_progress.darttest/wallets/restore_progress_test.dartInspect captured patch +23 / −2
diff --git a/lib/wallets/wallet/impl/epiccash_wallet.dart b/lib/wallets/wallet/impl/epiccash_wallet.dart
index 805ea30..3e5af8a 100644
--- a/lib/wallets/wallet/impl/epiccash_wallet.dart
+++ b/lib/wallets/wallet/impl/epiccash_wallet.dart
@@ -41,6 +41,7 @@ import '../../crypto_currency/crypto_currency.dart';
import '../../models/tx_data.dart';
import '../intermediate/bip39_wallet.dart';
import '../supporting/epiccash_wallet_info_extension.dart';
+import '../supporting/restore_progress.dart';
//
// refactor of https://github.com/cypherstack/stack_wallet/blob/1d9fb4cd069f22492ece690ac788e05b8f8b1209/lib/services/coins/epiccash/epiccash_wallet.dart
@@ -58,7 +59,10 @@ class EpiccashWallet extends Bip39Wallet {
Future<double> get getSyncPercent async {
final int lastScannedBlock = info.epicData?.lastScannedBlock ?? 0;
final _chainHeight = await chainHeight;
- final double restorePercent = lastScannedBlock / _chainHeight;
+ final restorePercent = calculateRestoreProgress(
+ scannedHeight: lastScannedBlock,
+ chainHeight: _chainHeight,
+ );
GlobalEventBus.instance.fire(
RefreshPercentChangedEvent(highestPercent, walletId),
);
diff --git a/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart b/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart
index 02797e4..6a65be7 100644
--- a/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart
+++ b/lib/wallets/wallet/impl/mimblewimblecoin_wallet.dart
@@ -35,6 +35,7 @@ import '../../crypto_currency/crypto_currency.dart';
import '../../models/tx_data.dart';
import '../intermediate/bip39_wallet.dart';
import '../supporting/mimblewimblecoin_wallet_info_extension.dart';
+import '../supporting/restore_progress.dart';
class MimblewimblecoinWallet extends Bip39Wallet {
MimblewimblecoinWallet(CryptoCurrencyNetwork network)
@@ -55,7 +56,10 @@ class MimblewimblecoinWallet extends Bip39Wallet {
final int lastScannedBlock =
info.mimblewimblecoinData?.lastScannedBlock ?? 0;
final _chainHeight = await chainHeight;
- final double restorePercent = lastScannedBlock / _chainHeight;
+ final restorePercent = calculateRestoreProgress(
+ scannedHeight: lastScannedBlock,
+ chainHeight: _chainHeight,
+ );
GlobalEventBus.instance.fire(
RefreshPercentChangedEvent(highestPercent, walletId),
);
diff --git a/lib/wallets/wallet/supporting/restore_progress.dart b/lib/wallets/wallet/supporting/restore_progress.dart
new file mode 100644
index 0000000..c2516b6
--- /dev/null
+++ b/lib/wallets/wallet/supporting/restore_progress.dart
@@ -0,0 +1,4 @@
+double calculateRestoreProgress({
+ required int scannedHeight,
+ required int chainHeight,
+}) => chainHeight <= 0 ? 0.0 : scannedHeight / chainHeight;
diff --git a/test/wallets/restore_progress_test.dart b/test/wallets/restore_progress_test.dart
new file mode 100644
index 0000000..b1c9729
--- /dev/null
+++ b/test/wallets/restore_progress_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+import 'package:stackwallet/wallets/wallet/supporting/restore_progress.dart';
+
+void main() {
+ test('restore progress waits for a chain height', () {
+ expect(calculateRestoreProgress(scannedHeight: 25, chainHeight: 0), 0);
+ expect(calculateRestoreProgress(scannedHeight: 25, chainHeight: 100), 0.25);
+ });
+}
Why this scored 19/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.