What happened, what we can learn from it, and why this was really so dumb?
by Kevin Wong
On 29th October 2018, about 4 million PRL tokens was minted out of the token contract and sent to KuCoin to be cashed out, subsequently causing a price crash and the suspension for the trading of the token. This “hack” can only be done by a team member.
OYSTER CONNECT WAS AN INSIDE JOB
Well, I can’t claim that I am knowledgeable about the team structure or the product, and that isn’t the point either. Suffice to say this could have happened to anyone, and I am willing to extend the benefit of doubt towards the team and call this an act conducted by a single malicious actor that held the private keys to the director address. Regardless, people should not wave the “S” word around so lightly.
A tiny hole for a big rat
Firstly, let us take a look at the code shall we?
Code can be found here : https://etherscan.io/address/0x1844b21593262668b7248d0f57a220caaba46ab9#code
We can see above that closeSale and openSale both uses the onlyDirector function modifiers. What’s inside the onlyDirector function modifier?
Seems like onlyDirector is controlled by another boolean named directorLock.
Ok, seems like directorLock will be set to true when selfLock is called.
What is onlyDirectorForce? Lets see where it is used.
Looks like onlyDirectorForce can transferDirector and withdrawFunds a.k.a. Ether.
All seems good eh, let me just check the variable in the token contract.
When it rains, it pours
So, we know that since the director was never locked out because selfLock was never called, openSale can still be called by the owner. We can also see that transferDirector is open for the director account to be called anytime.
Our malicious little insider, which I will henceforth refer to as Wormtail, first made an account and filled it with ether. Not a lot, but just enough.
Address in question https://etherscan.io/address/0x0001ee57bb28415742248d946d35c7f87cfd5a54
Then, Wormtail called transferDirector using the original director wallet and transferred directorship to his address with ether.. https://etherscan.io/tx/0x1ea00178c70ca6c1cc2d020939831d1393ac5fcf6154495395a074e19e0e70f9
With his newfound powers, Wormtail now calls openSale https://etherscan.io/tx/0x2321e305c20f45429f11045b9235e9bbd66b17bacede173ca86144ac5533d3bf and allowed anyone who sent ether to the contract to receive tokens at 5000PRL/ETH.
So now Wormtail sends Ether to the contract, gets 5000 PRL, then calls withdrawFunds to withdraw funds back to his address and repeats this process multiple times. All the while, he is sending the extra PRLs to exchanges, selling to ETH, withdrawing BTC (and maybe ETH) and (probably) Shapeshifting his bag of loot, securing his profit before anyone was prepared to combat his ratty ways. https://etherscan.io/txs?a=0x0001ee57bb28415742248d946d35c7f87cfd5a54
How much money did Wormtail made out of this? The malicious address alone had about 4 million PRL tokens minted, not accounting for the fact that he might have other accounts (or maybe not). That is somewhere about 4 million tokens minted at no cost to Wormtail. If he was able to sell all his tokens at $0.25, that is close to $1.5 million, assuming that he was able to withdraw it (well probably not, gotta account for that market slippage. Link below did specify that he was only able to withdraw about $300,000 before suspension). You can read more about the more team and exchange side of the story here https://oysterprotocol.com/oyster-update/
To make a mistake is only human; to persist in a mistake is idiotic.
A mistake is only a mistake if you don’t learn from it. What could be done next time for aspiring smart contract programmers to avoid this situation?
- The roles for director like functions and administrator like functions should be have been separated so that not a single person have control over the entire contract. This could also be done by having multiple smart contract governing sales and pegging which could potentially be owned by other accounts.
- Directorship could have been delegated to another smart contract to ensure actual decentralization. The new smart contract will need multiple signatures before executing any directorship functions.
- directorLock should not rely entirely on selfLock but maybe another modifier that is governed by timestamp. (eg, auto-lock after 6 months).
- Crowdsale contract should not be restartable in PRL’s particular case. This could be also governed with a timestamp etc.
We can see that this is not really a bug. It was the fact that directorship was never locked that caused this to happen. An err in logic and assumptions if you will. Unfortunately, directorship was also needed to control the pegging mechanisms within the smart contract, rendering it too important to disable. The code suffered from a poor design, that was later exploited by its creator for quick monetary gains.
Was the code malicious by design? Maybe. Who knows what was running in Wormtail’s mind?
Perhaps the biggest mistake of all was the assumption that humans are incorruptible, regardless of circumstances. In a scam-ridden space, we are at no luxury to assume the good intent of others while hundreds of thousands of dollars are dangling before their eyes. The extremely efficient movement of funds, the coincidental timings, and decisiveness of the act, all point to a premeditated and elaborate scheme that was planned weeks ahead, and conceived months before.
Is this the worst thing that can happen to a project? Nah, far from it honestly. If PRL is a legitimate project, I think the team can bounce back and recover from the incident, though not without a slight mar in the brand name itself.
“To have a good enemy, choose a friend: he knows where to strike.”
Original director address: 0x2DA59901939682Eab8887EDb0Fd1CE4299072265
Token Contract address: 0x1844b21593262668B7248d0f57a220CaaBA46ab9
Malicious director transfer txHash: 0x1ea00178c70ca6c1cc2d020939831d1393ac5fcf6154495395a074e19e0e70f9
Malicious wallet: 0x0001ee57bb28415742248d946d35c7f87cfd5a54
I have no investments in Oyster Pearl, this article is purely for educational purposes and I am in no way condoning what the exploiter has done, nor am I calling the project a scam, nor am I trying to FUD your beloved project. Do your own due diligence.
Oyster Website: https://oysterprotocol.com/
Team Update: https://oysterprotocol.com/oyster-update/