Skip to content

Signing UI does not indicate fee-bump transactions (design needed) #2941

Description

@JakeUrban

TL;DR (for the designer)

When a dApp asks Freighter to sign a fee-bump transaction, our "Confirm Transaction" screen shows the wrong picture: it displays somebody else's operations as if the user were approving them, and never tells the user that all they're actually agreeing to is paying a network fee for someone else's transaction. We need a signing UX that makes fee bumps clear. This ticket is design-first — engineering notes for related bugs are at the bottom so they don't get lost after design is done.

Context / not a security fire drill: This surfaced via a HackerOne report that was closed as informative — signing a fee bump carries no new security risk beyond what we already accept for normal transactions. But the report did identify genuine UI bugs in how we render fee bumps, and those are worth fixing. Treat this as a UX-clarity improvement, not an urgent security patch.


What is a fee-bump transaction? (plain language)

Stellar lets one account pay the network fee on behalf of another account's already-signed transaction. That wrapper is a fee-bump transaction.

The key thing: when you sign a fee bump, you are authorizing exactly one thing"I agree to pay the network fee for this other transaction." You are not authorizing any of the operations (payments, trustlines, claims, etc.) inside it. Those were created and signed by someone else. Your signature just foots the fee bill and names you, on-chain, as the payer.

The problem today

For a fee-bump transaction, the "Confirm Transaction" screen:

  • shows the inner (someone else's) operations as if they were what the user is approving;
  • has no label anywhere saying "fee bump";
  • never names who actually pays (the fee-source account) or whose transaction is being paid for (the inner source account);
  • says nothing to distinguish "operations you are authorizing" from "operations you are merely paying the fee for."

Net effect: a dApp can show the user a friendly-looking operation ("You receive 1,000 XLM", "Claim airdrop"), the user clicks Confirm, and their signature authorizes none of it — it only commits them to paying a fee for a stranger's transaction.

What we need designed

A signing screen + details view for fee-bump transactions that communicates, in language a non-technical user understands:

  1. This is a fee-bump transaction — an unmistakable label/heading/banner distinguishing it from a normal signing request.
  2. What the signature actually does — e.g. "You're only agreeing to pay the network fee for another account's transaction. You are not authorizing the operations below."
  3. Who pays the fee (fee-source account) and whose transaction it is (inner transaction's source account).
  4. The wrapped operations, clearly reframed — still viewable, but labeled something like "Operations in the wrapped transaction — not authorized by your signature," so they can't be misread as the user's own actions.

Today's screen for reference (no fee-bump treatment exists): a summary pane with Wallet / Network / Fee / Memo, then a "Transaction details" view listing operations, sequence #, memo, and raw XDR.


Bugs to fix alongside the redesign (engineering notes)

Confirmed against master (extension v5.44.0). Listing them so the engineer assigned after design lands doesn't miss the related defects. Root cause for all of these: the background serializer and the popup treat Transaction and FeeBumpTransaction as one shape and lean on FeeBumpTransaction.operations transparently forwarding the inner operations. The fix is to branch on the fee-bump case explicitly wherever the transaction is displayed.

  • Memo is falsely rendered as "None." For fee bumps the memo is never read, so the summary row prints "None" — a positive false statement, since the wrapped transaction can carry a memo. popup/views/SignTransaction/index.tsx:192-195 skips reading the memo for fee bumps; popup/components/TruncatedMemo/index.tsx:20-22 renders "None" for the empty value. Design should decide what the memo row shows for a fee bump (the inner transaction's memo, or an explicit "not applicable" state).
  • Details pane: "Sequence #" renders blank and the memo block is dropped entirely for fee bumps. popup/views/SignTransaction/Preview/Summary/index.tsx:52 renders the empty sequence value; :54 only renders the memo block when a value is present.
  • No fee-source / inner-source shown. The account that actually gets debited, and the account whose transaction is being paid for, are never displayed. No fee-bump branch exists in SignTransaction/index.tsx; background/helpers/transactionInfo.ts:22-24 flattens straight to the inner operations.
  • Fee row shows the fee bid, not what's charged. For a fee bump the displayed fee is the maximum bid (the ceiling the signer commits to), which can be well above the amount actually charged under normal network conditions. Worth a design decision on how to phrase this (e.g. "Max network fee").
  • (Nice to have) No guard when the active account isn't the fee source. If the user's active account isn't the fee-source of the fee bump, its signature can't make the envelope submittable — Freighter could warn instead of silently signing.

Suggested acceptance criteria

  • A fee-bump XDR renders a distinct fee-bump signing view (label + plain-language explanation of what's being authorized).
  • Fee-source and inner-source accounts are shown.
  • The memo row reflects the truth (no false "None"; correct value or an explicit N/A) in both the summary and details panes.
  • Sequence # is either shown correctly or intentionally hidden for fee bumps (no blank row).
  • Regression test: given a fee-bump XDR, the rendered tree contains the fee-bump treatment and does not assert a false memo.

Note: the identical defect exists on mobile — tracked separately in stellar/freighter-mobile.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions