After evaluating a lot of feedback, discussing the options described here and finding support for a multisig that would send ether to withdraw contracts for the edge cases, the following hard fork specification is proposed as having an acceptable tradeoff between auditability and completeness:

Specification:

The DAO (0xbb9bc244d798123fde783fcc1c72d3bb8c189413), its extraBalance (0x807640a13483f8ac783c557fcdf27be11ea4ac7a), all children of the DAO creator (0x4a574510c7014e4ae985403536074abe582adfc8) and the extrabalance of each child are encoded into a list `L` at block 1880000.

`L` is a list of all DAO addresses and extraBalanceAccount objects at https://gist.github.com/CJentzsch/faf894be44ee82b7ea07fd032eaf69a8, or in a list form https://gist.github.com/gavofyork/af747a034fbee2920f862ed352d32347. It can also be generated via the following python script:

from ethereum.utils import mk_contract_address

source = ‘0x4a574510c7014e4ae985403536074abe582adfc8’ L = [‘0xbb9bc244d798123fde783fcc1c72d3bb8c189413’, ‘0x807640a13483f8ac783c557fcdf27be11ea4ac7a’] + \ [‘0x’+mk_contract_address(source, i).encode(‘hex’) for i in range(1,58)] + \ [‘0x’+mk_contract_address(mk_contract_address(source, i), 0).encode(‘hex’) for i in range(1, 58)]

Or using this script: https://gist.github.com/CJentzsch/f0da62e4ff0ea8a2a3f4c81c2c50753a

At the beginning of block 1920000, all ether throughout all accounts in `L` will be transferred to contract account `C`, which is deployed at 0xbf4ed7b27f1d666546e30d74d50d173d20bca754. You can verify the solidity source code of `C` at https://etherscan.io/address/0xbf4ed7b27f1d666546e30d74d50d173d20bca754#code.

The contract `C` includes a withdraw function that allows DAO token holders to exchange their DAO tokens for ETH at a rate of 100:1 (NOTE: in base units, the exchange rate is 1:1 as ether has 10¹⁸ wei in 1 ETH whereas DAO has 10¹⁶ base units in 1 DAO). The trusteeWithdraw() function allows the curator multisig to withdraw the excess ether which cannot be withdrawn via the withdraw function. This allows the curator multisig to simultaneously:

1. Rescue all childDAOs including “legitimate” splits that may contain attackers

2. Allow the DAO token holders that sent ether to the extraBalance to withdraw that ether using an automated script as quickly as possible but still provide time for an appropriate security review.

3. Cover all edge cases including the 30% ETH losses from DAO token holders who split after the attack

The totalSupply() is 11538165987024671407837618 (see here); this.balance would return the balance of the withdrawable contract (namely, 12072877.497524777 ETH — X where `X` is the amount of ether already withdrawn, and 12072877.497524777 is the amount of ether in `L` at the time of this writing), and mainDAO.balanceOf(this) is the amount of DAO tokens collected by the the contract itself, which is equal to the amount of ether that has already been withdrawn divided by 100 (note again the 1:1 base-unit correspondence).

Hence, for example, if 100,000 ETH has already been withdrawn, the trusteeWithdraw() function would withdraw 11972877 + 100000–11538165 = 534712 ETH, which is exactly the intended amount. If 200000 ETH has already been withdrawn, it would withdraw 11872877 + 200000–11538165 = 534712 ETH. If the function is called multiple times, the second time it would withdraw 0 ETH.

Withdrawing for main DAO token holders is a two-step process: first call The DAO approve() function to approve the withdraw contract to transfer your DAO tokens, and then call the withdraw contract’s withdraw() function. In the geth command line, this would look as follows:

