How Cursor and ChatGPT helped me minimize the effect of getting hacked

27.01.2026. at 14:20:44

I was happily chugging along, testing my ENS/AR deployer tool, copying files over from previous experiments, when I accidentally committed my .env file which contained a private key, and pushed to a public repo.

Within a minute, I was getting drained. 0xppl notifications alerted me so I was able to dive right into the mess.

This private key belonged to my hot address, which I use willy nilly for not so important things - ENS deployments, playing with smart contracts, the occasional gamble.

The problem was - since I took over RMRK again, I hadn't taken the time to set up proper multisigs as everything was still in flux. I had been too focused on making the new renderer and locking tokens in permanent LP and completely forgot about this part. Inexcusable amateur mistake.

Luckily, the attacker liquidated immediately rather than exert long term sell pressure.

It could have been much worse - and would have been, if it hadn't been for LLMs and Cursor.

Tokens

The first crisis was: this wallet has access to all the multisigs, so all tokens on those were already presumed dead and buried. Indeed, a closer inspection revealed that the attacker skillfully extracted and liquidated everything - anything above a dollar was gone.

I had to somehow stop him from realizing he has minting access on the Axelar ITS contract of RMRK over on Moonbeam, but how if he's running a drainer. I can't do any ops without him immediately draining money.

So I enlisted ChatGPT's Codex in Cursor.

I initialized a new Foundry project. My prompt was:

I got my wallet hacked. The perp is still draining my wallet, but I have admin approval on a token:

[CONTRACT ABI]

It's RMRK on moonbeam at 0x524d524B4c9366be706D3A90dcf70076ca037aE3

I want to write a script which will in one fell swoop:

a) move some GLMR to this wallet
b) instantly issue an approve and revoke call on the token's minting ability, role 0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6. We would remove it from 0xB9b8EF61b7851276B0239757A039d54a23804CBb and give it to 0x4dA2e85D64bEcE663CCaB06E89B970b6b077f22F

This needs to be done at high gas price to prevent intercepting by the drainer.

I've initialized a forge project in the folder which you should use to anvil-clone moonbeam, from the RPC endpoint I added into .env (which you can source with set -a && source .env && source +a) and also the private key of the hacked address and of the new "admin role" address is in there under HACKED_KEY and NEW_KEY. The RPC key is under MOONBEAM_RPC_URL.

Test this run locally first (anvil), when we are sure it works, we will run it live.

Because this was my savage-configured "codex 5.2 extra high", it went on a whole exploration:

  1. It figured out that you can't replace minters unless you have admin role
  2. It went and looked at logs to find out who's admin, discovering admin has been revoked
  3. Checked if we can burnFrom instead (we can't)

I then asked if we can overmint to max supply and prevent him from minting more.

Screenshot 2026-01-27 at 20.59.43

I confirmed, and it then:

  1. Went to calculate exactly how much we can mint
  2. Gave me an approximate gas cast so I would know how much we'd need to top up the account with
  3. Wrote a script which in one go moves GLRM from NEW to HACKED, and immediately mints + revokes access, at a high enough gas fee that the attacker wouldn't be able to intercept.
Screenshot 2026-01-27 at 21.02.38

Legend.

This then prevented further abuse of the token, and we could focus on other things.

Operation: NFT salvage

The attacker took my Milady and about a dozen Lobs. Other NFTs had some value once upon a time but honestly, they amount to maybe in total (and that's if he manages to sell them) to something like $1000.

But the NFTs I really cared about - the Kanaria and the Skybreach Land Deeds - those worried me.

So, it was time to mount a rescue - time was of the essence, and the hacker had already started setting up 7702 delegations on my address to prevent me from seeding it with money and doing actions.

photo_5460988520039124377_w

EIP‑7702 is the “Smart EOA” upgrade that lets a normal, key‑controlled address behave like a smart account by writing a tiny delegation designator into the account’s code. That designator points at some contract, and from then on the chain executes that contract’s logic in the context of your address (same address, same balances, same approvals) - it’s meant for account‑abstraction UX like batching, sponsored gas, and permissioned sub-keys.

But if someone already has your private key, they can flip this into a weapon: delegate your EOA to a malicious “sweeper” contract. At that point your address stops being a dumb wallet and becomes attacker-chosen code. Any attempt to top it up (even a plain ETH transfer to seed gas) can be immediately forwarded away or outright reverted, and “racing” the attacker from that address becomes a dead end because the delegated logic can drain/re-route value as soon as it touches the account. Once I saw the 7702 delegation land, the only viable move was to treat the wallet as fully toxic and run the rescue from clean keys.

The first problem with the NFT rescue was that NFT collection contracts generally don't have any way to list "all NFTs owned by address", so getting a list of the tokens I want wasn't easy on-chain.

This is where Alchemy's getnfts function was priceless.

I didn't have time to fiddle with the docs, so I just grabbed the API key, gave it to Cursor's Codex5.2xh and let it rip. It immediately produced a list of Kanaria I own.

Screenshot 2026-01-27 at 21.06.55 Screenshot 2026-01-27 at 21.04.45

I confirmed, and it went deeper, analyzing gas costs and how much rescuing we can fit into a call.

Screenshot 2026-01-27 at 21.07.46

After a few more rounds of tweaks on gas price, we fired off the script. It issues 470 transactions, pre-paid, with high gas fee, and all we had to do was wait for it finish. This took a sweet while, some throttling and synchronous ops got in the way. But codex learned from its mistake.

Screenshot 2026-01-27 at 21.10.16

I had it rescue Skybreach Land Deeds, and then Chunkies, and then RMRK Banners. I also had it rescure Caimeo Soul Shards on Polygon.


It was an expensive lesson, yes, but not as expensive as it could have been. And without the LLMs to lend a hand in really fast TX composition and execution, my defenses would have been significantly slower.

So what's next?

Read the RMRK post mortem, I guess.

As for me? I secured my wallets and implemented some changes:

  1. I now have a global pre-commit hook on my machine checking for .env and other sensitive files.
  2. I now no longer use private keys in .env files at all, just in case. Looks like this is changing on the tool level too.
  3. I am building a rescue-op "skill" for Cursor so that anyone who ends up in a similar position in the future can just run it quickly and get assets saved. Follow on X and 🔔 on to be notified (the only way to see my posts, I am shadowbanned).