Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Orchestrates a full smart-contract-team offboarding end-to-end — swaps the departing person out of the multisig and rotates every shared SC-owned wallet they held (deployer, dev, pauser) to freshly generated replacements. v1 is EXECUTE-ONLY: it assumes the Linear ticket tree already exists (modeled on EXSC-558) and runs the rotations; it does NOT create the tickets (that is a fast-follow). Use when the user says "offboard <SC dev>", "run the SC-dev offboarding", or "replace <person> as multisig
.claude/skills/lifinance-offboard-sc-dev/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 195% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 104% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 33% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 108% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 230% | 0% |
Drives the smart-contract half of offboarding a departing SC team member: remove them as a Safe multisig signer, add their replacement, and rotate every shared wallet they had custody of to a freshly generated one. This is the orchestrator — it calls the per-role rotate- skills and multisig-rollout; it does not reimplement any rotation.
v1 scope — EXECUTE-ONLY. This skill assumes the offboarding Linear ticket tree already exists (created by hand, modeled on EXSC-558) and its job is to execute that plan. It does not generate the ticket tree. Auto-creating the tickets is a deliberate fast-follow — call it out at the start so the user knows to have the tree ready, and don't silently skip a step because a ticket is missing.
Why an orchestrator and not one big script: each role has a different rotation mechanism (Safe owner swap, staging owner transfer, immutable-facet redeploy), and each is independently useful and independently tested. This skill sequences them by dependency and holds the custody guard across all of them.
| Situation | Skill | |---|---| | Full SC-dev offboarding (signer swap + all shared wallets) | this skill | | Just the deployer wallet | rotate-deployer-wallet | | Just the staging owner (Dev wallet) | rotate-dev-wallet | | Just the emergency pauser | rotate-pauser-wallet | | A single production rollout / signer swap on its own | multisig-rollout |
NOT for non-SC offboarding (HR/IT deprovisioning is out of scope) and NOT for rotating a CTO-owned wallet (refund / feeCollector / withdraw — see custody guard).
--person <name> — the departing SC dev, resolved from the offboarding Linear tree (EXSC-558-style).--removed-signer 0x — the departing person's personal multisig signer seat to remove (human-supplied / ticket-sourced).--new-signer 0x — the replacement personal multisig signer to add (human-supplied / ticket-sourced).--linear EXSC-XXX — the parent offboarding ticket (the pre-existing tree this run executes). If absent, ask for it — do not invent a tree.config/global.json (it can be mid-rotation-inconsistent).multisig-rollout → script/deploy/safe/confirm-safe-tx.ts; this skill and the ones it calls hand off and WAIT — none run the signer.multisig-rollout — no direct cuts, no SEND_PROPOSALS_DIRECTLY_TO_DIAMOND=true.config/global.json.0 success; 1 real error (report, stop, no retry); 2 recoverable misconfig (name the missing env/credential). A failing network in one rotation must not silently abort the others — surface it and let the operator decide.bunx tsx) or Bash only, never Python. Foundry/bun may need export PATH="$HOME/.foundry/bin:$HOME/.bun/bin:$PATH".Ordered by dependency. The new keys must exist and be funded before anything on-chain can move, so key generation is the blocking first human step; the signer swap and deployer rotation come next because they change who can sign; dev and pauser follow; secret rotation and the completeness gate close it out.
Run from the repo root. Confirm and report (don't fix silently):
--linear, EXSC-558-style) exists and is the plan being executed. State the EXECUTE-ONLY scope note: ticket-tree creation is a fast-follow, not done here..env present, PRODUCTION correct, SEND_PROPOSALS_DIRECTLY_TO_DIAMOND not true; Foundry, gh auth status, VPN (MongoDB), Slack MCP all available (Slack + VPN needed by multisig-rollout).Nothing on-chain can proceed until the replacement keys exist. The human securely generates the new deployer, dev, and pauser keys and their replacement personal signer, and provides the addresses (never the keys, never via global.json). Fund the new deployer/dev/pauser enough to broadcast where each rotation needs gas — the individual rotate- skills sweep the bulk from the old wallets, but the new deployer needs bootstrap gas before it can broadcast. Wait for the addresses before continuing.
> HyperEVM big blocks. The new deployer and dev EOAs each need big blocks enabled on hyperevm before they can deploy there — an L1, per-address setting that does not carry over on rotation. rotate-deployer-wallet and rotate-dev-wallet each flag this in their funding phase; follow the runbook: docs/HyperEVMBigBlocks.md. (The pauser does not deploy, so it is exempt.)
Change the Safe ownership set on every production chain: remove the departing person's personal signer, add the replacement. This is a Safe owner change, so it runs through the production rollout lifecycle:
text/multisig-rollout
driven for the owner-swap (add replacement + remove departing signer) across all chains — proposals → PR → human Ledger signing (hand off, wait) → verify signatureCount >= 2 → post #dev-sc-multisig-proposals. Do not run confirm-safe-tx.ts yourself. Wait for the user to confirm signing before treating the swap as landed.
Heaviest governance role (safeOwners[0] + Timelock CANCELLER_ROLE + prod timelock executor), so it goes before the lighter roles:
text/rotate-deployer-wallet --new-address <NEW_DEPLOYER>
It sweeps old→new first (bootstrap gas), swaps the Safe owner + moves CANCELLER_ROLE via multisig-rollout (human signs), handles Tron ownership + delegation, updates config, and decommissions the old key. Let it own its own signing hand-offs; wait for it to report complete.
Staging diamond owner — lowest-stakes, the reference rotation:
text/rotate-dev-wallet --new-address <NEW_DEV>
It funds the new dev by sweeping the old, transfers staging diamond ownership old→new, moves the Tron delegation, updates config, and self-verifies.
Immutable pauser → redeploy EmergencyPauseFacet with the new pauser and cut it into every diamond:
text/rotate-pauser-wallet --new-address <NEW_PAUSER>
It repoints (via deploy-contract / multisig-rollout, incl. Tron), sweeps the old pauser, runs the CI funding check, rotates the CI pauser secret + re-verifies verifyEmergencyPauseReadiness.yml (coordinated, partly outside this repo), and updates config.
Beyond the on-chain wallets, the departing person had access to shared secrets that must be rotated so their leaving revokes access. Work the checklist modeled on EXSC-567 (RPC keys, API tokens, CI secrets, any shared credential store). These live largely outside contracts — coordinate with the secret owners and record what was rotated. Do NOT mark a secret rotated that this session cannot actually reach; surface it as a human/operational follow-up.
The single source of truth that the offboarding actually took effect everywhere, per rotated role:
text/check-rotation-status --old-address <OLD_ADDR> --new-address <NEW_ADDR> --role <deployer|dev|pauser> --removed-signer <DEPARTING_SIGNER> --production
Run it once per rotated role. Each invocation verifies only the checks that apply to that role: deployer — Safe-owner membership (departing removed / replacement added; old deployer removed / new added), Timelock CANCELLER_ROLE (old removed / new granted), whitelist role, and wallet funding; dev — staging-diamond owner() and wallet funding; pauser — wallet funding and CI pauser config. Read-only. The offboarding is not complete until every role passes on every network. Any red row → go back to the owning rotate- skill for that role and network.
Offboarding is complete only when ALL hold:
check-rotation-status green; proposals signed and executed via the timelock pipeline).safeOwners[0] is the new deployer, CANCELLER_ROLE moved, Tron ownership + delegation moved, old deployer key decommissioned.owner() is the new dev on every chain (incl. Tron staging), delegation moved.EmergencyPauseFacet to the facet carrying the new pauser; CI secret rotated + pause-flow re-verified (or logged as coordination follow-up).update-wallet-config PRs are open (EVM + tronWallets.*); Notion registry follow-ups noted.| Step | Calls | |---|---| | Multisig signer swap (remove departing, add replacement) | /multisig-rollout | | Rotate deployer (safeOwners[0] + CANCELLER) | /rotate-deployer-wallet | | Rotate dev (staging owner) | /rotate-dev-wallet | | Rotate pauser (immutable → redeploy EmergencyPauseFacet) | /rotate-pauser-wallet | | Completeness gate (signer swap + all roles, all networks) | /check-rotation-status --old-address <OLD> --new-address <NEW> --role <role> --removed-signer <DEPARTING_SIGNER> --production | | Config PRs per role (called inside each rotate- skill) | `/update-wallet-config` | | Fund sweeps per role (called inside each rotate- skill) | /sweep-wallet-funds |
Shared-secret rotation (EXSC-567) and Linear ticket-tree creation live outside this skill — coordinated / fast-follow, not owned here.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 11,564 | 18,594 | +61% | 1 | 1 | 0% | 2,440 | 7,194 | +195% | 0 | 0 | — |
case-02 | fail→pass | 16,911 | 18,995 | +12% | 1 | 1 | 0% | 3,417 | 6,983 | +104% | 0 | 0 | — |
case-03 | fail→pass | 17,790 | 10,892 | -39% | 1 | 1 | 0% | 3,915 | 5,204 | +33% | 0 | 0 | — |
case-04 | fail→pass | 10,914 | 4,073 | -63% | 1 | 1 | 0% | 1,644 | 3,418 | +108% | 0 | 0 | — |
case-05 | fail→pass | 7,885 | 4,437 | -44% | 1 | 1 | 0% | 1,077 | 3,551 | +230% | 0 | 0 | — |
case-06 | fail→pass | 11,250 | 8,515 | -24% | 1 | 1 | 0% | 1,665 | 4,483 | +169% | 0 | 0 | — |
case-07 | fail→pass | 11,423 | 6,883 | -40% | 1 | 1 | 0% | 1,666 | 3,954 | +137% | 0 | 0 | — |
case-08 | pass→pass | 11,681 | 3,506 | -70% | 1 | 1 | 0% | 1,741 | 3,346 | +92% | 0 | 0 | — |
case-09 | fail→pass | 6,985 | 2,562 | -63% | 1 | 1 | 0% | 970 | 3,174 | +227% | 0 | 0 | — |
case-10 | fail→pass | 11,660 | 5,392 | -54% | 1 | 1 | 0% | 1,933 | 3,959 | +105% | 0 | 0 | — |
case-11 | fail→pass | 12,911 | 5,432 | -58% | 1 | 1 | 0% | 1,986 | 3,689 | +86% | 0 | 0 | — |
case-12 | fail→pass | 13,581 | 15,732 | +16% | 1 | 1 | 0% | 2,066 | 3,738 | +81% | 0 | 0 | — |
case-13 | fail→pass | 13,865 | 8,399 | -39% | 1 | 1 | 0% | 1,916 | 4,142 | +116% | 0 | 0 | — |
case-14 | pass→pass | 9,136 | 1,779 | -81% | 1 | 1 | 0% | 1,467 | 3,112 | +112% | 0 | 0 | — |
case-15 | pass→pass | 11,997 | 4,959 | -59% | 1 | 1 | 0% | 1,700 | 3,596 | +112% | 0 | 0 | — |
case-16 | pass→pass | 15,794 | 3,119 | -80% | 1 | 1 | 0% | 2,185 | 3,230 | +48% | 0 | 0 | — |
case-17 | fail→pass | 20,384 | 4,422 | -78% | 1 | 1 | 0% | 908 | 3,818 | +320% | 0 | 0 | — |
case-18 | pass→pass | 6,884 | 2,883 | -58% | 1 | 1 | 0% | 1,002 | 3,336 | +233% | 0 | 0 | — |
case-19 | fail→pass | 9,499 | 1,958 | -79% | 1 | 1 | 0% | 1,594 | 3,080 | +93% | 0 | 0 | — |
case-20 | fail→pass | 11,544 | 2,756 | -76% | 1 | 1 | 0% | 1,727 | 3,212 | +86% | 0 | 0 | — |
case-21 | fail→pass | 7,343 | 2,056 | -72% | 1 | 1 | 0% | 1,095 | 3,132 | +186% | 0 | 0 | — |
case-22 | pass→pass | 13,124 | 8,460 | -36% | 1 | 1 | 0% | 1,860 | 4,010 | +116% | 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 21 counted toward the lift figure. The other 1 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 +73 percentage points is the difference between those two pass rates over the 21 comparable cases.
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.