swaps dialog: in callbacks, update either send or receive field, depending on which one follows
What changed, and why it matters
This commit fixes a UI behavior bug in Electrum's swap dialog. Previously, when certain events happened (like fee updates), the dialog would recalculate both the 'send' and 'receive' fields, which could overwrite a value the user had just typed. Now it only updates the field that is supposed to automatically follow from the other, leaving the user's manual input alone. There is no direct evidence this is a security vulnerability.
No immediate security action required. Treat as a normal UI bug fix. If auditing, verify that the send_follows flag correctly tracks user intent and that no race conditions remain between manual edits and callback updates.
Security signals we found
UI state inconsistency fixed
No explicit security relevance in commit message
No input validation or boundary changes
No cryptographic or network changes
No privilege or authorization changes
Evidence from the diff
The patch refactors callback handling in electrum/gui/qt/swap_dialog.py. Previously, event callbacks called both on_send_edited() and on_recv_edited(), which could modify the non-following field’s content. The change introduces update_send_receive(), which calls only on_recv_edited() if send_follows is True, or on_send_edited() otherwise. This preserves the invariant that only the dependent/following field is updated from the leading field. The commit message describes this as a UI consistency fix, not a security fix.
Changed components
electrum/gui/qt/swap_dialog.pySwapDialog UI callbacksInspect captured patch +7 / −10
diff --git a/electrum/gui/qt/swap_dialog.py b/electrum/gui/qt/swap_dialog.py
index 2a612e9..cfa85b9 100644
--- a/electrum/gui/qt/swap_dialog.py
+++ b/electrum/gui/qt/swap_dialog.py
@@ -150,13 +150,11 @@ class SwapDialog(WindowModalDialog, QtEventListener):
@qt_event_listener
def on_event_fee_histogram(self, *args):
- self.on_send_edited()
- self.on_recv_edited()
+ self.update_send_receive()
@qt_event_listener
def on_event_fee(self, *args):
- self.on_send_edited()
- self.on_recv_edited()
+ self.update_send_receive()
@qt_event_listener
def on_event_swap_offers_changed(self, recent_offers: Sequence['SwapOffer']):
@@ -190,10 +188,7 @@ class SwapDialog(WindowModalDialog, QtEventListener):
self.config.FEE_POLICY = self.fee_policy.get_descriptor()
if not self.is_reverse:
self.fee_target_label.setText(self.fee_policy.get_target_text())
- if self.send_follows:
- self.on_recv_edited()
- else:
- self.on_send_edited()
+ self.update_send_receive()
self.update()
def _set_fee_slider_visibility(self, *, is_visible: bool):
@@ -277,6 +272,9 @@ class SwapDialog(WindowModalDialog, QtEventListener):
self.send_follows = True
self.needs_tx_update = True
+ def update_send_receive(self):
+ self.on_recv_edited() if self.send_follows else self.on_send_edited()
+
def update(self):
sm = self.swap_manager
w_base_unit = self.window.base_unit()
@@ -457,8 +455,7 @@ class SwapDialog(WindowModalDialog, QtEventListener):
def choose_swap_server(self, transport: 'SwapServerTransport') -> None:
self.window.choose_swapserver_dialog(transport) # type: ignore
self.update()
- self.on_send_edited()
- self.on_recv_edited()
+ self.update_send_receive()
class SwapServerDialog(WindowModalDialog, QtEventListener):
Why this scored 15/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.