Atomic, sweeper-proof wallet rescue using EIP-7702.
Kintsugi rescues assets from a compromised EVM wallet in a single atomic transaction. The victim signs an EIP-7702 authorization plus an EIP-712 batch authorization off-chain. A clean rescuer wallet submits one Type-4 (SetCode) transaction that delegates the victim's EOA to the audited Rescue contract and runs the entire batch in the same block. The victim never holds ETH, so a sweeper bot watching the victim's balance has no opening.
Status: pre-alpha. Mainnet and Sepolia. Solidity contracts, TypeScript core library, interactive CLI.
The classical Flashbots-bundle approach to rescuing compromised wallets needs the victim to receive a funding transaction first. Against an active sweeper bot that funding always wins. Worse, the Flashbots relay rejects bundles whose victim transactions need more balance than the victim's pre-bundle state, so inter-transaction funding bundles do not even simulate.
EIP-7702 (mainnet since Pectra, May 2025) lets the rescuer pay for everything in one Type-4 transaction. The victim's balance never rises above zero during the rescue; whatever a sweeper is watching for, it is not there. See docs/ARCHITECTURE.md for the full reasoning.
contracts/ Solidity (Rescue + NonceTracker + mocks)
test/ Hardhat 3 + viem unit tests (34 covering every code path)
scripts/ Deploy, deploy-test-assets, sweeper simulation
packages/core/ @ophelios/kintsugi-core, headless TypeScript library
packages/cli/ @ophelios/kintsugi-cli, interactive CLI
docs/ Architecture, security, usage notes
git clone https://github.com/ophelios-studio/kintsugi
cd kintsugi
npm install
# Run the contract test suite
npx hardhat test
# Build everything (core, ui, cli)
npm run build:all
# Make `kintsugi` a global command on this machine
cd packages/core && npm link
cd ../cli && npm link @ophelios/kintsugi-core && npm link
kintsugi --helpTo run an actual rescue:
kintsugi rescue # interactive terminal flow
kintsugi ui # polished web UI on localhostAn Alchemy API key is required for asset discovery (ERC-20, NFT, and ENS). The free tier works. Get one at dashboard.alchemy.com/signup.
# Quick read-only inventory of a wallet
kintsugi status <address> --alchemy-api-key <key>See docs/USAGE.md for the full walkthrough.
- ERC-20: any token with a standard
transferfunction. - ERC-721: any standard NFT.
- ERC-1155: standard multi-token.
- ENS: unwrapped
.eth2LDs (reclaim + transfer in the same batch), wrapped names (NameWrapper transfer), unwrapped subdomains (registry setOwner). Optional helpers forsetResolverandclearReverseRecord. - Custom calls: any contract function the victim must call before transferring an asset (unstake, withdraw, claim, exit, revoke).
npx hardhat test34 unit tests covering every code path in Rescue.sol and NonceTracker.sol, plus a structural sweeper-bypass test that asserts the victim's ETH balance is zero at every observable point in the rescue lifecycle, even though every asset transfer succeeds.
Mainnet (self-audited, no third-party audit, see AUDIT.md)
- Rescue contract:
0x25b2e6fb74fe4a186f1b3f25b289439fcc80aaca - NonceTracker:
0x3dda6ee79963b73cbdba9a4664c880633e7a5087
The integration test test/integration/sepolia-sweeper-bypass.test.ts runs a real sweeper bot against both rescue strategies on Sepolia and proves the difference end to end.
- Rescue contract:
0x53c1f40ca0a58942f9eb89d7fd445457a8521fd5(verified) - NonceTracker:
0x717883abfa58fa2bf0f9c2d5a132227253c47963(verified)
Demo result from the most recent run:
| Scenario | Outcome |
|---|---|
| Traditional rescue (rescuer funds victim, then signs from victim) | Sweeper bot drained the funding tx in tx 0x8a851fb5.... Assets stuck. |
| Kintsugi rescue (Type-4, sweeper still active) | Atomic rescue mined in tx 0xa39d79f3.... Sweeper got 0 ETH, 0 drains. Assets at safe. |
All four package.json files share the same version. Bump them together.
Only two packages are published to npm:
npm run build:all
cd packages/core && npm publish --access public && cd ../..
cd packages/cli && npm publish --access public && cd ../..@ophelios/kintsugi-ui is not published — its dist/ is copied into the CLI during build (cp -r ../ui/dist dist/web), so end users get the UI bundled inside @ophelios/kintsugi-cli.
This is the first open-source CLI for EIP-7702 wallet rescue. Closed-source services (Antidrain, DrainerLESS) charge a percentage of recovered assets and do not have a CLI. Existing OSS efforts have under 50 stars combined and do not handle ENS or asset discovery. See docs/ARCHITECTURE.md and docs/SECURITY.md for the design choices that follow from those gaps.
MIT.