add additional fee rate limit check for high fee transactions
What changed, and why it matters
This commit adds an extra safety check in Sparrow Wallet that warns users before broadcasting Bitcoin transactions with extremely high fee rates. Previously, the wallet only warned if the fee rate exceeded the top of a long-term fee rate range. Now it also warns if the fee rate is more than 100 times the default fee rate. This helps prevent users from accidentally overpaying transaction fees, which could be caused by user error, wallet misconfiguration, or potentially a malicious or compromised transaction.
No immediate action required. This is a defensive hardening change. Users should ensure they are running a Sparrow Wallet version that includes this commit if they want the additional high-fee warning. Developers may want to review whether 100x is an appropriate threshold and whether the default fee rate source is reliable.
Security signals we found
Adds a user-facing confirmation dialog for high fee rate transactions
Introduces a hard-coded multiplier limit (100x default fee rate) as a safety guard
Prevents accidental or malicious overpayment of Bitcoin transaction fees
Does not change transaction validation logic, only warning behavior
Evidence from the diff
In HeadersController.java, a new constant FEE_MULTIPLE_LIMIT = 100d is introduced. The existing warning condition for ‘Very high fee rate!’ is extended with an additional check: feeRateAmt > AppServices.getDefaultFeeRate() * FEE_MULTIPLE_LIMIT, but only if AppServices.getTargetBlockFeeRates() is non-null. This adds a second independent threshold for triggering a user confirmation dialog before broadcasting a transaction with an unusually high fee rate.
Changed components
src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.javaTransaction broadcast fee rate warning dialogInspect captured patch +3 / −1
diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
index d7d3e8e..314991f 100644
--- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
@@ -86,6 +86,8 @@ public class HeadersController extends TransactionFormController implements Init
private static final Pattern RBF_INSUFFICIENT_FEE = Pattern.compile("insufficient fee, rejecting replacement.*?(\\d+\\.?\\d*) < (\\d+\\.?\\d*)");
private static final Pattern RBF_INSUFFICIENT_FEE_RATE = Pattern.compile("insufficient fee, rejecting replacement.*new feerate (\\d+\\.?\\d*)[^\\d]*(\\d+\\.?\\d*)[^\\d]*");
+ private static final double FEE_MULTIPLE_LIMIT = 100d;
+
private HeadersForm headersForm;
@FXML
@@ -1220,7 +1222,7 @@ public class HeadersController extends TransactionFormController implements Init
if(fee.getValue() > 0) {
double feeRateAmt = fee.getValue() / headersForm.getTransaction().getVirtualSize();
- if(feeRateAmt > AppServices.getLongFeeRatesRange().getLast()) {
+ if(feeRateAmt > AppServices.getLongFeeRatesRange().getLast() || (AppServices.getTargetBlockFeeRates() != null && feeRateAmt > AppServices.getDefaultFeeRate() * FEE_MULTIPLE_LIMIT)) {
Optional<ButtonType> optType = AppServices.showWarningDialog("Very high fee rate!",
"This transaction pays a very high fee rate of " + String.format("%.0f", feeRateAmt) + " sats/vB.\n\nBroadcast this transaction?", ButtonType.YES, ButtonType.NO);
if(optType.isPresent() && optType.get() == ButtonType.NO) {
Why this scored 45/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.