# Multisig AllSet withdrawals with the CLI

Withdraw from a Fast multisig to EVM with CLI 1.7.0, two signing rounds, and a local recovery journal.

[`@fastxyz/cli` 1.7.0](https://www.npmjs.com/package/@fastxyz/cli/v/1.7.0) supports Fast → EVM withdrawals from a Fast multisig. Each signer keeps their own key. The coordinator uses one recovery journal through two signing rounds: a token transfer to the bridge, then its linked AllSet intent.

This guide covers the new multisig withdrawal flow, not EVM → Fast deposits or Safe/CCTP transactions. Single-signer withdrawals retain their existing behavior. **Rehearse the actual CLI flow in testnet before using treasury funds.** A rehearsal with custom scripts is not validation of the CLI.

## Before starting

* Use macOS or Linux and Node.js 20 or newer. Windows is not supported for multisig withdrawal journals.
* Both operators must have the same Fast multisig imported, with their own local signer account. The examples assume a 2-of-3 multisig named `treasury`, with local signers `alice` and `bob`. Account names are local aliases; independently compare the multisig address, signer set, and quorum.
* Confirm the destination chain, recipient, USDC token mapping, bridge, endpoints, liquidity, and fees for the chosen network. The CLI checks route state before payment, but checks are snapshots, not reservations.
* Fund the Fast multisig for the withdrawal **and Fast gas for both signing rounds**. Serialize operations on this account across operators and devices.

Install the published version and check it:

```bash
npm install -g @fastxyz/cli@1.7.0
fast --version
```

## 1. Coordinator: propose the transfer

Create a private journal directory once:

```bash
mkdir -p "$HOME/.fast/withdrawals"
chmod 700 "$HOME/.fast/withdrawals"
```

The following is a **testnet template**, not a ready-to-run payment. Replace `0xRECIPIENT` with the intended EVM address and verify the supported route before executing. Amount `1` means one display unit, not one base unit.

```bash
fast send 0xRECIPIENT 1 --token testUSDC --to-chain ethereum-sepolia \
  --network testnet --account treasury --as alice \
  --withdrawal "$HOME/.fast/withdrawals/rehearsal.json"
```

Save the returned transfer hash. Keep this exact command and journal path for all subsequent coordinator calls.

## 2. Cosigner: inspect and approve the transfer

On the cosigner's own machine, inspect the pending transaction. Compare the network, sender, bridge, token and amount with the agreed withdrawal; approve only the exact transfer hash.

```bash
fast multisig pending --network testnet --account treasury --as bob
fast multisig vote --network testnet --account treasury --as bob --tx 0xTRANSFER_HASH
```

Replace the hash placeholder with the coordinator's transfer hash. Read the complete transaction shown before signing.

## 3. Coordinator: propose the linked intent

After transfer quorum, repeat the **exact same `send` command with the same journal** from step 1. This proposes the linked withdrawal intent, not another token transfer. Save the returned intent hash.

## 4. Cosigner: inspect and approve the intent

Inspect pending again. Verify the linked transfer hash, token, amount, destination chain, bridge, recipient and deadline against the first round and the agreed withdrawal. The decoded summary accompanies the raw claim; decoding is not authentication. The intent expires 24 hours after creation.

```bash
fast multisig pending --network testnet --account treasury --as bob
fast multisig vote --network testnet --account treasury --as bob --tx 0xINTENT_HASH
```

## 5. Coordinator: relay and verify settlement

After intent quorum, repeat the same `send` command and journal. The CLI cross-signs the certificates, simulates execution and submits to the relayer. Repeat that command later to observe settlement.

Relayer acceptance is **not completion**: it remains `awaiting-settlement`. The CLI reports `completed` only after a successful matching EVM `Withdraw` receipt and the token payment tied to that withdrawal's executor action. Settlement verification also needs the bridge's executor configuration at the receipt block; an RPC failure leaves the withdrawal pending.

For mainnet, prepare a separate, explicitly authorized withdrawal after testnet validation. Use `--network mainnet`, the verified destination chain, and **`--token USDC`**: the mainnet default `fastUSD` is not an EVM token. Recheck all route details; do not repurpose a testnet journal.

## Recovery rules

* **Never use a new journal to retry a payment.** A different file starts a new payment. Keep one coordinator and the original journal until settlement; its local lock does not coordinate multiple machines.
* The journal contains signed public envelopes, not seeds. Keep its directory at `0700` and file at `0600`; do not edit or delete stages. Do not exchange private keys between signers.
* Transactions are persisted before submission. Unknown responses are reconciled using exact envelopes, hashes and nonces; uncertain submissions or relay attempts are not automatically repeated. RPC, cross-sign and relayer endpoints can rotate, but the signed route stays fixed.
* Missing proposals, expired intents, revoked transfers, or rejected/uncertain relay attempts require manual recovery of the **original transfer**, not another payment. This command does not implement revoke.
* A crash may leave `FILE.lock`. Reconcile the original transaction hashes and account state before manually removing it.
* `--memo`, `--replace-pending` and `--eip-7702` are unsupported for this flow. A successful simulation does not guarantee settlement.

See the [CLI command reference](https://github.com/fastxyz/fast-sdk/blob/main/app/cli/README.md#multisig-allset-withdrawals-two-signing-rounds) and [AllSet SDK reference](/sdk-references/core-sdk-execution/allset-sdk.md). The source on `main` can advance beyond the installed release.
