We just lived through the nightmare scenario we were worried about as we called for a moratorium on The DAO: someone exploited a weakness in the code of The DAO to empty out more than 2M ($40M USD) ether.
The exploit seems to have targeted the reentrancy problem in the 'splitDAO' function. The reentrancy problem is related to but distinct from the unchecked-send problem that was discussed on this blog yesterday. Both problems are well-known, identified by Least Authority's audit of the Ethereum virtual machine as problems that can affect applications, as well as Peter Vessenes's recent blog post. In essence, a call that looks like a regular call can easily be turned into a recursive call, and unless the application is coded very carefully, it can be used to make multiple withdrawals when only one should be allowed. It looks like the attacker took advantage of it to withdraw substantial sums.
My immediate reactions to this hack are as follows.
First of all, I'm not even sure that this qualifies as a hack. To label something as a hack or a bug or unwanted behavior, we need to have a specification of the wanted behavior.
We had no such specification for The DAO. There is no independent specification for what The DAO is supposed to implement. Heck, there are hardly any comments in The DAO code that document what the developers may have been thinking at the time they wrote the code.
The "code was its own documentation," as people say. It was its own fine print. The hacker read the fine print better than most, better than the developers themselves.
Had the attacker lost money by mistake, I am sure the devs would have had no difficulty appropriating his funds and saying "this is what happens in the brave new world of programmatic money flows." When he instead emptied out coins from The DAO, the only consistent response is to call it a job well done.
You might think that, faced with an attacker on The DAO, you could just take your funds and be safe. But this is not the case here.
The DAO devs decided to make it difficult to take funds out of The DAO. So they did not give people the option to "just take funds out." Instead, a DAO investor gets to create a new "child DAO" and move her funds into the child and keep them there for 27 days -- there is no direct withdrawal.
The problem is that the child DAO is exactly the same code as the parent, and has the exact same vulnerability. Converting the child back to ether takes another 34 days; replacing the child DAO with an upgraded contract takes a minimum of 7 days.
So, the attacker, if he so chose, could stalk people into their children DAOs, and drain them before they got a chance to upgrade their contracts. I don't think he'll do this: if he rose to this level of obnoxiousness, he'd certainly invoke specific censure.
The DAO was not designed to have an easy "update" function. In particular, at this moment, there seems to be no way to take The DAO from its current state, and reinstate it into a newer contract code, keeping its internal state intact. The "extraBalance" account, in particular, is not transferable through "newContract" upgrades. This means that the extraBalance amount, a few million dollars worth, is a writeoff.
Practically, this should mark the end of The DAO. The SlockIt folks should work hard to dismantle the fund and return the coins back to the investors in as orderly a fashion as possible.
It's clear that writing a robust, secure smart contract requires extreme amounts of diligence. It's more similar to writing code for a nuclear power reactor, than to writing loose web code.
Yet the current Solidity language and underlying EVM seems designed more for the latter. Some misfeatures are:
The current language does not fulfill any of these commandments, and in fact, the last one, involving implicit recursive calls, is what did The Dao in.
The SlockIt team even had the designer and implementor of Solidity perform a review of their code. If he cannot get something like The DAO to be secure, no one can.
A re-think seems called for.
The main worry right now involves copycat attacks. Others can learn from this attack and launch the exact same one.
The big unknown is how the ethereum community will react.
On the one hand, rolling back the ethereum blockchain will send a terrible message. If contracts can be reverted, then how exactly are smart contracts any better than regular old paper contracts?
On the other hand, watching The DAO get drained by a thief is a depressing end to an exciting experiment.
There is no good solution here. Practically speaking, the miners will probably put a freeze in effect and provide some time for The DAO investors to withdraw their funds, to minimize heartache. But in the end, there is no outcome that'll make everyone happy.
Smart contracts are and remain an incredibly exciting field. We have only begun to scratch the surface.
There can be no birth without pain, no initial foray into the unknown without some setback.
I believe that Ethereum overall will emerge from this in a few weeks, having been made much stronger as a result. It will have a newfound direction and charter that involves a slight pivot, away from "let's get DApps at all costs, let's make front-end programmers into smart contract writers," towards "let's build up the science of secure, smart contracts."
And that will make everything worth it.