QA report: external/tower.exchange at hosted
Tower Exchange fails to block or flag swaps that exceed the user's available token balance, despite core swap execution and navigation passing.
The test suite executed eleven deep-feature scenarios across the application, covering token swaps, native gas reservation on MAX selections, input validation, slippage configuration, network constraints, transaction history, bridge navigation, and the Tower AI interface. Ten scenarios passed and one failed.
The single confirmed defect is a high-severity functional issue where entering a sell amount higher than the wallet balance does not disable the Swap button or display an insufficient balance warning, allowing quotes to be fetched for impossible amounts. A second finding regarding upstream 429 rate limits in the AI agent was audited and withdrawn, as rate limit handling behaved as expected.
While standard swap flows and network guardrails function properly, failing to prevent over-balance swap submissions degrades usability and can lead to failed on-chain transactions. Addressing balance validation on the swap input is necessary to prevent invalid transaction submissions.
Run summary
| Metric | Count |
|---|
| Scenarios executed | 11 |
| Passed | 10 |
| Failed | 1 |
| Blocked | 0 |
| Findings raised | 2 |
| Issues after the audit | 1 |
| Withdrawn by the audit | 1 |
| Critical / high / medium / low | 0 / 1 / 0 / 0 |
Target: https://tower.exchange · Testing level: deep_feature · Stack: unknown
Issues
High severity
F1 · Swap action is not blocked or marked as insufficient balance when sell amount exceeds token balance
Severity: high · Type: functional · Verdict: confirmed · Scenario: S3
I reproduced the steps by entering an amount (999999999 USDC) well over the available balance (0.48 USDC) on the main swap interface at tower.exchange. As reported, the application fetched quotes (e.g. from Synthra, XyloNet) and the main action button remained as "Swap" rather than updating to an "Insufficient balance" state or appearing disabled.
Expected: The Swap button should be disabled with an 'Insufficient balance' message preventing submission of invalid transactions.
Actual: The Swap button remains active and quotes are fetched for the excessive amount without an 'Insufficient balance' warning or disabled button state.
Steps to reproduce:
- Navigate to https://tower.exchange/
- Click 'Select Token' and select a target token (such as EURC)
- In the 'Sell amount' input, enter an amount greater than the current balance (e.g. 999999999 when balance is 0.99 USDC)
- Observe the swap action button state and validation messaging
Evidence: screenshots/S3-1.png, screenshots/S3-4.png, screenshots/S3-8.png
Withdrawn findings
The Critic re-examined these claims and found the evidence did not support them. They are kept here rather than deleted.
- Tower AI agent returns 'Too many requests (upstream 429).' on user queries (S9, medium): The 429 status is a standard HTTP rate limit caused by the test harness, which S10 explicitly verifies the application handles gracefully by design. The page reported 3 console errors during the scenario.
Scenario results
| Scenario | Priority | Result | Issues |
|---|
| S1 Execute standard USDC token swap | high | pass | none |
| S2 MAX button reserves native gas | high | pass | none |
| S3 Block swap on insufficient balance | high | fail | F1 |
| S4 Block swap on empty or zero input | high | pass | none |
| S5 Apply slippage tolerance preset | high | pass | none |
| S6 Enforce Arc testnet network constraint | medium | pass | none |
| S7 View transaction activity history | medium | pass | none |
| S8 Navigate to Bridge interface | medium | pass | none |
| S9 Submit Tower AI agent query | low | pass | none |
| S10 Handle Tower AI 429 rate limits gracefully | low | pass | none |
| S11 Verify legacy AI route returns 404 gracefully | low | pass | none |
The audit
The Critic reviewed 2 findings and re-verified 2 of them live in the browser, replaying the reported steps on a fresh page.
- S9 and S10 contradict each other regarding the AI agent 429 response, with S9 filing it as a defect while S10 explicitly passes it as graceful rate-limit handling.
- A possible defect in S1 ("Console error 401 Unauthorized during standard token [redacted]") was not promoted: the live replay came back inconclusive.
What to fix first
- Disable the swap button and show an insufficient balance indicator when the sell amount exceeds the user's token balance (F1).
Coverage and caveats
In scope: DEX Swap core flow on Arc testnet; Gas reservation logic for native USDC MAX inputs; Swap validation (insufficient balance, empty/zero amounts); Slippage tolerance configuration; Network selector constraint enforcement; Transaction activity log; AI Agent chat functionality and rate limit handling.
Not covered: Bridge execution (focusing deep testing on Swap as primary DEX feature); External developer and documentation links.
- The injected wallet automatically handles connection approvals without requiring cross-window interaction
- The wallet has sufficient test USDC to perform swaps
- The Settings gear icon exists as described in the Swap flow, even if not explicitly captured in the interactive elements list
By the numbers
| Metric | Value |
|---|
| Scenarios | 10 passed, 1 failed, 0 blocked of 11 (37 planned steps) |
| Screenshots | 43 (5 explore, 36 scenario, 2 critic), 36 captioned |
| Coverage | 3 pages, 2 forms, 4 flows, 6 console errors |
| Audit | 2 findings, 2 re-verified live, 1 confirmed, 0 promoted, 1 withdrawn |
| Model calls | 185 |
| Tokens | 2,033,865 input, 9,224 output, 20,206 thinking |
| Time | 13 min |
| Wallet | 6 transactions, 6 signatures, 0 refusals on chain 5042002 |
| Stage | Calls | Input | Output | Thinking | Seconds |
|---|
| explore | 41 | 523,892 | 2,227 | 1,219 | 219 |
| plan | 1 | 3,485 | 1,900 | 2,144 | 33 |
| test | 127 | 1,358,145 | 4,217 | 9,293 | 403 |
| critique | 15 | 146,829 | 619 | 7,045 | 92 |
| report | 1 | 1,514 | 261 | 505 | 6 |