dao = web3.eth.contract([{“constant”:true,”inputs”:[],”name”:”name”,”outputs”:[{“name”:””,”type”:”string”}],”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_spender”,”type”:”address”},{“name”:”_amount”,”type”:”uint256"}],”name”:”approve”,”outputs”:[{“name”:”success”,”type”:”bool”}],”type”:”function”},{“constant”:true,”inputs”:[],”name”:”totalSupply”,”outputs”:[{“name”:””,”type”:”uint256"}],”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_from”,”type”:”address”},{“name”:”_to”,”type”:”address”},{“name”:”_amount”,”type”:”uint256"}],”name”:”transferFrom”,”outputs”:[{“name”:”success”,”type”:”bool”}],”type”:”function”},{“constant”:true,”inputs”:[],”name”:”decimals”,”outputs”:[{“name”:””,”type”:”uint8"}],”type”:”function”},{“constant”:true,”inputs”:[],”name”:”standard”,”outputs”:[{“name”:””,”type”:”string”}],”type”:”function”},{“constant”:true,”inputs”:[{“name”:”_owner”,”type”:”address”}],”name”:”balanceOf”,”outputs”:[{“name”:”balance”,”type”:”uint256"}],”type”:”function”},{“constant”:true,”inputs”:[],”name”:”symbol”,”outputs”:[{“name”:””,”type”:”string”}],”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_to”,”type”:”address”},{“name”:”_amount”,”type”:”uint256"}],”name”:”transfer”,”outputs”:[{“name”:”success”,”type”:”bool”}],”type”:”function”},{“constant”:true,”inputs”:[{“name”:”_owner”,”type”:”address”},{“name”:”_spender”,”type”:”address”}],”name”:”allowance”,”outputs”:[{“name”:”remaining”,”type”:”uint256"}],”type”:”function”},{“anonymous”:false,”inputs”:[{“indexed”:true,”name”:”_from”,”type”:”address”},{“indexed”:true,”name”:”_to”,”type”:”address”},{“indexed”:false,”name”:”_amount”,”type”:”uint256"}],”name”:”Transfer”,”type”:”event”},{“anonymous”:false,”inputs”:[{“indexed”:true,”name”:”_owner”,”type”:”address”},{“indexed”:true,”name”:”_spender”,”type”:”address”},{“indexed”:false,”name”:”_amount”,”type”:”uint256"}],”name”:”Approval”,”type”:”event”}]).at(‘0xbb9bc244d798123fde783fcc1c72d3bb8c189413’) withdrawable = web3.eth.contract([{“constant”:false,”inputs”:[],”name”:”trusteeWithdraw”,”outputs”:[],”type”:”function”},{“constant”:false,”inputs”:[],”name”:”withdraw”,”outputs”:[],”type”:”function”},{“constant”:true,”inputs”:[],”name”:”mainDAO”,”outputs”:[{“name”:””,”type”:”address”}],”type”:”function”},{“constant”:true,”inputs”:[],”name”:”trustee”,”outputs”:[{“name”:””,”type”:”address”}],”type”:”function”}]).at(‘0xbf4ed7b27f1d666546e30d74d50d173d20bca754) dao.approve(withdrawable.address, dao.balanceOf(eth.accounts[0]), {from: eth.accounts[0]}) withdrawable.withdraw({from: eth.accounts[0], gas: 500000})

This procedure has been tested. See this transaction: https://etherscan.io/tx/0xa2d43ef6ec0b34ffe83628ccacc21df47858140e6a3fe5a33c078fede26ac109.

The extradata of blocks X to X+9 inclusive must be: 0x64616f2d686172642d666f726b (this is needed so that header only clients (fast sync, light client) can differentiate between peers on different chains). DAO-aware “anti-fork” clients can accept block headers between block X and X+9 only if their extradata is NOT the above.

Implementations:

Go-ethereum:

https://github.com/ethereum/go-ethereum/pull/2814

Parity:

https://github.com/ethcore/parity/pull/1483

Misc links:

Diff between (already-audited) Ethereum foundation multisig (left) and the Curator multisig (right):

https://www.diffchecker.com/lasyum7z

Conclusion:

At this point, what remains to be done is double and triple checking every line of code used. The goal was always to keep the code used as simple as possible. This is all open source and the data needed is available on the blockchain. Everyone can review it. Please do so!