Security: limit order pre-sign modal missing chain label before wallet dialog opens [SEC-I05] (F02) #461

Closed
opened 2026-06-30 18:31:44 +00:00 by totdking · 18 comments
totdking commented 2026-06-30 18:31:44 +00:00 (Migrated from gitlab.com)
No description provided.
totdking commented 2026-06-30 18:32:26 +00:00 (Migrated from gitlab.com)

Summary

The swap pre-sign summary card (SwapPreSubmitSummary.tsx) displays action, pair tokens, amounts, max spread, min return, and chain label before the Keplr wallet dialog appears. The limit order pre-sign path shows fee and deviation only. No in-app chain anchor (chain name, chain ID, or network badge) is surfaced before the wallet dialog for limit order placement. A phishing page substituting a different chain could display the same limit order form without the user seeing the chain name before they approve in Keplr.


What Was Checked

  • frontend-dapp/src/components/swap/SwapPreSubmitSummary.tsx: renders chainFullLabel from getNetworkBadgeCopy().fullLabel before wallet dispatch.
  • frontend-dapp/src/pages/LimitOrdersPage.tsx line 703 and frontend-dapp/src/components/trade/TradeOrderTicket.tsx line 831: pre-sign entry points for limit order placement. No equivalent pre-sign summary card with chain label found.
  • frontend-dapp/src/components/trade/TradeOrderTicket.tsx: renders fee estimate and price deviation before submit, but not chain, pair address, or network badge.

Expected (per checklist)

All transaction types (swap, limit order, provide, withdraw) show at minimum the chain label and action type in an in-app confirmation card before the wallet dialog opens, consistent with the SEC-D11 anti-phishing protection applied to swaps.


Actual

Limit order placement has no pre-sign summary card with chain label. The first explicit chain identification the user sees is inside the Keplr dialog.


Suggested Fix

Add a pre-sign summary step to TradeOrderTicket.tsx and LimitOrdersPage.tsx that surfaces: action ("Place Limit Order"), pair, side (buy/sell), amount, price, and chain label before dispatching the Keplr signing request. Reuse or extend SwapPreSubmitSummary or create LimitOrderPreSubmitSummary following the same pattern.


Verification Checklist

  • Limit order placement renders a pre-sign summary card showing chain label, action type, pair, side, and amount
  • Chain label derives from getNetworkBadgeCopy().fullLabel (same as swap summary)
  • Unit test asserts the chain label field is rendered in the limit order pre-sign summary
  • Keplr wallet dialog is not the first place chain is identified to the user during limit order placement

Cc: @PlasticDigits

### Summary The swap pre-sign summary card (`SwapPreSubmitSummary.tsx`) displays action, pair tokens, amounts, max spread, min return, and chain label before the Keplr wallet dialog appears. The limit order pre-sign path shows fee and deviation only. No in-app chain anchor (chain name, chain ID, or network badge) is surfaced before the wallet dialog for limit order placement. A phishing page substituting a different chain could display the same limit order form without the user seeing the chain name before they approve in Keplr. --- ### What Was Checked - `frontend-dapp/src/components/swap/SwapPreSubmitSummary.tsx`: renders `chainFullLabel` from `getNetworkBadgeCopy().fullLabel` before wallet dispatch. - `frontend-dapp/src/pages/LimitOrdersPage.tsx` line 703 and `frontend-dapp/src/components/trade/TradeOrderTicket.tsx` line 831: pre-sign entry points for limit order placement. No equivalent pre-sign summary card with chain label found. - `frontend-dapp/src/components/trade/TradeOrderTicket.tsx`: renders fee estimate and price deviation before submit, but not chain, pair address, or network badge. --- ### Expected (per checklist) All transaction types (swap, limit order, provide, withdraw) show at minimum the chain label and action type in an in-app confirmation card before the wallet dialog opens, consistent with the SEC-D11 anti-phishing protection applied to swaps. --- ### Actual Limit order placement has no pre-sign summary card with chain label. The first explicit chain identification the user sees is inside the Keplr dialog. --- ### Suggested Fix Add a pre-sign summary step to `TradeOrderTicket.tsx` and `LimitOrdersPage.tsx` that surfaces: action ("Place Limit Order"), pair, side (buy/sell), amount, price, and chain label before dispatching the Keplr signing request. Reuse or extend `SwapPreSubmitSummary` or create `LimitOrderPreSubmitSummary` following the same pattern. --- ### Verification Checklist - [ ] Limit order placement renders a pre-sign summary card showing chain label, action type, pair, side, and amount - [ ] Chain label derives from `getNetworkBadgeCopy().fullLabel` (same as swap summary) - [ ] Unit test asserts the chain label field is rendered in the limit order pre-sign summary - [ ] Keplr wallet dialog is not the first place chain is identified to the user during limit order placement Cc: @PlasticDigits
totdking commented 2026-06-30 18:37:45 +00:00 (Migrated from gitlab.com)

