Standalone, ISC-licensed source for the local companion used by ittybits rescue. It includes the CLI, tests, pinned dependencies, and public ittybit ID registry. It contains no website backend, API credentials, real rescue cases, or private website history.
Developers and coding assistants: start with DEVELOPMENT.md for the public plan format, module map, and integration boundaries, and AGENTS.md for working rules. This is a CLI, not a hosted signing API.
Experimental software; not independently audited. This is for a wallet you own or are expressly authorized to rescue after its private key was compromised. It supports 1–50 canonical native Ethscription ittybits on Ethereum mainnet. It does not recover ERC-721 tokens, escrowed assets, seed phrases, or smart-contract wallets. Do not fund the compromised source wallet directly.
The website handles public addresses and a public plan only. This separate local program signs on your computer. It accepts the already-compromised source's private key through a hidden terminal prompt, encrypts it locally, and never accepts a seed phrase. It does not send private keys or passwords to the website, RPCs, indexer, or builders. Use a clean computer you trust; encryption cannot protect keys while in use from malware on that computer.
- Create a clean destination wallet with a different seed in your normal wallet application. Keep its private key/seed out of this tool. Verify its full address in that wallet. This version requires an ordinary EOA with no delegation or contract code. The source, destination, and gas sponsor must be three different addresses.
- Download
rescue-plan.jsonfrom https://ittybits.xyz/rescue. Review the source, destination and every selected ittybit. The plan contains no secrets. - Download
rescue-kit.zipand its SHA-256 checksum from the same release. Verify the checksum before extraction. This detects corrupt or mixed downloads; it does not protect against a compromised release server. Source is available at https://github.com/Posvar/itty-rescue for review. The ZIP also includes the full source, tests, dependency lockfile, and file-hash manifest. - Extract the kit into a private, non-synced folder outside a Git repository.
Install Node.js 22 or newer from https://nodejs.org/ . Put
rescue-plan.jsonalongsiderescue.cjsand open a local terminal in that folder.
On Windows PowerShell, verify the ZIP with:
Get-FileHash .\rescue-kit.zip -Algorithm SHA256Compare the full hash with rescue-kit.sha256. Then install pinned dependencies
without dependency install scripts and run the fixture-only tests:
npm ci --ignore-scripts
npm test
node rescue.cjs check --plan rescue-plan.json
On Windows, use npm.cmd instead of npm if PowerShell blocks npm.ps1.
npm test uses public disposable fixture keys and mocked network responses;
it does not sign using your keystores or submit transactions.
Run these yourself in an interactive terminal. Do not paste keys, passwords, seed phrases, keystores, or signed transactions into chats or support tickets.
node rescue.cjs create-sponsor --plan rescue-plan.json
Choose a strong password (at least 12 characters). This creates a new encrypted
gas-only wallet and prints only its public address. Fund that sponsor, not
the compromised source, with up to 0.00015 ETH. The program caps the worst-case
sponsor spend at 0.0001 ETH. If the current quote exceeds the cap it stops;
more funding will not bypass it. Wait for lower gas or select fewer assets.
Keep the sponsor keystore and its password: unspent ETH remains in this wallet,
and this version does not include a sweep command. An Ethereum wallet/tool that
supports a standard V3 encrypted keystore can later manage the remaining balance
using the nested keystore object in the local envelope; never upload it to a
website or ask a stranger to decrypt it.
node rescue.cjs import-source --plan rescue-plan.json
Confirm the compromised source address. Enter its private key only at the hidden prompt. The key must match the plan. Choose a separate encryption password. No plaintext key file is read or written. Never enter the destination wallet's key or seed here.
node rescue.cjs check --plan rescue-plan.json
node rescue.cjs simulate --plan rescue-plan.json
Review the displayed addresses, all assets, current delegation, and maximum spend.
simulate asks for both keystore passwords and a typed SIMULATE confirmation.
It signs locally and sends the exact two signed transactions to Flashbots for
simulation only. A passing simulation is not a submission or an inclusion
guarantee. Signed transactions are never written to disk or printed.
node rescue.cjs send --plan rescue-plan.json
Review the fresh quote and type the complete requested confirmation:
RESCUE <count> TO <full destination address>. The program rechecks ownership,
code, nonces, indexer lag, and block consistency before every attempt. It signs
and simulates again before submitting the exact bundle privately. There is no
public transaction broadcast fallback. At most eight target attempts are made;
fees must remain within the fixed cap. Attempts use the same sponsor nonce, so
only one funding transaction can land; nonce changes stop the run.
node rescue.cjs verify --plan rescue-plan.json
After any interruption, rejection, timeout, or uncertain result, run verify before retrying, using the exact same plan and folder. A request can time out after reaching a builder. Never delete the attempt log to force a retry. Partial inclusion, changed nonces, conflicting receipts, unexpected gas, or account-code changes require manual review. Do not automatically switch to another plan or sponsor to bypass a stop.
Success requires both successful transactions, consecutive positions in the same block, three confirmations, cleared source code at rescue-block end, and indexed ownership of every selected ID at the destination. After verification, use your clean destination wallet to wrap or transfer normally. Retire the compromised wallet permanently; clearing delegation does not make its leaked key safe.
- The clean sponsor sends a type-4 transaction carrying the compromised source's chain-bound EIP-7702 zero-address authorization. This clears delegation before funding the source with just the reserved transfer gas. Clearing is also performed for ordinary EOAs, defending against an existing delegation and advancing the source nonce by one.
- The source sends a type-2, zero-value direct transfer to the destination with the selected canonical Ethscription IDs concatenated as ESIP-5 calldata. The transfer gas limit uses the EIP-7623 calldata floor.
These are two ordered transactions in a private builder bundle, not one consensus-atomic transaction. Private builders receive the signed bundle and are trusted to honor its inclusion rules and privacy. Reorgs, malicious builders, source-key-holder races, endpoint outages, and future protocol changes remain risks. The code fails closed when its supported gas/account assumptions differ. No tool can revoke an attacker's knowledge of a compromised key.
Local files live under .rescue-state/<plan hash>/. Both keystores are encrypted
standard V3 JSON, wrapped with the plan hash, public address, and role. Public
preflight, simulation, attempt and receipt files are bound to that same plan.
Changing the destination, assets, source or creation time gives a different plan
identity. This isolation avoids accidentally reusing a sponsor or submission log
for a different rescue; it is not protection against local malware editing code.
The Node process holds decrypted keys in memory while running; JavaScript does not guarantee memory wiping. Passwords are not accepted in arguments or env vars. File modes are restrictive on Unix; on Windows use a private user folder with appropriate account permissions. Back up the encrypted sponsor keystore and password securely until its remaining balance is handled.
- Public read RPCs:
ethereum-rpc.publicnode.com,eth.drpc.org. They see public queried addresses, calldata and IP address.RESCUE_RPC_URLmay replace the primary read endpoint with an HTTPS mainnet RPC; it never receives signatures. - Ownership indexer:
api.ethscriptions.com; it sees queried public IDs and IP. - Simulation and private submission:
relay.flashbots.net; it receives signed transactions and an ephemeral request-authentication signature. - Additional private submission:
rpc.beaverbuild.org,rpc.titanbuilder.xyz. Flashbots may forward to the named builders in the code. These parties can inspect and potentially act on the signed transactions. Privacy is not a consensus guarantee. - Dependency installation contacts npm's registry. Use the pinned lockfile and
npm ci --ignore-scripts; do not replace the kit's dependencies casually.
There is no telemetry, secret-upload endpoint, seed recovery, live-chain test, or automatic site connection in the local companion. The ID registry is pinned to the reviewed collection registry with a SHA-256 integrity check. If a registry update or unsupported wallet blocks rescue, seek a reviewed update; do not remove validation checks.
The source is ISC-licensed; you may inspect and run it without the website. The workflow nevertheless depends on available RPCs, the Ethscriptions indexer and private builders. If those services reject a rescue, the safe escape is to stop and get the public error/state reviewed, rather than publicly fund the source.
Protocol references: https://eips.ethereum.org/EIPS/eip-7702 and https://eips.ethereum.org/EIPS/eip-7623 .