There have recently been two high-profile cases of protocols recovering a large chunk of their stolen funds by counter-attacking the hacker which stole them. Platypus Finance was hit by a bungled attack that left funds locked in the attack contract, where the team was able to retrieve some of the tokens. Jump Crypto, backers of the Wormhole bridge which ate a $326M exploit in the middle of Bridge Hack Season in early 2022, were able to recover $140M of their lost funds when the hacker placed it into a DeFi protocol to earn yield.
These events make electric, you-couldn’t-make-this-up stories. We love to see the good guys win, and it’s just poetic when the hacker is hoisted by their own petard in a counter-hack.
There’s a bigger lesson here, however, and it’s not as happy-ending as the recovery of millions of dollars from evildoers. Both of these counterattacks were made possible by a subtle and sometimes sinister piece of tech: the upgradeable smart contract.
For those who aren’t familiar, smart contracts on Ethereum are immutable. Once you deploy them, their code cannot change.
This is why you can safely deposit your hard-earned internet money into a protocol. You can read the code, determine exactly what it does, and know it’s never going to stop acting the way that you expect it to behave.
This is the essence of trustlessness. You don’t have to trust whoever you’re dealing with. You may even know they they are untrustworthy. But if the code is right, you don’t have to trust them.
If the contract is written safely, it does not matter who deployed it. You can put your ETH into an identical copy of the WETH contract deployed by the scummiest dark web ne’erdowell out there, and know it’s going to be safe. It could have been deployed by North Korea’s Lazurus group themselves. Does not matter.
All these assurances go out the window when you start talking about upgradeable contracts.
An upgradable contract uses a few features of the EVM to effectively change its code. Standard contracts have their storage and implementation code in the same place. Upgradeable contracts use a proxy pattern which separates the storage (balances, etc) from the code which gets executed when you call the contract.
Users interact with a proxy, which holds the storage but does not have any implementation code of its own, just code dealing with the delegation.
The proxy will delegate calls to the implementation contract containing the code. Delegate calling is a fancy way of saying “ask this other contract what I should do, then do it”
Proxies don’t have to be upgradeable. Many are not. If you want to make a proxy upgradeable, all you have to do is add code to the proxy that lets it point to a different implementation.
A lot of legitimate protocols use this pattern. It can be used to fix bugs, add features, etc. with minimal disruption to the users.
However.
What happens when the new implementation does something you don’t expect?
Like, say, add a function that lets the owner withdraw everything in the vault?
This is essentially what happened to the Jump and Platypus hackers. The Platypus hacker used a bug in the USP stablecoin’s solvency mechanism to drain the protocol, critically however, their attack vector required sending tokens to Platypus in order to get more back than they put in.
The attacker’s bungled attack contract didn’t have a way to withdraw his stolen funds, which were now permanently locked. It also didn’t have a protection on the flash loan callback function meant to receive the flashloaned funds and use them to exploit Platypus. This meant anyone could trigger the callback function and start the hack.
But what good would it do to hack them when they’d already been hacked?
Platypus’s smart contracts were upgradeable.
They changed the logic so that when the attack flow was called, instead of sending back more than was put in, the contract just took everything that was put in. They turned the protocol itself into an attack contract. From there, it was as simple as triggering the attacker’s callback function, sending the tokens into the waiting arms of Perry the Platypus team.
The Wormhole counter-exploit does not involve an attacker’s smart contract, but rather an operational mistake by the attacker. In his quest for yield, or something, he deposited $140M into an upgradeable vault controlled by Oasis. Oasis recieved a court order to dispatch the fiend, which they did, by upgrading the vault contract to a version that permitted sending its contents to a third party. For more details, you can see this thread and this article.
Both of these recoveries involved the attacker screwing up, and the protocol being upgradeable. If the Platypus attacker had added a withdrawal function to his contract, he would have been gone with the wind and halfway to Tornado Cash by the time Platypus devs were on the scene. If the Wormhole exploiter had deposited his tokens somewhere else, authorities could have done little besides seethe silently.
Conversely, if the protocols were not upgradeable, the Platypus funds would have been locked forever, and the Wormhole exploiter would still be merrily doing whatever he intended to be doing.
It’s a heart-warming story when it’s the good guys doing it to the bad guys in the name of law and order, but it can just as easily be you getting rugged by a bad actor.
Watch out for upgradeable contracts, and treat them with the respect they deserve.
Stay safe out there, anon.