# CoinPayPortal Multisig Escrow QA Report Scope tested: public `/escrow/create` page, static HTML, and client bundle for the 2-of-3 multisig escrow flow. Date: 2026-06-09 ## Summary The multisig option is present and wired in the client. Selecting "2-of-3 Multisig" changes the flow from custodial token escrow to signer public keys, switches the default chain from `USDC_POL` to `ETH`, limits chain choices to native signer chains, requires an arbiter signer, and disables recurring series. The client submits multisig creation to `/api/escrow/multisig` and the post-create success state references the expected follow-up API flow: `/api/escrow/multisig/:id/prepare` -> `/sign` -> `/broadcast`. I did not fund or broadcast an escrow because this was an unauthenticated/public QA pass with no test wallet funds. The report focuses on form behavior, client validation, route wiring, and visible UX risks. ## What Looks Correct - The page loads at `https://coinpayportal.com/escrow/create`. - The form exposes two escrow models: - `custodial` - `multisig_2of3` - When multisig is selected, recurring series is disabled, which is correct because the code path only supports recurring custodial escrow. - The arbiter becomes required for multisig before client submission. - Labels adapt by chain type: - EVM-like chains show signer address language. - Non-EVM chains show public key language. - The "Use CoinPay as arbiter" checkbox calls `/api/escrow/platform-arbiter?chain=`, which is the expected helper route for pre-filling a platform arbiter key. - The client uses `/api/escrow/multisig` for multisig instead of the custodial `/api/escrow` route. ## Issues / Risks Found ### 1. Multisig requires authentication, but that is only discovered after form work The public page allows a non-logged-in user to select multisig, enter amount, signer keys, arbiter, expiry, and description. The client only reveals that multisig creation requires authentication after submit. Recommended fix: When multisig is selected and no `auth_token` is present, show a persistent inline notice near the model selector: > Multisig escrow creation requires login. You can preview the form, but must log in before creating. Also consider changing the submit button text to "Log in to create multisig escrow" in that state. ### 2. Address/public-key expectations could be more explicit The labels change between "Signer Address" and "Public Key", but users may not know whether BTC/LTC/DOGE/SOL need compressed pubkeys, wallet addresses, or raw keys. Recommended fix: Add one short example placeholder per chain family: - EVM: `0x...` - BTC/LTC/DOGE: compressed public key such as `02...` or `03...` - SOL: base58 public key ### 3. Amount helper initially states "0 USDC_POL" Before the user enters an amount, the helper says the depositor sends exactly `0 USDC_POL`. This is technically a default state, but it reads like an instruction. Recommended fix: Before amount input, show "Enter an amount to calculate the exact deposit." After input, show the exact amount. ### 4. Platform arbiter lookup should surface failures near the checkbox The client sets a generic error if `/api/escrow/platform-arbiter` fails. Since the checkbox is contextual, a field-level message under the arbiter input would be easier to diagnose. Recommended fix: Keep the error beside the arbiter field and include the chain in the message, e.g. "No platform arbiter key available for SOL." ## Suggested Acceptance Tests 1. Anonymous custodial escrow preview: - Open `/escrow/create`. - Enter valid custodial addresses and amount. - Confirm unauthenticated custodial fallback works or displays a clear auth requirement. 2. Anonymous multisig auth guard: - Select `2-of-3 Multisig`. - Fill amount, depositor signer, beneficiary signer, and arbiter signer. - Submit while logged out. - Expected: clear inline auth requirement before any network-side failure. 3. Authenticated multisig creation: - Log in. - Select `2-of-3 Multisig`. - Create ETH or SOL multisig escrow with valid signer inputs. - Expected: response includes escrow id, deposit address, status, signer fields, and next-step API guidance. 4. Platform arbiter: - Select every supported multisig chain. - Toggle "Use CoinPay as arbiter". - Expected: a valid arbiter signer/address is fetched or a field-level unsupported-chain message appears. 5. Recurring guard: - Select custodial, enable recurring. - Switch to multisig. - Expected: recurring state is disabled and not included in the multisig POST body. ## Overall The multisig path appears implemented and correctly separated from custodial escrow at the client level. The main QA concern is not the wiring; it is discoverability and validation clarity for users who start the multisig form while logged out or who do not know which signer key format each chain expects.