Ethereum Refunds – How to Get a Refund for Excess Payment in The DAO Tokens

etherthe-daothedao-refundtokens

Anyone who bought DAOs in the last two weeks of The DAO crowdfunding phase paid more than 1 ether (ETH) per 100 The DAO tokens (DAO). The ETH amount in excess of 1 ETH per 100 DAOs was stored in The DAO's extraBalance account. The balance of the extraBalance account has now been transferred into the curator's multisig wallet.

As described in How do I convert my The DAO tokens into ethers using the withdrawal contract after the hard fork?, The DAO token holders can currently convert their DAOs into ETH at a rate of 100 DAO = 1 ETH.

How do I get a refund for the amount I paid in excess of 1 ether to 100 The DAO tokens?


The DAO Refunds


See also:

Best Answer

Update Mar 29 2017

The latest instructions can be found at The DAO Refunds.



At the hard-fork block #1,920,000 , the ETH balance from The DAO and it's child DAOs (which includes the balance from the extraBalance account) were transferred into the Withdrawal contract.

Immediately after the hard-fork, at block #1,920,090, the Withdrawal contact's trusteeWithdraw() function was called in this transaction to transfer 463,798.08818109 ETH into TheDAOCurator multisig wallet.

See the ExtraBalance section in The DAO’s Edge Cases Multisig (Post Hard Fork) by Griff Green for the refund process being planned.

You should be able to find your account that contributed to the Extra Balance account in github.com/bokkypoobah/TheDAOData with further details in Which accounts contributed to The DAO's extraBalance account?:

Notes:

Update 08:07 Sep 13 2016 UTC

From ExtraBalance Withdraw Contract to be Funded on September 15th by Griff Green, the Withdrawal contract will be funded by the curators on Sep 15 2016. You will then be able to withdraw your ethers using the methods listed below. You will find a more detailed guide to executing the Withdrawal contract using the Ethereum Wallet (similar to Method 2 below) in this linked article. Check that the ETH balance of 0x755cdba6AE4F479f7164792B318b2a06c759833B is non-zero before trying to execute your withdrawal.

Update 14:08 Sep 17 2016 UTC

The Withdrawal contract has been topped up by the curators with 344,917.580854976758120496 ETH. You can now execute your withdrawals!


Following are 3 methods to withdraw your funds:

  • Method 1 - MyEtherWallet
  • Method 2 - The Ethereum Wallet
  • Method 3 - geth



Method 1 - Withdrawing Using MyEtherWallet

Update 07:00 Sep 17 2016 UTC From @tayvano:

Please make sure the funds have been depositted by checking that the extraBalance Withdraw Contract has a balance before attempting to withdraw. We have pushed this live as we are unavailable until the night of September 17th. Thank you.

Run MyEtherWallet from https://www.myetherwallet.com/#the-dao (Be careful as there are bogus MyEtherWallet phishing sites with similar URLs popping up over the internet aiming to steal your private keys.) enter image description here



Method 2 - Withdrawing Using The Ethereum Wallet

UPDATE 05:22 Sep 8 2016 UTC - The ExtraBalWithdrawal contract has been upgraded - replace your old version if you have already set it up. Also note that the Withdrawal contract has not been filled yet.

UPDATE 06:04 Sep 9 2016 UTC - @ledgerwatch has created the document How to withdraw from extraBalance refund contract that includes some steps for replay protection.

Make sure that you have downloaded Ethereum Wallet 0.8.1 or later.

The first time you start Ethereum Wallet 0.8.1, select "Yes" to the question "Do you want to activate the chain in which funds linked to the exploit are restored to a contract where they can be withdrawn by The DAO token holders?". You have now made the choice to use the hard-forked Ethereum chain.

Method 2 - Step 1 - Watch ExtraBalToken Contract

In Ethereum Wallet, select the CONTRACTS page in the top menu. Click on WATCH CONTRACT.

  • Enter a CONTRACT NAME of ExtraBalToken
  • Enter a CONTRACT ADDRESS of 0x5c40ef6f527f4fba68368774e6130ce6515123f2
  • Enter in JSON INTERFACE field the following text: [{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","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":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"seal","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"data","type":"uint256[]"}],"name":"fill","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"sealed","outputs":[{"name":"","type":"bool"}],"type":"function"},{"inputs":[],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
  • Click OK. Your Watch Contract should look like: enter image description here

Method 2 - Step 2 - Watch ExtraBalWithdrawal Contract