mentioned in issue #454

mentioned in issue #454
totdking commented 2026-06-30 18:37:56 +00:00 (Migrated from gitlab.com)

mentioned in issue #381

mentioned in issue #381
Brouie commented 2026-06-30 19:27:45 +00:00 (Migrated from gitlab.com)

mentioned in merge request !989

mentioned in merge request !989
Brouie commented 2026-06-30 19:29:04 +00:00 (Migrated from gitlab.com)

Fixed. The limit-order pre-sign card (LimitOrderPreSubmitSummary) already exists and shows deviation + maker fee + network fee, but had no in-app chain anchor — so the first chain identification during limit placement was the Keplr dialog.

Added a Chain row deriving from getNetworkBadgeCopy().fullLabel (same source the swap pre-sign card uses), via a new optional chainFullLabel prop defaulting to the env badge. The card is already rendered in TradeOrderTicket before the place dispatch, so the chain anchor now shows pre-wallet on the limit path too.

Tests: new case asserts the -chain row renders the label; component suite 4/0, tsc clean. Source + unit verified here; the before-the-wallet-dialog placement is a laptop browser confirmation.

MR !989, branch qa/461-limit-presign-chain-label, commit 8ca9eb51. Needs review/merge @PlasticDigits — leaving open for verification.

Fixed. The limit-order pre-sign card (`LimitOrderPreSubmitSummary`) already exists and shows deviation + maker fee + network fee, but had no in-app chain anchor — so the first chain identification during limit placement was the Keplr dialog. Added a Chain row deriving from `getNetworkBadgeCopy().fullLabel` (same source the swap pre-sign card uses), via a new optional `chainFullLabel` prop defaulting to the env badge. The card is already rendered in `TradeOrderTicket` before the place dispatch, so the chain anchor now shows pre-wallet on the limit path too. Tests: new case asserts the `-chain` row renders the label; component suite 4/0, tsc clean. Source + unit verified here; the before-the-wallet-dialog placement is a laptop browser confirmation. MR !989, branch `qa/461-limit-presign-chain-label`, commit `8ca9eb51`. Needs review/merge @PlasticDigits — leaving open for verification.
PlasticDigits commented 2026-06-30 22:07:21 +00:00 (Migrated from gitlab.com)

mentioned in commit b803ac105b

mentioned in commit b803ac105b64663fcf3291410f5bc4e29b4cb904
PlasticDigits commented 2026-06-30 22:08:43 +00:00 (Migrated from gitlab.com)

Fix needs review to reduce user cognitive overload

Fix needs review to reduce user cognitive overload
PlasticDigits commented 2026-06-30 22:20:14 +00:00 (Migrated from gitlab.com)

mentioned in commit 16d19e715a

mentioned in commit 16d19e715afb515fc5edb1fe75bdf6546588072d
PlasticDigits commented 2026-06-30 22:20:23 +00:00 (Migrated from gitlab.com)

mentioned in merge request !995

mentioned in merge request !995
PlasticDigits commented 2026-07-01 00:08:31 +00:00 (Migrated from gitlab.com)

mentioned in commit 79943b6df1

mentioned in commit 79943b6df1a06dbd5dc849ac80a9f7cce2553929
PlasticDigits commented 2026-07-01 00:11:30 +00:00 (Migrated from gitlab.com)

mentioned in commit b2b067ec8f

mentioned in commit b2b067ec8f19d60bd0a60a460cfc79acbd3c737b
PlasticDigits commented 2026-07-01 00:11:32 +00:00 (Migrated from gitlab.com)

mentioned in merge request !997

mentioned in merge request !997
PlasticDigits commented 2026-07-01 00:33:34 +00:00 (Migrated from gitlab.com)

mentioned in commit 4dad91d80d

mentioned in commit 4dad91d80d80e5a609e91124efb4903f021706d5
PlasticDigits commented 2026-07-01 00:33:37 +00:00 (Migrated from gitlab.com)

mentioned in merge request !991

mentioned in merge request !991
PlasticDigits commented 2026-07-01 01:03:44 +00:00 (Migrated from gitlab.com)

mentioned in commit ee5f71d8ba

mentioned in commit ee5f71d8ba6526f06f0ff113491ac8ec3349ba1d
PlasticDigits commented 2026-07-01 01:03:56 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1000

mentioned in merge request !1000
PlasticDigits commented 2026-07-01 01:11:42 +00:00 (Migrated from gitlab.com)

mentioned in commit 4f4f4de102

