Built for Agents Onchain — KeeperHub × DoraHacks
Lands the revoke before the drainer moves.
$revoker watch
TypeScript · Solidity 0.8.28 + Foundry · viem · KeeperHub · Ethereum Sepolia
The most common wallet-drain vector
approve(spender, MAX_UINT256)
You signed it once, months ago. It never expires — and the day that contract turns malicious, the allowance is still live.
The problem
Approval checkers are read-only: they rate the risk, list the allowance — and leave the acting to you. For a wallet holder with forgotten approvals, or a DAO treasury signer asleep at 3 a.m., an alert is not protection.
A spender you approved has been flagged. Your allowance is unlimited.
allowance = MAX_UINT256 · granted 214 days ago
AcknowledgeThe state of the art ends here — a notification, and a button that does nothing on-chain.
The solution
An autonomous agent that watches a wallet’s live approval set and executes
approve(spender, 0) through KeeperHub the instant a threat rule fires —
no human in the loop.
Proof of execution · Ethereum Sepolia
approve(spender, MAX_UINT256) to the drainer contract.
approve(spender, 0) via KeeperHub check-and-execute.
The drain tx succeeded — it just found nothing left to take.
We let the drain contract fire after the revoke. It succeeded — and
took 0
balance unchanged: 10,000 mUSDC
across the whole sequence
How it works
The sharpest technical idea
transferFrom in here —
before the revoke lands.
Integration depth
Remove KeeperHub and Revoker needs seven separate systems — relayer,
gas oracle, MEV-protected route, confirmation poller, action discovery, ABI resolution,
audit pipeline — plus custody. The atomic check-and-execute
and the enclave-held key are the two pieces a standalone script cannot honestly replicate.
No key to steal. Signing happens inside a Turnkey enclave via KeeperHub — the agent process never holds a private key.
POST /execute/check-and-executethe atomic revokePOST /execute/contract-callcontract writesPOST /execute/transfernative transfersGET /execute/{id}/statusconfirmation · gas · audit recordGET /chainsnetwork + explorer resolutionGET /chains/{id}/abisource-verification signal, rule 1GET /user/walletsigner identity assertionGET /user/wallet/balancestoken discoverysimulate: truepre-flight dry runsIdempotency-Keysafe retries, no double-executionReliability · 25 full cycles against live Sepolia
Every bar is a real transaction. Cycles 10–13 hit a slow block-inclusion window (amber) — the network’s variance, reported as a distribution, not hidden behind an average.
Scope · stated plainly
A security tool that hides its blind spots is part of the problem. These are Revoker’s.
The mainnet path is documented, not executed. No real funds were risked producing any number in this deck.
No public RPC serves an address-less eth_getLogs over a useful range.
Revoker protects the tokens it is told to watch — not coverage it doesn’t have.
young-spender abstains loudlyWithout an archive RPC it returns INDETERMINATE and names the remedy —
instead of silently reporting “safe”.
A spender that is verified, aged, and off the deny-list trips nothing. That case is out of scope, not silently mishandled.
The ask
Judge Revoker on execution — that is the point. Every number in this
deck is a Sepolia transaction; the allowance we zeroed is still zero, and one
cast call proves it.
Expected output: 0
The drainer fired.
It found an empty room.