In Ethereum Wallet, select the CONTRACTS page in the top menu. Click on WATCH CONTRACT.

  • Enter a CONTRACT NAME of ExtraBalWithdrawal
  • Enter a CONTRACT ADDRESS of 0x755cdba6ae4f479f7164792b318b2a06c759833b
  • Enter in JSON INTERFACE field the following text: [{"constant":false,"inputs":[],"name":"clawback","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"}]
  • Click OK. Your Watch Contract should look like: enter image description here

Method 2 - Step 3 - Execute ExtraBalToken.Approve

This will approve the transfer of the tokens from your account to the ExtraBalWithdrawal contract. Make sure that you send 0 ethers as this transaction may be replayed on the Ethereum Classic chain.

Select the CONTRACTS page in the top menu. Click on EXTRABALTOKEN.

  • In the Balance of field on the left hand side of the page under READ FROM CONTACT, enter your account address, ALL IN LOWERCASE. Your withdrawal balance in wei should be displayed under your address.
    • Copy this balance figure
  • On the right hand side of the page under WRITE TO CONTRACT
    • Select function Approve.
    • In spender, enter 0x755cdba6ae4f479f7164792b318b2a06c759833b, the address of the ExtraBalWithdrawal contact.
    • Copy the value in the Balance of result from the left hand side of the page and paste this figure into the value field.
    • In Execute from, select your account.
    • Enter 0 as the number of ETH under the Send ETHER field.
    • Click on the EXECUTE button, enter your password and confirm.

Here is a screen image: enter image description here

Method 2 - Step 4 - Execute ExtraBalWithdrawal.Withdraw

--- DON'T EXECUTE THIS INSTRUCTION JUST YET. The curators have not filled the extraBalWithdrawal contract and the execution will fail. This post will be updated when you are able to execute this script ---

This will withdraw ETH from the ExtraBalWithdrawal contract to your account. Make sure that you send 0 ethers as this transaction may be replayed on the Ethereum Classic chain.

Select the CONTRACTS page in the top menu. Click on EXTRABALWITHDRAWAL. On the right hand side of the page under WRITE TO CONTRACT, Select function Withdraw. In Execute from, select your account. Enter 0 as the number of ETH under the Send ETHER field. Click on the EXECUTE button, enter your password and confirm. Here is a screen image:

enter image description here



Method 3 - Withdrawing Using geth

UPDATE 05:22 Sep 8 2016 UTC - The ExtraBalWithdrawal contract has been upgraded and the code below has been tested. Note the new address and ABI in the geth script below.

Make sure that you are running geth version 1.4.10 or later. And run your geth commands with the --support-dao-fork option so that you are on the hard-forked blockchain.

--- DON'T EXECUTE THE FOLLOWING COMMANDS JUST YET. The curators have not filled the extraBalWithdrawal contract and the execution will fail. This post will be updated when you are able to execute this script ---

user@Kumquat:~$ geth --support-dao-fork console
// Allow chain to sync
var account = "{your account}".toLowerCase();
personal.unlockAccount(account, "{your account password}")

var extraBalTokenAddress = "0x5c40ef6f527f4fba68368774e6130ce6515123f2";
var extraBalTokenABIFragment = [{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"}, {"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"type":"function"}];
var extraBalTokenContract = eth.contract(extraBalTokenABIFragment).at(extraBalTokenAddress);    

var extraBalWithdrawalAddress = "0x755cdba6ae4f479f7164792b318b2a06c759833b";
var extraBalWithdrawalABIFragment = [{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"type":"function"}];
var extraBalWithdrawalContract = eth.contract(extraBalWithdrawalABIFragment).at(extraBalWithdrawalAddress); 

var balance = extraBalTokenContract.balanceOf(account);
console.log("Your extraBalTokenContract.balance() for " + account + " is " + web3.fromWei(balance, "ether") + " ethers");

// Approve the transfer of your tokens from the extraBalToken contract
// to the extraBalWithdrawal contract
var approve = extraBalTokenContract.approve(extraBalWithdrawalAddress, balance, {from: account, value: 0});
console.log("approve() returned " + approve);

// Wait for approve() to be mined. Repeat checking using the following command until you get a non-null result.
eth.getTransactionReceipt(approve).blockNumber;

var withdraw = extraBalWithdrawalContract.withdraw({from: account, value: 0});
console.log("withdraw() returned " + withdraw);

// Wait for withdraw() to be mined. Repeat checking using the following command until you get a non-null result.
eth.getTransactionReceipt(withdraw).blockNumber;