mentioned in commit 4f4f4de1023295e1b3fb1ed518c08e6b95ed1bad
PlasticDigits commented 2026-07-01 01:36:00 +00:00 (Migrated from gitlab.com)

Verification — #461 (SEC-I05 F02)

Result: PASS — fix on main (LimitOrderPreSubmitSummary chain anchor; MR !989 + follow-up ee5f71d8).

Checklist

Criterion Result How verified
Limit order pre-sign card shows chain label, action, pair, side, amount PASS LimitOrderPreSubmitSummary.tsx renders Action/Pair/Side/Amount/Chain rows; mounted in LimitOrdersPage.tsx and TradeOrderTicket.tsx before Place dispatch
Chain label from getNetworkBadgeCopy().fullLabel (same as swap) PASS Default prop chainFullLabel = getNetworkBadgeCopy().fullLabel in LimitOrderPreSubmitSummary.tsx (mirrors SwapPreSubmitSummary.tsx)
Unit test asserts chain label in limit pre-sign summary PASS npm test -- --run src/components/trade/__tests__/LimitOrderPreSubmitSummary.test.tsx → 5/5 pass, including #461 case on -chain row
Chain not first identified only in Keplr during limit placement PASS Page tests: LimitOrdersPage.test.tsx (limits-page-pre-submit-summary-chain → LocalTerra), TradePage.test.tsx (trade-limit-pre-submit-summary-chain → LocalTerra); Playwright smoke on LocalTerra /limits — pre-submit card visible with “Review these fields before your wallet opens” and chain row before Place limit (Simulated Wallet)

Commands run

bash scripts/with-node.sh --cwd frontend-dapp -- npm test -- --run \
  src/components/trade/__tests__/LimitOrderPreSubmitSummary.test.tsx \
  src/pages/LimitOrdersPage.test.tsx \
  src/pages/TradePage.test.tsx
# 53/53 pass

make setup-cloud-localterra --fresh --skip-build   # LocalTerra + deploy + indexer
make dev                                           # frontend on :5173
# Playwright e2e-smoke spot-check: /limits pre-submit summary + chain row visible pre-wallet

Follow-up

@PlasticDigits noted the card may still feel cognitively heavy (deviation + maker fee + network fee alongside the new chain anchor). Consider a follow-up UX pass to tighten copy/layout while keeping the SEC-D11 chain anchor visible.

## Verification — #461 (SEC-I05 F02) **Result: PASS** — fix on `main` (`LimitOrderPreSubmitSummary` chain anchor; MR !989 + follow-up `ee5f71d8`). ### Checklist | Criterion | Result | How verified | |-----------|--------|--------------| | Limit order pre-sign card shows chain label, action, pair, side, amount | **PASS** | `LimitOrderPreSubmitSummary.tsx` renders Action/Pair/Side/Amount/Chain rows; mounted in `LimitOrdersPage.tsx` and `TradeOrderTicket.tsx` before Place dispatch | | Chain label from `getNetworkBadgeCopy().fullLabel` (same as swap) | **PASS** | Default prop `chainFullLabel = getNetworkBadgeCopy().fullLabel` in `LimitOrderPreSubmitSummary.tsx` (mirrors `SwapPreSubmitSummary.tsx`) | | Unit test asserts chain label in limit pre-sign summary | **PASS** | `npm test -- --run src/components/trade/__tests__/LimitOrderPreSubmitSummary.test.tsx` → 5/5 pass, including `#461` case on `-chain` row | | Chain not first identified only in Keplr during limit placement | **PASS** | Page tests: `LimitOrdersPage.test.tsx` (`limits-page-pre-submit-summary-chain` → `LocalTerra`), `TradePage.test.tsx` (`trade-limit-pre-submit-summary-chain` → `LocalTerra`); Playwright smoke on LocalTerra `/limits` — pre-submit card visible with “Review these fields before your wallet opens” and chain row **before** Place limit (Simulated Wallet) | ### Commands run ```bash bash scripts/with-node.sh --cwd frontend-dapp -- npm test -- --run \ src/components/trade/__tests__/LimitOrderPreSubmitSummary.test.tsx \ src/pages/LimitOrdersPage.test.tsx \ src/pages/TradePage.test.tsx # 53/53 pass make setup-cloud-localterra --fresh --skip-build # LocalTerra + deploy + indexer make dev # frontend on :5173 # Playwright e2e-smoke spot-check: /limits pre-submit summary + chain row visible pre-wallet ``` ### Follow-up @PlasticDigits noted the card may still feel cognitively heavy (deviation + maker fee + network fee alongside the new chain anchor). Consider a follow-up UX pass to tighten copy/layout while keeping the SEC-D11 chain anchor visible.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-07-01 01:36:01 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#461
No description provided.