Whitehats: Make A Refund Wallet First

A surprising number of people have contacted me about a whitehat attack on TheDAO. I wouldn't participate in a whitehat attack on TheDAO, or really on anything, but I do want to talk about one thing that would be helpful -- a refund wallet.

If whitehats do go ahead and attack TheDAO with the goal of saving at least 70% of the funds, avoid lawsuits and lengthy bankruptcy proceedings, I suggest they utilize what I'm calling a Refund Wallet.

Let's think about what a refund wallet should do, shouldn't do, and might want to do.

Full Disclosure -- I think TheDAO Should Directly Refund

There are lots of possibilities forward, but I think the best one for TheDAO token holders is a straight up refund. I don't have a proposal for the fairest way to do the split, but I will suggest a simple one as a straw man for this post -- each token held in the parentDAO gets a pro-rata share of remaining coins.

I'm going to imagine there are two functions in our wallet that I won't detail here: tokensHeldBy(account) and totalDAOTokens(), and an array of accounts that are token holders, tokenHolders.

Then a fair distribution of any ether coming in could be coded up like this:

function() {  
   for (uint32 i=0; i < tokenHolders.length; i++) {
     tokenHolders[i].balance += msg.value *  tokensHeldBy(tokenHolders[i].account) / totalDAOTokens() ;
  }
}

We'll talk about withdrawal for a second, but this would fairly accrue any balances over to tokenHolders, pro-rata with the amount of tokens they own.

Withdrawals

First things first, a refund wallet should not be vulnerable to any of the wide array of attacks we know about now, published on this blog or elsewhere.

It should not be too fancy. It should allow users to withdraw their portion, and not be vulnerable to any recursive call threats.

How could this be coded? I'm paranoid right now, and would suggest it be implemented with every safety feature we can imagine: user-implemented withdrawal, mutexes and proper ordering of account balance mutation. Something like this

bool alreadyExecutingWithdraw;

function withdraw() {  
   if ( alreadyExecutingWithdraw) { throw; }
   if (! istokenHolder(msg.sender)) { throw; }
   var tokenHolderIndex = tokenHolderLookup(msg.sender);
   int balance = balances[tokenHolderIndex];

   if (balance <= 0) { throw; } // better would be a logged event

   alreadyExecutingWithdraw = true;

   balances[tokenHolderIndex] = 0;

   if (!(msg.sender.send(balance)) {
      // we failed to send. Log it And roll back
      LogFailedSend(msg, balance);
      balances[tokenHolderIndex] = balance;
   }

   alreadyExecutingWithdraw = false;
}

Not all details are covered here, but this is the core idea. With this contract in hand, we can be assured that any money going in is credited to token holders pro-rata, and that only a token holder can request a withdraw, and that the withdraw is protected from recursive calls a number of ways.

Publish The Vetted Refund Contract

This contract should be publicized and reviewed for correctness. Once people are convinced, it should be published, resulting in an address, call it the refundAddress.

Step Two: Whitehat Attack Relying on the Refund Wallet

A successful whitehat attack contract would take the rest of the money into a new childDAO. It would be instrumented to do the following:

  1. Attack any split proposal by joining, voting yes and doing the recursive attack used by the darkDAO attacker
  2. Vote no on any non-split proposal that does not have refundAddress as the recipient.
  3. Vote yes on any non-split proposal that does have refundAddress as a recipient.

With this contract deployed, the whitehats can sit back. Both 2 and 3 can be instrumented to be callable by anyone in the world.

Result

This childDAO can be safely whitelisted by miners -- it pays out a refund to DAO token holders, that's it. And, in fact, even if there is no soft fork, this pattern could be used to get a guaranteed refund out to participants, especially if the childDAO had only a single participant.

Refinements

There are a lot of refinements on this, but I want to hold them back for now, and see if we can get some discussion going about this idea. To me, it's a fair shake that doesn't end with years of multi-country bankruptcy litigation, makes threats of all sorts useless against the whitehats and keeps the token holders first without pulling them into some crazy world of new DAO proposals or other extreme complications.

Problems

Reddit user avsa noted that there are too many token holders to loop through -- the block gas limit is too small to make a loop like this happen. Read here for more on his proposal and comments.

This isn't a deal breaker. Token holders can be grouped into smaller chunks for processing, and then processChunk could be called. It needs to be properly engineered, but doesn't fundamentally change the suggested mechanics of a refund wallet.

Also, he noted there is no in-contract list of token holders. This list could be created outside the contract, and embedded. There are slightly more complex ways to solve this without a list, as well. Here's one.

More Complicated Token Holder Credit Schemes

If you don't have a list of token holders, things get tougher: on a payment in to the refund wallet, it can't pass things on directly to a balances variable.

The reason this causes problems is we really want to makes sure we're giving everyone the proper amount of credit for the money. If some get credited early, some later, perhaps after tokens move around, there will be trouble.

So, we could do this. Each payment that comes in is put into an 'incoming payments' list. (We'd want to deal with spam, but that can wait).

Now, each token holder can request a withdrawal of each unclaimed deposit.

This means if tokenholders are paid off in pieces, it's no problem -- they can claim each of those separately. In fact, anyone could initiate the transfer for them. The tokenholder would have marked how many tokens they held that had been paid off per incoming transfer.

If tokens transfer around before claims are made, this could cause some problems, but not fundamental contract problems, just questions of value -- a token contract that hasn't been paid out is worth more. I propose these problems are drilled down to the point where there is no existential risk to the ecosystem or theDAO token holders.

As always, I'm available for contracting and audit: contact me directly.

Peter Vessenes

Read more posts by this author.

Subscribe to Peter Vessenes

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!