Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Sweeps all native gas from a rotated-OUT SC wallet to the new wallet across every active EVM chain, via `script/tasks/moveNativeFundsToNewWallet.ts` — this is how every wallet rotation funds its replacement. Previews per-network balances first (read-only via `cast balance` — the script itself has no dry-run flag), derives the sender from the private key (never `config/global.json`), shows a human-confirmed pre-sweep report, and reports per-network moved/skipped/failed. Use when the user says "sw
.claude/skills/lifinance-sweep-wallet-funds/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 66% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 137% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 119% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 44% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 50% | 0% |
Multi-chain native-gas sweep from a rotated-out SC wallet to its new replacement, run as the funding step of a wallet rotation. Wraps script/tasks/moveNativeFundsToNewWallet.ts, which iterates every active EVM chain and moves the native balance (minus a gas reserve) from the wallet the private key controls into the new address. This skill is the funding primitive that rotate-dev-wallet, rotate-deployer-wallet, and rotate-pauser-wallet call — it does not itself change any on-chain role or config; it only moves gas so the new wallet can operate.
Use when:
rotate-* skill reaches its funding step (old wallet drained → new wallet bootstrapped).Do NOT use when:
request-dev-funds (PR to the automate-wallet) or a single manage-wallet-funds send.manage-wallet-funds in send mode (explicit-confirm-gated, one network/recipient).Required:
--new-address, EVM 0x…) — the rotation's replacement wallet; the sweep destination.Optional:
--old-key-env, default PRIVATE_KEY_PRODUCTION in prod / PRIVATE_KEY staging) — which .env key controls the rotated-out wallet. Maps to the script's --privateKeyEnvKey..env PRODUCTION=true double-opt-in rail. Selects the default --old-key-env (PRIVATE_KEY_PRODUCTION when set, PRIVATE_KEY otherwise).cast balance) and stop before any broadcast. moveNativeFundsToNewWallet.ts itself has no dry-run flag — never pass --check to it; citty silently ignores unknown flags and the script would broadcast a live sweep.The old (source) wallet is never taken as input — it is derived from the key (see Guardrails). If --new-address is missing or not a valid EVM address, ask once and stop.
cast wallet address, inside a subshell, never echoed — and never read from config/global.json (the key and config can diverge mid-rotation; a wrong source makes a funded wallet look empty). Confirm the derived source matches the role's current on-chain address before sweeping.manage-wallet-funds send: render the per-network report and require explicit human confirmation before any broadcast. An agent must never self-approve. --check needs no confirmation (it moves nothing).moveNativeFundsToNewWallet.ts sweeps native last within itself; the ordering rule here is about where this skill sits in a rotation.)multisig-rollout.0 success (all targeted networks swept or cleanly skipped); 1 real error (report stderr, stop, no retry, no fallback); 2 recoverable misconfig (missing --new-address, missing key env var — name the var to set). Lets an orchestrator process the rotation deterministically.Run from the worktree root. export PATH="$HOME/.foundry/bin:$HOME/.bun/bin:$PATH" if cast/bun are not found. Check and report (don't fix silently):
.env exists and the --old-key-env env var (default PRIVATE_KEY_PRODUCTION in prod / PRIVATE_KEY staging) is present. Missing → exit 2, name the var.cast --version), bun available.bash# --old-key-env wins; otherwise PRIVATE_KEY_PRODUCTION only with --production, PRIVATE_KEY for staging FROM_KEY_VAR="${OLD_KEY_ENV:-$([ "$PRODUCTION" = "true" ] && echo PRIVATE_KEY_PRODUCTION || echo PRIVATE_KEY)}" SOURCE=$(set +x; KEY=$(grep -E "^${FROM_KEY_VAR}=" .env | cut -d= -f2- | tr -d '"'); cast wallet address --private-key "$KEY")
Report the derived SOURCE. Cross-check it equals the role's current on-chain / config address (the wallet being rotated out) — if it instead matches --new-address, the key has already been rotated and there is nothing to sweep; stop and say so. Do not read the source from config/global.json.
moveNativeFundsToNewWallet.ts has no dry-run / preview flag (its only citty args are --newWalletAddress, --privateKey, --privateKeyEnvKey; unknown flags are silently ignored and the script broadcasts immediately). Never invoke it to "preview" — the preview is read-only cast balance per active EVM chain:
bash# same selection as the mover's getAllActiveNetworks(), minus Tron (cast is EVM-only) for NET in $(jq -r 'to_entries[] | select(.value.status == "active") | .key | select(startswith("tron") | not)' config/networks.json); do RPC=$(jq -r --arg n "$NET" '.[$n].rpcUrl' config/networks.json) BAL=$(cast balance "$SOURCE" --rpc-url "$RPC" 2>/dev/null) || BAL="RPC unreachable" echo "$NET: $BAL" done
Render a per-network table: chain, source balance, destination ($NEW). The mover's getAllActiveNetworks() does NOT exclude Tron — tron/tronshasta are in its target set and it will attempt (and fail on) them; list them in the table as explicit rows marked "not previewable with cast; expected to fail in the sweep; handled manually per Phase 5" so the preview covers exactly the set the script will touch. This preview reports raw balances only — the gas reserve kept and exact amount-to-move come from the mover's internal reserve logic and are not available without broadcasting; say so explicitly in the report. Flag chains with a dust/zero balance (the script will skip them) and any chain whose RPC is unreachable (surface, don't silently drop). Never broadcast to preview.
Present the pre-sweep report and require explicit confirmation (yes/proceed/confirm, case-insensitive; reject bare y). Skip only in --check mode. An agent/sub-agent must never answer this itself.
Runs long (one broadcast per chain, native moved last within the script). Run in the background and monitor:
bashbunx tsx script/tasks/moveNativeFundsToNewWallet.ts \ --newWalletAddress "$NEW" \ --privateKeyEnvKey "$FROM_KEY_VAR"
--privateKey 0x… is an alternative to --privateKeyEnvKey; omitting both drops the script into an interactive key prompt — prefer the env-key form so no key is ever on the command line. Pipe output through a filter that strips any line mentioning the key and redacts RPC URLs before display. Let per-network failures continue the run: capture the failed networks and their errors, keep the succeeded ones, and offer to retry the failures individually.
moveNativeFundsToNewWallet.ts can only sweep EVM chains — it does not filter Tron out of its active-network set, so expect tron/tronshasta to show up as failed rows in its output (don't retry them). Tron native (TRX) has no multi-chain sweep in this repo, so it is a single manual troncast send from the old Tron address to the new one. Derive both Tron base58 addresses from the EVM addresses (see update-wallet-config / troncast address to-base58), then hand the operator the single-transfer command to run — do not attempt to loop or automate it here. Note explicitly in the report that Tron native was handled (or is pending) manually.
check-rotation-status; this skill verifies only that the gas moved, not that roles were reassigned.script/tasks/moveNativeFundsToNewWallet.ts — the multi-chain EVM native mover this skill wraps (citty camelCase flags: --newWalletAddress, --privateKeyEnvKey/--privateKey; no dry-run flag).manage-wallet-funds — the single-chain / arbitrary-recipient sibling (send mode) with the same secrets-hygiene, derive-sender, and human-confirm rails. Use it, not this skill, for a one-off top-up.troncast address to-base58 / troncast send — Tron address derivation + the manual single-transfer for Tron native (Phase 5).update-wallet-config — records the new wallet in config/global.json after the rotation (separate PR step).check-rotation-status — read-only completeness gate for the overall rotation.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→fail | 19,562 | 19,701 | +1% | 1 | 1 | 0% | 3,664 | 3,318 | -9% | 0 | 0 | — |
case-01 | fail→fail | 15,258 | 6,869 | -55% | 1 | 1 | 0% | 3,026 | 3,217 | +6% | 0 | 0 | — |
case-02 | fail→fail | 11,746 | 9,261 | -21% | 1 | 1 | 0% | 2,309 | 3,212 | +39% | 0 | 0 | — |
case-04 | fail→pass | 12,043 | 4,941 | -59% | 1 | 1 | 0% | 2,076 | 3,439 | +66% | 0 | 0 | — |
case-05 | fail→pass | 8,301 | 4,628 | -44% | 1 | 1 | 0% | 1,484 | 3,510 | +137% | 0 | 0 | — |
case-06 | fail→pass | 8,815 | 2,501 | -72% | 1 | 1 | 0% | 1,420 | 3,111 | +119% | 0 | 0 | — |
case-07 | fail→pass | 11,388 | 3,089 | -73% | 1 | 1 | 0% | 2,218 | 3,185 | +44% | 0 | 0 | — |
case-08 | fail→pass | 14,273 | 4,342 | -70% | 1 | 1 | 0% | 2,262 | 3,403 | +50% | 0 | 0 | — |
case-09 | fail→pass | 12,376 | 3,656 | -70% | 1 | 1 | 0% | 2,196 | 3,369 | +53% | 0 | 0 | — |
case-10 | fail→pass | 6,607 | 2,433 | -63% | 1 | 1 | 0% | 1,116 | 3,069 | +175% | 0 | 0 | — |
case-11 | fail→pass | 6,267 | 2,731 | -56% | 1 | 1 | 0% | 956 | 3,090 | +223% | 0 | 0 | — |
case-12 | pass→pass | 13,399 | 2,890 | -78% | 1 | 1 | 0% | 1,977 | 3,094 | +56% | 0 | 0 | — |
case-13 | pass→pass | 8,118 | 2,414 | -70% | 1 | 1 | 0% | 1,275 | 3,038 | +138% | 0 | 0 | — |
case-14 | pass→pass | 8,814 | 6,148 | -30% | 1 | 1 | 0% | 1,307 | 3,077 | +135% | 0 | 0 | — |
case-15 | fail→pass | 18,454 | 7,391 | -60% | 1 | 1 | 0% | 3,219 | 4,062 | +26% | 0 | 0 | — |
case-16 | pass→pass | 8,875 | 4,600 | -48% | 1 | 1 | 0% | 1,367 | 3,438 | +151% | 0 | 0 | — |
case-17 | pass→pass | 11,869 | 3,006 | -75% | 1 | 1 | 0% | 1,719 | 3,088 | +80% | 0 | 0 | — |
case-18 | pass→pass | 15,844 | 6,281 | -60% | 1 | 1 | 0% | 2,432 | 3,634 | +49% | 0 | 0 | — |
case-19 | fail→pass | 11,581 | 4,391 | -62% | 1 | 1 | 0% | 1,708 | 3,405 | +99% | 0 | 0 | — |
case-20 | fail→pass | 5,290 | 3,754 | -29% | 1 | 1 | 0% | 660 | 3,179 | +382% | 0 | 0 | — |
case-21 | pass→pass | 6,347 | 1,511 | -76% | 1 | 1 | 0% | 1,064 | 2,869 | +170% | 0 | 0 | — |
case-22 | pass→pass | 13,938 | 7,132 | -49% | 1 | 1 | 0% | 1,932 | 3,631 | +88% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +50 percentage points is the difference between those two pass rates over the 20 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.