How Crypto Gets Hacked - The Death of The Dao
Part 3: The death of THE DAO and birth of two Ethereums
I started my crypto journey answering the basic questions of how this works, why this important and why I should be paying attention. But then I wondered “What could go wrong? How does a crypto protocol get hacked and what happens after?”
Im starting this mini-series to help you discover what I found. Hope you enjoy.
Disclaimer: I’ll be talking about individual crypto projects in this series but this is for informational purposes only and not a solicitation to buy or sell any cryptoassets.
Do your own due diligence.
In May of 2016, the first DAO was born.
A DAO is a “Decentralized Autonomous Organization.” DAO’s allow members to pool resources to solve a common goal in a permissionless, trustless manner using smart contracts. Today there are various DAO’s.
There is the MakerDAO, which is governed by the Maker token holders and governs the Maker DeFi application.
There is also Metacartel, a DAO that gives out grants to build up the Ethereum application layer and also runs their own decentralized for-profit venture fund.
But at the time there was only one, and henceforth was forever remembered as
“THE DAO.”
It was crowdfunded with $160,000,000 in ETH, the native cryptocurrency of Ethereum. The world had never seen anything like it: a totally decentralized organization run by code. Seth Bannon at TechCrunch wrote about it back in 2016:
A new paradigm of economic cooperation is underway — a digital democratization of business.
Over the past couple of weeks a project with no mainstream press has become the second biggest crowdfunding project in history. It’s not crowdfunding a product, an artwork or a new cryptocurrency. It’s crowdfunding — or more accurately, crowd-founding — a corporation called “The DAO.” This is a corporation whose bylaws are written entirely in code.
But not quite. Wikipedia defines a corporation as “a company or group of people authorized to act as a single entity (legally a person) and recognized as such in law.” While The DAO is a group of people authorized to act as a single economic entity, no governmental body recognizes it as such.
Rather, it’s given its authority purely through code. The DAO is a decentralized autonomous organization. It, as of the time of writing, controls more than $100 million in assets, and yet it exists entirely on the Ethereum blockchain.
In exchange for supporting THE DAO backers received Dao tokens. These token holders could then vote on governance and how THE DAO spent its resources. They were like a VC fund, corporation, and Kickstarter all rolled into one.
The big difference was everyone owned voting shares, and yet no one owned THE DAO.
THE DAO was ever present and existed solely as code “within the ether.”
Very cool.
But there was a problem: the creators raised far, far more than they had anticipated (the campaign target was only about $500K according to Wikipedia). And during the crowd-sale, a few people alerted the creators the code was vulnerable to attack. A few days later though, one of the creators of THE DAO, Stephan Tual, said in an infamous public post that the code was in no way vulnerable to attack (which you can’t find; the post was deleted).
All good fellow Daoists, nothing to see here.
Just 5 days later THE DAO was hacked.
The person who described the original vulnerability in the code ended up being right. The method he had descibed days before was what the attacker used to drain the funds. He explained in a public post how this was eventually carried out:
Here is some code; see if you can find the problem.
function getBalance(address user) constant returns(uint) { return userBalances[user]; } function addToBalance() { userBalances[msg.sender] += msg.amount; } function withdrawBalance() { amountToWithdraw = userBalances[msg.sender]; if (!(msg.sender.call.value(amountToWithdraw)())) { throw; } userBalances[msg.sender] = 0; }
Here's the problem:
msg.sender
might have a default function that looks like this.
function () { // To be called by a vulnerable contract with a withdraw function. // This will double withdraw. vulnerableContract v; uint times; if (times == 0 && attackModeIsOn) { times = 1; v.withdraw(); } else { times = 0; } }
What happens? The call stack looks like this:
vulnerableContract.withdraw run 1 attacker default function run 1 vulnerableContract.withdraw run 2 attacker default function run 2
Each time, the contract checks that the user's withdrawable balance and sends it out. So, the user will get twice their balance out of the contract.
When the code resolves, the user's balance will be set to 0 however many times the contract was called.
Now, as I've written the attacking wallet code, this (purposely) won't work exactly. There are a few caveats and things to do. But, hopefully this strikes some fear in your heart.
Too bad they didn’t listen or fix it in time.
Maria P. Gomez Gelvez explains it more simply, emphasis mine:
The hacker initiates the interaction with contract Bank through its malicious contract and the sequence of the actions is as follows:
The first thing the hacker does is send ether (75 wei) to the vulnerable contract through the depositfunction of the malicious contract. This function calls the addToBalance function of the vulnerable contract.
Then, the hacker withdraws, through the withdraw function of the malicious contract, the same amount of wei (75), triggering the withdrawBalancefunction of the vulnerable contract.
The withdrawBalance function first sends ether (75 wei) to the malicious contract, triggering its fallback function, and last updates the userBalances variable (that this piece is done last is very important for the attack).
The malicious fallback function calls the withdrawBalancefunction again (recursive call), doubling the withdraw, before the execution of the first withdrawBalance function finishes, and thus, without updating the userBalances variable.
In this example, there are only two recursive calls to the withdrawBalance function so the hacker ends up with a balance of 150 wei. They took more than they should (75 wei) because the userBalance variable is the last thing set/updated.
Imagine you had $100 in your bank account and you could bring your bank teller any number of withdrawal slips. The bank teller gives you money for each slip in order, and only at the end of all the slips do they record your withdrawal.
What if you brought them three slips to each withdraw $100?
What if you brought them three thousand?
3.6 million ETH was stolen from THE DAO using this recursive call exploit, the equivalent of around $70 million at the time. White hat hackers who called themselves the “Robin hood Group” hacked THE DAO using the same method in order to protect the rest of the funds in THE DAO and move them to a safer location. They were able to secure about 70% of the original funds.
Interestingly MakerDAO, which had been also vulnerable to this type of hack, also hacked themselves in order to protect all their funds before the attack on THE DAO.
Now that the funds were safe, there was another problem: what to do about Ethereum?
They knew they had to do something; there was so much invested in THE DAO that the hacker now controlled around 14% of the entire supply of ETH and put the entire protocol in jeopardy.
The Ethereum leadership, including co-founder and spiritual leader Vitalik Buterin, tried to propose a “soft fork” on the protocol, which would invalidate any future harmful transactions the hacker tried to make but would keep the blockchain backward-compatible. All withdrawal requests were subject to a 28 day delay, so they still had time to implement it.
Unfortunately, they later found this soft fork proposal would open them up to another common type of hack known as a denial-of-service attack (DoS attack). At this point, the only chance they had left to return the stolen funds and protect Ethereum was to initiate a hard fork, something that was very controversial at the time.
A hard fork would permanently change the blockchain into a new one which would no longer be backward-compatible with the old blockchain. It would split the Ethereum community in two: one running on the old blockchain and one running on the new, forked blockchain.
Some members of the Ethereum community were adamantly against a hard fork. Ethereum itself hadn’t been hacked. It was this other entity, THE DAO, a smart contract built on top of Ethereum that was hacked. The blockchain itself was still secure. People were in charge of their own cryptocurrency and they should be responsible if it gets stolen, or so they thought. Re-writing the blockchain’s history through a hard fork went against the ethos of a blockchain. They are supposed to be immutable and resistant to any type of censorship or control, and the Ethereum developers were taking the reins for what they thought was a more noble cause: to return the stolen funds.
The community had a vote and the consensus was to hard fork to a new Ethereum blockchain, but you could opt-out and remain on the old blockchain if you wanted to. This would allow Ethereum to roll back the network history to a time before the hack on the DAO. Then they could re-allocate the ETH on THE DAO to a new smart contract and redistribute ETH back to the DAO token holders to return their funds.
Did you get all that?
On July 20th, 2016, block 1,920,000 was officially forked.
Ethereum returned the stolen funds in the form of ETH.
Around 10% of the value/mining power of Ethereum decided to remain on the old blockchain, which would eventually become “Ethereum Classic” (ETC).
The hope was everyone would migrate to the new blockchain and the stolen funds would become worthless. But now that many of the miners stayed on the old blockchain, the hacker had millions of the newly formed ETC cryptocurrency.
Aftermath:
As far as I can tell looking through some old articles, the white hat hackers only partially returned the ETC in their possession and the hacker himself/herself was last seen trying to convert some of the stolen ETC into BTC. If this wallet address is still correct, the hacker is still holding a lot of ETC for some strange reason (Maybe they lost the keys?). If you do any more digging yourself, let me know what you find!
Both Ethereum and Ethereum Classic can be traded on most exchanges today.
Ethereum became the crypto super computer, Web 3.0, the birthplace of DeFi applications and popular NFT’s.
Ethereum Classic is still struggling to find its place in the crypto ecosystem after multiple 51% attacks. (Which I plan to talk about next time)
The death of THE DAO was a warning to all future projects:
This is what could happen to you in the crypto space when you aren’t careful enough with your code.
Seems like we’re still learning the lesson.
Thanks for reading.
More reading:
If you want more info about modern DAO’s, Packy had a nice write-up on his Not Boring blog. He’s also written a lot lately about the Ethereum ecosystem.
This site has a good timeline where I got a lot of material for the DAO hack and Ethereum hard fork. As well as from Gemini’s Cryptopedia, another useful resource.
Here is “The History of the DAO and Lessons Learned” by the slock.it group who created THE DAO (and who also deleted all those posts that made them look bad).
Bloomberg had a nice long form piece on the DAO story as well. Especially about the white hat hackers and how they tried to save THE DAO.