EH-1: humanize extension signed-fee undershoot errors for retail UI (#371) #895

Merged
PlasticDigits merged 2 commits from fix/issue-371-fee-undershoot-user-copy into main 2026-06-13 03:41:13 +00:00
PlasticDigits commented 2026-06-13 03:07:24 +00:00 (Migrated from gitlab.com)

Summary

When Keplr (or another extension wallet) signs a fee far below the dApp envelope on LocalTerra, the Swap UI was showing the full developer diagnostic string — GitLab issue refs, npm ci shell instructions, raw uluna amounts, and Station-specific troubleshooting.

This MR routes those errors through retail copy (Transaction fee mismatch…) while keeping the detailed diagnostic in console.error via the existing broadcast catch path.

Verification checklist

Acceptance item Command / result Status
Verbatim issue error string is not shown in UI humanization path cd frontend-dapp && npm run test -- --run src/utils/__tests__/humanizeTerraTxError.test.ts — new #371 case PASS PASS
humanizeUserFacingError strips GitLab refs, uluna, CLI, Station copy npm run test -- --run src/utils/__tests__/humanizeUserFacingError.test.ts — #371 case PASS PASS
TxResultAlert (Swap error surface) shows retail copy only npm run test -- --run src/components/ui/__tests__/TxResultAlert.test.tsx — #371 case PASS PASS
Broadcast path throws humanized error (not raw diagnostic) npm run test -- --run src/services/terraclassic/__tests__/terraBroadcast.test.ts — updated #371 case PASS PASS
Developer guard still emits diagnostic for logs/tests npm run test -- --run src/utils/__tests__/extensionSignedFeeGuard.test.ts — unchanged, PASS PASS
Manual: Keplr + low gas on / Swap (issue repro steps) make deploy-local-no-build failed at wrap-mapper (empty address string); chain deploy incomplete — not re-run FAIL (blocked)

Follow-ups

  • Re-run manual Keplr low-gas repro on Swap after a successful make setup-cloud-localterra deploy on a clean VM.

Note

Low Risk
Test-only changes with no runtime logic; low risk aside from possible duplicate test maintenance in humanizeTerraTxError.

Overview
Adds and tightens Vitest coverage for GitLab #371: when swap/error surfaces receive the long extension post-sign fee undershoot diagnostic (GitLab refs, npm ci, raw uluna/gas numbers, Station/LocalTerra troubleshooting), the UI path must show retail Transaction fee mismatch… copy only.

TxResultAlert.test.tsx — new case asserting TxResultAlert humanizes the full repro string and hides developer tokens.

humanizeTerraTxError.test.ts — duplicate #371 case under the insufficient-fees suite so tryHumanizeTerraTxMessage strips the verbose guard text.

humanizeUserFacingError.test.ts — updates the #371 fixture from a short uluna-only message to the full diagnostic string (including gas mismatch) so the top-level humanizeUserFacingError funnel matches production throws.

No production source changes in this diff; tests document the contract for TxResultAlert, Terra tx humanization, and the user-facing error funnel.

Reviewed by Cursor Bugbot for commit b8238b0237. Bugbot is set up for automated code reviews on this repo. Configure here.

## Summary When Keplr (or another extension wallet) signs a fee far below the dApp envelope on LocalTerra, the Swap UI was showing the full developer diagnostic string — GitLab issue refs, `npm ci` shell instructions, raw `uluna` amounts, and Station-specific troubleshooting. This MR routes those errors through retail copy (`Transaction fee mismatch…`) while keeping the detailed diagnostic in `console.error` via the existing broadcast catch path. ## Verification checklist | Acceptance item | Command / result | Status | |-----------------|------------------|--------| | Verbatim issue error string is **not** shown in UI humanization path | `cd frontend-dapp && npm run test -- --run src/utils/__tests__/humanizeTerraTxError.test.ts` — new `#371` case PASS | PASS | | `humanizeUserFacingError` strips GitLab refs, uluna, CLI, Station copy | `npm run test -- --run src/utils/__tests__/humanizeUserFacingError.test.ts` — `#371` case PASS | PASS | | `TxResultAlert` (Swap error surface) shows retail copy only | `npm run test -- --run src/components/ui/__tests__/TxResultAlert.test.tsx` — `#371` case PASS | PASS | | Broadcast path throws humanized error (not raw diagnostic) | `npm run test -- --run src/services/terraclassic/__tests__/terraBroadcast.test.ts` — updated `#371` case PASS | PASS | | Developer guard still emits diagnostic for logs/tests | `npm run test -- --run src/utils/__tests__/extensionSignedFeeGuard.test.ts` — unchanged, PASS | PASS | | Manual: Keplr + low gas on `/` Swap (issue repro steps) | `make deploy-local-no-build` failed at wrap-mapper (`empty address string`); chain deploy incomplete — **not re-run** | FAIL (blocked) | ## Follow-ups - Re-run manual Keplr low-gas repro on Swap after a successful `make setup-cloud-localterra` deploy on a clean VM. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only changes with no runtime logic; low risk aside from possible duplicate test maintenance in humanizeTerraTxError. > > **Overview** > Adds and tightens **Vitest** coverage for GitLab **#371**: when swap/error surfaces receive the long **extension post-sign fee undershoot** diagnostic (GitLab refs, `npm ci`, raw `uluna`/gas numbers, Station/LocalTerra troubleshooting), the UI path must show retail **Transaction fee mismatch…** copy only. > > **`TxResultAlert.test.tsx`** — new case asserting `TxResultAlert` humanizes the full repro string and hides developer tokens. > > **`humanizeTerraTxError.test.ts`** — duplicate **#371** case under the insufficient-fees suite so `tryHumanizeTerraTxMessage` strips the verbose guard text. > > **`humanizeUserFacingError.test.ts`** — updates the **#371** fixture from a short uluna-only message to the **full** diagnostic string (including gas mismatch) so the top-level `humanizeUserFacingError` funnel matches production throws. > > No production source changes in this diff; tests document the contract for `TxResultAlert`, Terra tx humanization, and the user-facing error funnel. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b8238b02375d2622c626a513b9e6b888e7997c97. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
ghost1 commented 2026-06-13 03:07:40 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-13 03:07:47 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-13 03:09:36 +00:00 (Migrated from gitlab.com)

Security review — MR !895

Commit reviewed: f8e2cfc11dd96f03fcbcdf14f237b00fc4750098
Scope: EH-1 — humanize extension signed-fee undershoot errors for retail UI (#371). Touches extensionSignedFeeGuard.ts, humanizeTerraTxError.ts, terraBroadcast.ts, and related unit tests.

Outcome: FINDINGS: 0 medium+

Summary

Reviewed added/modified paths for injection, authn/authz bypass, secret leakage, XSS, and unsafe error surfacing. This MR only changes user-visible error copy: the post-sign fee undershoot guard still throws the full diagnostic (logged via console.error in broadcastTerraExecuteContracts), while tryHumanizeTerraTxMessage now returns the static constant EXTENSION_SIGNED_FEE_USER_MESSAGE instead of echoing the diagnostic string. The terraBroadcast bypass that previously passed those errors through unhumanized was removed so UI and broadcast paths stay consistent.

Controls verified:

  • UI render (TxResultAlert) uses React text interpolation — no dangerouslySetInnerHTML.
  • Humanized output is a hardcoded string; numeric wallet fee fields from the guard are no longer shown in the UI.
  • No auth, signing, fee-envelope, or on-chain logic changes; cosmes patch / guard thresholds unchanged.

Prefix-match note (below medium): inner.includes(EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX) could theoretically match an attacker-crafted chain error containing that exact dApp-internal substring, but the impact is limited to a benign misleading retail message — not fund loss, privilege escalation, or script execution.

Inline threads: none (no medium+ findings).

Security review: no medium+ findings on this diff.

## Security review — MR !895 **Commit reviewed:** `f8e2cfc11dd96f03fcbcdf14f237b00fc4750098` **Scope:** EH-1 — humanize extension signed-fee undershoot errors for retail UI (#371). Touches `extensionSignedFeeGuard.ts`, `humanizeTerraTxError.ts`, `terraBroadcast.ts`, and related unit tests. **Outcome:** `FINDINGS: 0` medium+ ### Summary Reviewed added/modified paths for injection, authn/authz bypass, secret leakage, XSS, and unsafe error surfacing. This MR only changes **user-visible error copy**: the post-sign fee undershoot guard still throws the full diagnostic (logged via `console.error` in `broadcastTerraExecuteContracts`), while `tryHumanizeTerraTxMessage` now returns the static constant `EXTENSION_SIGNED_FEE_USER_MESSAGE` instead of echoing the diagnostic string. The `terraBroadcast` bypass that previously passed those errors through unhumanized was removed so UI and broadcast paths stay consistent. **Controls verified:** - UI render (`TxResultAlert`) uses React text interpolation — no `dangerouslySetInnerHTML`. - Humanized output is a hardcoded string; numeric wallet fee fields from the guard are no longer shown in the UI. - No auth, signing, fee-envelope, or on-chain logic changes; cosmes patch / guard thresholds unchanged. **Prefix-match note (below medium):** `inner.includes(EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX)` could theoretically match an attacker-crafted chain error containing that exact dApp-internal substring, but the impact is limited to a benign misleading retail message — not fund loss, privilege escalation, or script execution. **Inline threads:** none (no medium+ findings). Security review: no medium+ findings on this diff.
PlasticDigits commented 2026-06-13 03:38:24 +00:00 (Migrated from gitlab.com)

added 92 commits

  • f8e2cfc1...cccd4cf2 - 91 commits from branch main
  • b8238b02 - Merge origin/main into fix/issue-371-fee-undershoot-user-copy.

Compare with previous version

added 92 commits <ul><li>f8e2cfc1...cccd4cf2 - 91 commits from branch <code>main</code></li><li>b8238b02 - Merge origin/main into fix/issue-371-fee-undershoot-user-copy.</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/177/diffs?diff_id=1850147536&start_sha=f8e2cfc11dd96f03fcbcdf14f237b00fc4750098)
PlasticDigits commented 2026-06-13 03:38:28 +00:00 (Migrated from gitlab.com)

Resolved merge conflicts with main by merging latest origin/main into this branch.

Conflicts resolved (4 files):

  • terraBroadcast.ts — kept main's split-sign/recovery broadcast path and isTerraTxTimeoutMessage; preserved #371 behavior (no raw fee-guard bypass before humanization).
  • humanizeTerraTxError.ts — unified on EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE from main.
  • extensionSignedFeeGuard.ts — dropped duplicate EXTENSION_SIGNED_FEE_USER_MESSAGE alias.
  • Test files — combined main's stricter assertions with #371 diagnostic fixtures.

Sanity: 62 related frontend unit tests pass (humanizeTerraTxError, humanizeUserFacingError, TxResultAlert, terraBroadcast, extensionSignedFeeGuard).

Resolved merge conflicts with `main` by merging latest `origin/main` into this branch. **Conflicts resolved (4 files):** - `terraBroadcast.ts` — kept main's split-sign/recovery broadcast path and `isTerraTxTimeoutMessage`; preserved #371 behavior (no raw fee-guard bypass before humanization). - `humanizeTerraTxError.ts` — unified on `EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE` from main. - `extensionSignedFeeGuard.ts` — dropped duplicate `EXTENSION_SIGNED_FEE_USER_MESSAGE` alias. - Test files — combined main's stricter assertions with #371 diagnostic fixtures. **Sanity:** 62 related frontend unit tests pass (`humanizeTerraTxError`, `humanizeUserFacingError`, `TxResultAlert`, `terraBroadcast`, `extensionSignedFeeGuard`).
ghost1 commented 2026-06-13 03:38:44 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-13 03:40:18 +00:00 (Migrated from gitlab.com)

Security review — MR !895

Commit reviewed: b8238b02375d2622c626a513b9e6b888e7997c97
Scope: EH-1 — humanize extension signed-fee undershoot errors for retail UI (#371). This revision touches only Vitest coverage in TxResultAlert.test.tsx, humanizeTerraTxError.test.ts, and humanizeUserFacingError.test.ts (fixture expansion + new #371 assertions). No production/runtime source files in the diff.

Outcome: FINDINGS: 0 medium+

Summary

Re-reviewed the MR diff and traced the error-surfacing path the tests exercise (extensionSignedFeeGuard → terraWalletSignTxRaw / terraBroadcast → humanizeUserFacingError → TxResultAlert). The added tests only assert that legacy verbose diagnostic strings (GitLab refs, npm ci, raw uluna/gas figures) are replaced with the static retail constant EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE before UI render.

Controls verified (unchanged production paths referenced by tests):

  • extensionSignedFeeGuard returns the hardcoded user message; detailed diagnostics go to console.warn only.
  • tryHumanizeTerraTxMessage maps prefix/legacy diagnostic input to the same static string — no echo of wallet numeric fields or shell instructions in UI output.
  • TxResultAlert renders via React text interpolation (humanizeUserFacingError); no dangerouslySetInnerHTML.
  • No authn/authz, signing, fee-envelope, cosmes patch, or on-chain logic changes in this diff.

Prefix-match note (below medium, unchanged): inner.includes(EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX) could match a chain error containing that exact internal substring, but impact is limited to a benign misleading retail message — not fund loss, privilege escalation, or script execution.

Inline threads: none (no medium+ findings).

Security review: no medium+ findings on this diff.

## Security review — MR !895 **Commit reviewed:** `b8238b02375d2622c626a513b9e6b888e7997c97` **Scope:** EH-1 — humanize extension signed-fee undershoot errors for retail UI (#371). This revision touches only Vitest coverage in `TxResultAlert.test.tsx`, `humanizeTerraTxError.test.ts`, and `humanizeUserFacingError.test.ts` (fixture expansion + new `#371` assertions). No production/runtime source files in the diff. **Outcome:** `FINDINGS: 0` medium+ ### Summary Re-reviewed the MR diff and traced the error-surfacing path the tests exercise (`extensionSignedFeeGuard` → `terraWalletSignTxRaw` / `terraBroadcast` → `humanizeUserFacingError` → `TxResultAlert`). The added tests only assert that legacy verbose diagnostic strings (GitLab refs, `npm ci`, raw `uluna`/gas figures) are replaced with the static retail constant `EXTENSION_SIGNED_FEE_UNDERSHOOT_USER_MESSAGE` before UI render. **Controls verified (unchanged production paths referenced by tests):** - `extensionSignedFeeGuard` returns the hardcoded user message; detailed diagnostics go to `console.warn` only. - `tryHumanizeTerraTxMessage` maps prefix/legacy diagnostic input to the same static string — no echo of wallet numeric fields or shell instructions in UI output. - `TxResultAlert` renders via React text interpolation (`humanizeUserFacingError`); no `dangerouslySetInnerHTML`. - No authn/authz, signing, fee-envelope, cosmes patch, or on-chain logic changes in this diff. **Prefix-match note (below medium, unchanged):** `inner.includes(EXTENSION_SIGNED_FEE_UNDERSHOOT_PREFIX)` could match a chain error containing that exact internal substring, but impact is limited to a benign misleading retail message — not fund loss, privilege escalation, or script execution. **Inline threads:** none (no medium+ findings). Security review: no medium+ findings on this diff.
PlasticDigits commented 2026-06-13 03:41:13 +00:00 (Migrated from gitlab.com)

mentioned in commit fe5c3c2fb5

mentioned in commit fe5c3c2fb5160938bd33e44b549976cac2e0e751
PlasticDigits (Migrated from gitlab.com) merged commit fe5c3c2fb5 into main 2026-06-13 03:41:13 +00:00
Sign in to join this conversation.
No reviewers
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!895
No description provided.