A few months ago, a friend of mine got hacked.
He had DOT staked, a bot draining his free balance as fast as funds arrived, and no clear path forward. I wrote this forum post explaining the mechanics of what was happening and a rough strategy to fight back. The community responded well, and shortly after, one more person in the same situation reached out.
Then a second case arrived. And this one was different.
When the attacker is actually good
The second case came through Mario Pino from Polkastats. He had spent months trying to help a user whose account had been compromised, and despite his best efforts, they hadn’t been able to get control of the situation. He reached out to us hoping we could find a way through.
I’ll be honest: my first reaction was that it would be straightforward. It wasn’t. It became clear very quickly that we were dealing with a skilled and well-resourced attacker; not someone running a generic script, but someone who genuinely knew what they were doing. They had bots with good latency, they understood the protocol, and they were patient. They also knew how to exploit forks to their advantage, and when they sensed they were losing ground, they flooded the network with transactions for hours on end in a deliberate attempt to crowd us out.
Mario stayed involved throughout, helping us coordinate, stress-test our approach, and validate edge cases we hadn’t anticipated. His persistence over those months, and his willingness to keep pushing when most would have given up, was a real part of why we succeeded.
What followed was weeks of technical work that went well beyond “move faster than the bot.” We had to build capabilities we simply didn’t have before:
- Calculating transaction priorities in real-time to guarantee inclusion order under adversarial conditions
- Handling fee calculations dynamically as network conditions shifted block by block
- Monitoring the transaction pool in real-time to understand what the attacker was doing and respond ahead of their next move
- Watching for incoming XCMs (both HRMP and DMP) and anticipating their outcomes before they settled on-chain
- Building a modified PolkadotSDK node tailored to our specific operational needs
- Many more things that we won’t mention for obvious reasons.
None of this could be developed and validated purely against mainnet. So we also built an extensive E2E test suite using zombienet that accurately reproduces the Polkadot AssetHub environment: same pallets, same configuration, producing one block every ~2 seconds. This let us iterate on recovery strategies against a faithful replica before touching real funds. As a side effect of pushing zombienet hard in this context, we were able to provide feedback that contributed to improvements in some of its newer features. A particular thank you to @javier for his responsiveness and help throughout that process.
And throughout all of this: staking mechanics, lock interactions, precise extrinsic sequencing across eras, edge cases in how pallets interact under concurrent state changes. We found things along the way that surprised us, including protocol-level bugs, and one small but real vulnerability that we responsibly disclosed.
In the end, we recovered everything. The attacker did not collect a single DOT.
What we built from that experience
By that point it was clear this wasn’t a one-off. The problem is real, it affects real people across the entire Polkadot ecosystem, and the expertise required to handle it well is genuinely rare. So we built PAPI Rescue: a technical recovery service for compromised wallets on Polkadot-based chains.
The team behind it is the same team behind polkadot-api. We know the protocol at a low level. That’s not an accident; it’s exactly why this kind of recovery is possible where others have given up.
The track record
To date, we’ve recovered $250,000+ in assets across eligible cases, with a 100% recovery rate.
That last number deserves a caveat: not every case is recoverable. If funds have already left the wallet and are beyond any protocol-level constraint, there is nothing we or anyone else can do. We will tell you that honestly upfront, before any commitment is made.
But for cases where recovery is still possible, and there are more of those than people realise, we have not failed yet.
Why we built this when we did
Some of you will remember the funding situation we wrote about earlier this year. When our funding was paused, we had a choice: wait it out, or find a way to keep contributing that didn’t depend on committee approval.
We chose the latter.
PAPI Rescue wasn’t a pivot away from our core work. It was a way to stay embedded in the ecosystem and keep funding our team. Every recovery case we take deepens our understanding of the protocol. The edge cases we encounter feed back into polkadot-api. The bugs we find get disclosed and fixed. The team stays together and keeps shipping.
We didn’t leave when the funding went away. We found a symbiotic path: one where we add direct, measurable value to people in the community who need it most, and in return we sustain the work on the libraries and protocol tooling that the broader ecosystem depends on.
That felt right to us. It still does.
How to reach us, and why we designed it this way
The intake form on our landing page is live. I want to walk through how it works, because the design reflects something important about the nature of this problem.
The obvious approach would be a simple email form. We deliberately didn’t do that. Here’s why: attackers are often watching. If they see their victim reaching out to a recovery service, their incentive is to spam that same contact channel, flooding us with fake requests under the compromised account and making it impossible to identify who the legitimate owner is.
So instead, the intake process works like this:
-
You provide the compromised account address. We check on-chain whether the account has locked or reserved funds that are technically recoverable. If there’s nothing to recover, we tell you immediately. No point going further.
-
If funds are recoverable, the form asks for your email and asks you to sign a message with the compromised account. This is the first ownership signal.
-
We ask for a small on-chain verification transaction. Specifically, 1 DOT sent in a batch call that includes a remark with your request ID. This is a refundable deposit, not a fee: once the legitimate owner is confirmed, every DOT collected is returned to them, regardless of who sent it. The purpose is purely to make it costly for attackers to flood us with fake claims on the same account.
One more thing that is non-negotiable: we can only help people who are willing to prove they are the legitimate owner of the compromised account. If you’re not willing or able to verify ownership, we can’t take your case. Not because we don’t want to help, but because without that verification we could inadvertently be helping the attacker. We won’t do that.
If you, or someone you know, has been compromised
The single most important thing to understand is this: recovery is often possible when people assume it isn’t. Most people who get hacked either don’t know help exists, or give up too quickly. If funds are still in the wallet, even staked, even being drained slowly, there may be a path.
Head to papirescue.now and start a recovery assessment. We’ll give you an honest answer.
And if you know someone in the ecosystem who has been in this situation, please pass this along. Word of mouth is how people in crisis find out that help exists.
More to come, including a deeper write-up on the protocol-level findings from our casework and what they mean for the ecosystem. For now, the door is open.