QA report: external/www.swaparc.app at hosted
The application exhibits critical balance calculation flaws that omit gas reserves, unhandled disconnected states in liquidity pools, and broken transaction history due to CORS errors.
Testing covered core decentralized exchange workflows including wallet connections, token swaps, Mini Wallet transfers, liquidity provisioning, and PrivPay features across twelve scenarios. Out of twelve scenarios, five passed, three failed, and four were blocked by headless Web3 signature requirements and missing interface controls.
Multiple high-severity functional defects break core user flows. Selecting the maximum balance in both the swap interface and the Mini Wallet allocates the entire USDC balance without holding back gas reserves for network fees. Furthermore, attempting to supply liquidity without an attached wallet produces no UI feedback or connection prompt, and the transaction history view fails silently due to cross-origin resource sharing restrictions on the backend API.
These failures risk failed on-chain transactions and leave users without transaction visibility or clear error states. The gas reservation logic, unauthenticated action handling, and API CORS configurations should be addressed before general release.
Run summary
| Metric | Count |
|---|
| Scenarios executed | 12 |
| Passed | 5 |
| Failed | 3 |
| Blocked | 4 |
| Findings raised | 3 |
| Issues after the audit | 4 |
| Withdrawn by the audit | 0 |
| Critical / high / medium / low | 0 / 3 / 1 / 0 |
Target: https://www.swaparc.app/ · Testing level: deep_feature · Stack: unknown
Issues
High severity
F1 · USDC Max button fills 100% of balance without gas reservation on Arc testnet
Severity: high · Type: functional · Verdict: confirmed · Scenario: S3
The observations confirm the 'Max' button populates the input field with the exact total balance, which would fail if USDC acts as the native gas token [redacted] a reserved amount. The live replay was inconclusive: The replay ran out of tool calls before it reached the reported state. The page reported 1 console error during the scenario.
Expected: The populated pay amount should be slightly less than the total USDC balance (e.g., deducting a gas reserve) since USDC is the native gas token on Arc testnet.
Actual: The pay amount input is populated with 2.9926, which is exactly 100% of the total USDC wallet balance, leaving zero reserve for transaction gas fees.
Steps to reproduce:
- Navigate to https://www.swaparc.app/
- Click 'Explore the testnet app anyway' and open the 'Swap' page
- Connect wallet (or observe connected wallet balance of 2.9926 USDC)
- Ensure 'Sell' token is set to USDC
- Click the 'Max' shortcut button
Evidence: screenshots/S3-8.png, screenshots/S3-12.png
F3 · Supply Liquidity button fails to initiate deposit or trigger wallet prompt when wallet is disconnected
Severity: high · Type: functional · Verdict: confirmed · Scenario: S8
The evidence clearly states that clicking 'Supply Liquidity' results in no wallet prompt or validation error, leaving the modal completely stagnant. The live replay was inconclusive: The replay ran out of tool calls before it reached the reported state.
Expected: The application should trigger a wallet connection request or initiate a deposit transaction, or disable the button with a prompt to connect wallet.
Actual: Clicking 'Supply Liquidity' produces no reaction, error message, or wallet prompt; the modal remains static.
Steps to reproduce:
- Navigate to https://www.swaparc.app/
- Dismiss the testnet completion modal by clicking 'Explore the testnet app anyway'
- Click the 'Pools' navigation button
- Click the 'ALL POOLS' tab selector
- Click 'Deposit' on any displayed liquidity pool
- Enter valid deposit amounts in the token input fields
- Click 'Supply Liquidity'
Evidence: screenshots/S8-8.png
F4 · CORS policy blocks transaction history API request
Severity: high · Type: functional · Verdict: promoted · Scenario: S10
Surfaced by the audit of S10, which the Tester passed, and reproduced live: I navigated to the Swap view and clicked on the 'Swap history' button. The drawer opened and displayed a 'No transactions found.' state, confirming the empty state caused by the silent fetch failure described in the bug report. The page reported 3 console errors during the scenario.
Expected: The application should successfully fetch and display the transaction history from the Arcscan API.
Actual: The API request is blocked by a CORS policy error, causing a silent fetch failure and an incorrect 'No transactions found.' empty state to render.
Steps to reproduce:
- Navigate to the Swap view
- Open the Swap History drawer
- Observe the network requests and console errors
Evidence: screenshots/critic-M2-1.png
Medium severity
F2 · Mini Wallet Send MAX shortcut fills exact maximum balance without reserving gas
Severity: medium · Type: functional · Verdict: confirmed · Scenario: S5
The Tester explicitly noted that the Mini Wallet's 'Max' functionality fills the exact maximum balance of 2.992649 USDC without deducting any gas reserve.
Expected: The transfer amount populates with a value slightly below the maximum balance to account for Arc testnet gas.
Actual: The transfer amount populates with the exact maximum balance (2.992649 USDC).
Steps to reproduce:
- Go to https://www.swaparc.app/
- Click 'Explore the testnet app anyway' or navigate to Profile
- Connect wallet if not already connected
- In the Mini Wallet section on Profile, click 'Send' next to USDC
- Enter a recipient address in the Recipient field
- Click the 'Max' button next to the Amount input
Evidence: screenshots/S5-9.png
Scenario results
| Scenario | Priority | Result | Issues |
|---|
| S1 Connect wallet and dismiss testnet notice | high | pass | none |
| S2 Execute standard token swap | high | blocked (On-chain token [redacted] execution requires an active Web3 wallet connection and accessible testnet RPC, which is unavailable in the headless test environment.) | none |
| S3 Swap MAX amount with USDC gas reservation | high | fail | F1 |
| S4 Create PrivPay payroll batch | high | blocked (Submitting and funding the PrivPay payroll batch requires an external Web3 wallet connection and cryptographic signature to authorize pool funding and employee addition.) | none |
| S5 Send MAX amount from Mini Wallet | high | fail | F2 |
| S6 Validate custom slippage boundaries | medium | pass | none |
| S7 Validate PrivPay Payroll recipient address | medium | blocked (Reached tool-call budget before completing the final submission action for validating the recipient wallet address.) | none |
| S8 Deposit liquidity into pool | medium | fail | F3 |
| S9 Process PrivPay claim | medium | pass | none |
| S10 Handle API CORS errors gracefully in Swap History | medium | pass | F4 |
| S11 Validate transaction deadline constraint | low | blocked (The application does not have a 'Transaction deadline (minutes)' field in the Slippage settings panel or Swap interface.) | none |
| S12 Load hosted documentation | low | pass | none |
The audit
The Critic reviewed 3 findings and re-verified 4 of them live in the browser, replaying the reported steps on a fresh page.
- The Tester passed scenarios S1 and S10 despite clear console errors, mistakenly treating the application's ability to survive a failing network request as a passing test of the feature itself.
- A possible defect in S1 ("Server responds with 502 Bad Gateway during initial load") was not promoted: the live replay came back not-reproduced.
What to fix first
- Reserve sufficient gas fees when users click the maximum balance shortcut on swap inputs (F1).
- Prompt users to connect their wallet or display an informative error when attempting to supply liquidity while disconnected (F3).
- Configure appropriate CORS headers on the transaction history API to prevent request blocking and restore historical activity views (F4).
- Implement gas fee deduction logic when populating the maximum transfer amount in the Mini Wallet (F2).
Coverage and caveats
In scope: Initial modal dismissal and wallet connection; Swap execution and gas reservation on MAX shortcuts; PrivPay Payroll creation and validation; PrivPay Claim execution; Mini Wallet transfers and gas reservation; Slippage settings validation; Liquidity pool deposits; Graceful degradation on known CORS API errors.
Not covered: Network switching to non-Arc chains (intake specifies wallet automatically refuses this); Real zero-knowledge proof cryptographic verification (only frontend triggers are observable); Ecosystem dropdown navigation (insufficient AppMap detail for target routes).
- Wallet injection intercepts connection requests and connects automatically when 'Connect via Wallet' is selected
- MAX shortcuts exist on the Swap and Mini Wallet forms to populate balances
- Testnet balance holds sufficient USDC to perform core transactions
- Third-party Arcscan API CORS errors will persist, allowing testing of UI error handling
- S2 could not be executed: On-chain token [redacted] execution requires an active Web3 wallet connection and accessible testnet RPC, which is unavailable in the headless test environment..
- S4 could not be executed: Submitting and funding the PrivPay payroll batch requires an external Web3 wallet connection and cryptographic signature to authorize pool funding and employee addition..
- S7 could not be executed: Reached tool-call budget before completing the final submission action for validating the recipient wallet address..
- S11 could not be executed: The application does not have a 'Transaction deadline (minutes)' field in the Slippage settings panel or Swap interface..
By the numbers
| Metric | Value |
|---|
| Scenarios | 5 passed, 3 failed, 4 blocked of 12 (46 planned steps) |
| Browser actions | 260 (94 clicks, 19 inputs, 21 navigations, 126 snapshots) |
| Screenshots | 48 (4 explore, 41 scenario, 3 critic), 41 captioned |
| Coverage | 2 pages, 6 forms, 6 flows, 6 console errors |
| Audit | 3 findings, 4 re-verified live, 3 confirmed, 1 promoted, 0 withdrawn |
| Model calls | 226 |
| Tokens | 1,046,547 input, 11,400 output, 20,420 thinking |
| Time | 14 min |
| Wallet | 0 transactions, 3 signatures, 0 refusals on chain 5042002 |
| Stage | Calls | Input | Output | Thinking | Seconds |
|---|
| explore | 26 | 127,592 | 2,076 | 1,618 | 70 |
| plan | 1 | 4,539 | 2,158 | 3,587 | 47 |
| test | 169 | 818,298 | 5,561 | 8,936 | 502 |
| critique | 29 | 94,241 | 1,272 | 5,491 | 221 |
| report | 1 | 1,877 | 333 | 788 | 9 |