// Your withdrawal should now be complete. Check your account balance has received the withdrawal amount.
web3.fromWei(eth.getBalance(account), "ether");



ExtraBalToken Contract

@ledgerwatch in thedao.slack.com/messages/extrabal_community deployed the ExtraBalToken contract to 0x5c40ef6f527f4fba68368774e6130ce6515123f2.

contract ExtraBalToken {
    uint256 public totalSupply;

    /* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    /* This generates a public event on the blockchain that will notify clients */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /* Send coins */
    function transfer(address _to, uint256 _value) {
        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
        balanceOf[msg.sender] -= _value;                     // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
        Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place
    }

    /* Allow another contract to spend some tokens in your behalf */
    function approve(address _spender, uint256 _value)
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        return true;
    }

    /* A contract attempts to get the coins */
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        if (balanceOf[_from] < _value) throw;                 // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw;  // Check for overflows
        if (_value > allowance[_from][msg.sender]) throw;   // Check allowance
        balanceOf[_from] -= _value;                          // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
        allowance[_from][msg.sender] -= _value;
        Transfer(_from, _to, _value);
        return true;
    }

    /* This unnamed function is called whenever someone tries to send ether to it */
    function () {
        throw;     // Prevents accidental sending of ether
    }

    uint constant D160 = 0x10000000000000000000000000000000000000000;

    address public owner;

    function ExtraBalToken() {
        owner = msg.sender;
    }

    bool public sealed;
    // The 160 LSB is the address of the balance
    // The 96 MSB is the balance of that address.
    function fill(uint[] data) {
        if ((msg.sender != owner)||(sealed))
            throw;

        for (uint i=0; i<data.length; i++) {
            address a = address( data[i] & (D160-1) );
            uint amount = data[i] / D160;
            if (balanceOf[a] == 0) {   // In case it's filled two times, it only increments once
                balanceOf[a] = amount;
                totalSupply += amount;
            }
        }
    }

    function seal() {
        if ((msg.sender != owner)||(sealed))
            throw;    
        sealed= true;
    }    
}

The contract ABI is: [{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","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":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"seal","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"data","type":"uint256[]"}],"name":"fill","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"sealed","outputs":[{"name":"","type":"bool"}],"type":"function"},{"inputs":[],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}].

@ledgerwatch then fill(...)ed the ExtraBalToken contract with the extraBalance values generated from a script similar to my getTheDAOCreatedTokenEventsWithNonZeroExtraBalance_v4 script. The results from my script can be found at CreatedTokenEventsWithNonZeroExtraBalance_v4.txt or CreatedTokenEventsWithNonZeroExtraBalance_v4.xlsx.

I have tested the ExtraBalToken contract - see the reconciliation script and report at github.com/bokkypoobah/TheDAOData/ExtraBalTokenValuesReconciliation.

The contract was then seal()ed in block #2,202,674.



ExtraBalWithdrawal Contract

UPDATE 05:22 Sep 8 2016 UTC The ExtraBalWithdrawal (WithdrawDAO in the source code) has been upgraded and deployed to a new address. trusteeWithdraw(...) has been replaced with clawback().

@ledgerwatch deployed the upgraded contract to 0x755cdba6ae4f479f7164792b318b2a06c759833b.

// Refund contract for extraBalance
// Amounts to be paid are tokenized in another contract and allow using the same refund contract as for theDAO
// Though it may be misleading, the names 'DAO', 'mainDAO' are kept here for the ease of code review

contract DAO {
    function balanceOf(address addr) returns (uint);
    function transferFrom(address from, address to, uint balance) returns (bool);
    uint public totalSupply;
}

contract WithdrawDAO {
    DAO constant public mainDAO = DAO(0x5c40ef6f527f4fba68368774e6130ce6515123f2);
    address constant public trustee = 0xda4a4626d3e16e094de3225a751aab7128e96526;

    function withdraw(){
        uint balance = mainDAO.balanceOf(msg.sender);

        if (!mainDAO.transferFrom(msg.sender, this, balance) || !msg.sender.send(balance))
            throw;
    }

    /**
    * Return funds back to the curator.
    */
    function clawback() external {
        if (msg.sender != trustee) throw;
        if (!trustee.send(this.balance)) throw;
    }
}

The contract ABI is: [{"constant":false,"inputs":[],"name":"clawback","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"}].

NOTE This contract is yet to have the ethers added for The DAO token holders to withdraw.



Further References