Ether

如何在硬分叉後使用提款合 約將我的 The DAO 代幣轉換為乙太幣?

  • July 1, 2017

DAO 合約於 2016 年 6 月 17 日遭到攻擊,攻擊者利用DAO 合約程式碼中的遞歸呼叫漏洞耗盡了價值約5000 萬美元的乙太幣。

攻擊者將被盜的乙太幣轉移到幾個子 DAO 中,而羅賓漢集團將剩餘的資金轉移到其他子 DAO 中。

硬分叉計劃在#1,920,000 區塊(大約 24 小時內,約 20/07/2016 澳大利亞東部標準時間 23:26)將乙太幣從 The DAO 合約及其子 DAO 轉移到提款合約中。

一旦硬分叉通過,我如何將我的 The DAO 代幣轉換為乙太幣?


DAO 退款


更新時間 2016 年 7 月 20 日 13:31 UTC

取款合約的餘額為 11,597,664.781027947 乙太幣(145,318,739.71 美元)。

一次成功的硬分叉。祝大家硬分叉快樂!開發人員和其他相關人員做得很好。

更新時間 2016 年 7 月 20 日 22:31 UTC

取款合約現在的餘額為 6,369,298.685677664 乙太幣(79,807,312.53 美元)。現在大約 45% 的 DAO 已轉換為 ETH,超過 1,506 筆交易。

更新時間 2016 年 7 月 23 日 18:04 UTC

取款合約現在的餘額為 4,595,418.245476871 乙太幣(65,944,251.82 美元)。現在大約 60% 的 DAO 已轉換為 ETH,超過 3,887 筆交易。

這是來自https://slacknation.github.io/medium/11/11.html的圖表: 在此處輸入圖像描述

更新時間 2016 年 8 月 1 日 23:18 UTC

在此處輸入圖像描述

更新時間 2016 年 9 月 6 日 14:58 UTC

剩餘 13.55% 的餘額。

在此處輸入圖像描述

2017 年 3 月 29 日更新

最新說明可在The DAO Refunds中找到。


筆記

  • 此提款合約僅允許以 100 個 DAO = 1 ETH 的比率將 The DAO 代幣 (DAO) 轉換為乙太幣 (ETH)。
  • 提款合約的編碼方式意味著您必須批准您賬戶中所有 DAO 的轉移,因為提款合約只會一次性轉移您的所有 DAO。如果你不批准你所有的 DAO 被轉移,該withdraw()函式將拋出一個錯誤,消耗交易指定的所有氣體。
  • 在 DAO 眾籌階段的最後兩週購買 DAO 的任何人每 100 個 DAO 支付超過 1 ETH。每 100 個 DAO 超過 1 ETH 的金額儲存在 The DAO 的extraBalance 帳戶中。extraBalance 賬戶的餘額現已轉入管理員的多重簽名錢包。

對於每 100 個 DAO 支付超過 1 ETH 的購買者,有一個單獨的流程可以退還已支付的額外金額(超過每 100 個 DAO 1 ETH)。此答案未涵蓋此過程,但請放心,開發人員正在盡最大努力將多餘的資金公平地分配給原始 DAO 購買者。

請參閱如何獲得我支付的超過 1 乙太幣到 100 DAO 代幣的退款,這將在進一步詳細資訊公佈時更新。

  • 如果您從 The DAO 執行了合法拆分,您的 DAO 餘額已移至子 DAO,並且您在 The DAO 中的 DAO 餘額為零。由於您在 The DAO 中的 DAO 餘額為零,因此您將無法使用本問答中的程序將您的 DAO 轉換為 ETH。

請參閱如何獲得拆分為子 DAO 的 The DAO 代幣的退款?因為您需要聯繫 TheDAOCurator 以便他們安排您的退款。

  • 在硬分叉之後等待一段時間,然後再嘗試將您的 DAO 轉換為 ETH。提款沒有最後期限。最安全的做法是等待。

更新 2016 年 10 月 26 日 06:33一些 DAO -> ETH 交易由於舍入錯誤而失敗。請參閱為什麼我的 DAO 到 ETH 退款失敗?.


提款方式一 - MyEtherWallet

  1. 訪問http://www.myetherwallet.com/#the-dao
  2. 上傳/粘貼您的 Keystore 文件/私鑰以訪問您的錢包。
  3. 按大紅色按鈕。
  4. 確認您確定要退出。
  5. 等待幾秒鐘,將出現 2 個交易連結。再等大約 30 秒,然後在 Etherscan 上檢查您的帳戶餘額。你應該有更多的 ETH 和 0 DAO。我(@tayvano)使用 MyEtherWallet 捐贈帳戶確認它在太平洋夏令時間上午 6:43 有效:http: //etherscan.io/address/0x7cb57b5a97eabe94205c07890be4c1ad31e486a8

提現方式二——乙太坊錢包

Griff Green的(循環引用的)文章How to use the Withdraw Contract with Mist提供了類似於以下說明的分步絲網印刷指南。

確保您已下載Ethereum Wallet 0.8.1或更高版本。

第一次啟動乙太坊錢包 0.8.1 時,對問題“你想啟動與漏洞相關的資金恢復到可以由 The DAO 代幣持有者提取的契約的鏈嗎?”選擇“是”。 . 您現在已經選擇使用硬分叉的乙太坊鏈。

如果 Ethereum Wallet 凍結,請參閱2016 年 7 月 23 日更新如何從 Ethereum Wallet (Mist) 監視列表中刪除 DAO 合約,因為它正在凍結?.

如果您尚未在 The DAO 合約上添加監視,請參閱The DAO - 如何添加和監視 DAO 合約。此步驟將允許您批准將 DAO 轉移到提款合約。

如果找不到下面需要的Approve函式,請使用上面的步驟重新載入 The DAO 合約的 JSON 介面。如果您在使用乙太坊錢包時遇到凍結顯示的問題,請嘗試從乙太坊錢包中移除 The DAO 合約(如何從乙太坊錢包 (Mist) 關注列表中移除 The DAO 合約,因為它正在凍結?),然後再次觀看 The DAO 合約.

在 The DAO 提款合約上添加手錶。使用與上面連結中相同的過程,但設置:

  • 契約名稱:The DAO Withdrawal
  • 合約地址:0xbf4ed7b27f1d666546e30d74d50d173d20bca754
  • JSON介面:[{"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"}]

23:47 20/07/2016 AEST - 我已確認以下使用乙太坊錢包的過程有效

批准將您的 DAO 轉移到提款合約

  1. 獲取您想要將 DAO 轉換為 ETH 的賬戶地址
  • 在 Wallet 菜單下,選擇要將 DAO 轉換為 ETH 的賬戶。
  • 點兩下帳戶地址,然後使用 Linux 或 Windows 中的 Control-C 或 MacBook 上的 Command-C 將地址複製到剪貼板。
  1. 獲取您想要將 DAO 轉換為 ETH 的賬戶餘額
  • 在合約菜單中,選擇 The DAO 合約。
  • 向下滾動到左側“從合約讀取”列下的“餘額”功能。
  • 將剪貼板中的地址粘貼到所有者地址欄位中。
  • 點兩下顯示的餘額,然後在 Linux 或 Windows 中使用 Control-C 或在 MacBook 上使用 Command-C 將餘額複製到剪貼板。
  1. 批准將您賬戶的 DAO 餘額轉移到提款合約地址
  • 在合約菜單中,選擇 The DAO 合約。
  • 在右側的 Write To Contract 列下,選擇Approve功能。
  • 使用 Linux 或 Windows 中的 Control-V 或 MacBook 上的 Command-V將剪貼板中的餘額粘貼到數量 256 位無符號整數欄位中。
  • 0xbf4ed7b27f1d666546e30d74d50d173d20bca754支出者地址欄位中輸入提款合約地址。
  • Execute from欄位下,選擇要將 DAO 轉換為 ETH 的賬戶。
  • 將發送 ETHER欄位保留為 0。
  • 點擊執行並輸入您的帳戶密碼。
  • 您應該會收到一條交易確認消息。

執行提現合約功能

  1. 從提款合約中提取 ETH
  • 在合約菜單中,選擇 The DAO 提款合約
  • 在右側的 Write To Contract 列下,選擇Withdraw功能。
  • Execute from欄位下,選擇要將 DAO 轉換為 ETH 的賬戶。
  • 點擊執行並輸入您的帳戶密碼。
  • 您應該會收到一條交易確認消息。
  • 稍等片刻,您的乙太幣餘額應該會更新。如果沒有,請重啟乙太坊錢包。

提款方式3 -geth

確保您執行的是geth1.4.10或更高版本。並使用該選項執行您的geth命令,--support-dao-fork以便您位於硬分叉區塊鏈上。例如:

geth --support-dao-fork console

--support-dao-fork設置在 的單獨執行之間保持不變geth,因此您只需指定一次此參數。

使用確認您的geth版本

user@Kumquat:~$ geth version
Geth
Version: 1.4.10-stable
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.5.1
OS: linux

這是geth用於將您的 DAO 轉換為您帳戶的 ETH的過程{x}

00:14 21/07/2016 AEST - 我已確認以下使用過程geth有效

geth --support-dao-fork --unlock {your account} console
...
Unlocking account {your account}
Passhrase: {enter your passphrase}
// Allow your blockchain to sync

> var account = "{your account}";
undefined

> var theDAOAddress = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413";
undefined

> var theDAOWithdrawalAddress = "0xbf4ed7b27f1d666546e30d74d50d173d20bca754";
undefined

> var theDAOABIFragment = [{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"type":"function"}, {"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"type":"function"}];
undefined

> var theDAO = web3.eth.contract(theDAOABIFragment).at(theDAOAddress);
undefined

> var approve = theDAO.approve(theDAOWithdrawalAddress, theDAO.balanceOf(account), {from: account});
undefined

> eth.getTransaction(approve);
// Repeat the command above until you see that blockNumber is not null

// Wait a few blocks (~ 15 seconds each) for your approve transaction to get mined

> var theDAOWithdrawalABIFragment = [{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"type":"function"}];
undefined

> var theDAOWithdrawal = web3.eth.contract(theDAOWithdrawalABIFragment).at(theDAOWithdrawalAddress);
undefined

> var withdrawal = theDAOWithdrawal.withdraw({from: account});
undefined

> eth.getTransaction(withdrawal);
// Repeat the command above until you see that blockNumber is not null

// Wait a few blocks (~15 second each) and check your new account balance
web3.fromWei(eth.getBalance(account), "ether")
11.023456789012345678

提現方式四——Mist 瀏覽器模式下的乙太坊錢包

確保您已下載Ethereum Wallet 0.8.1或更高版本。

第一次啟動乙太坊錢包 0.8.1 時,對問題“你想啟動與漏洞相關的資金恢復到可以由 The DAO 代幣持有者提取的契約的鏈嗎?”選擇“是”。 . 您現在已經選擇使用硬分叉的乙太坊鏈。退出乙太坊錢包。

現在在 Mist 瀏覽器模式下執行乙太坊錢包,使用您安裝軟體的子目錄中的以下命令:

  • 在 Linux 和 MacBook 中
./Ethereum-Wallet --mode mist & 
  • 在 Windows 中
Ethereum-Wallet --mode mist

(或者,您可以直接下載Mist 瀏覽器- 請參閱@johnmardlin下面的答案)。

然後:

  1. 確保您只選擇了用於購買“The DAO”代幣的帳戶。
  2. 在 Mist 中瀏覽到https://slacknation.github.io/medium/12/12.html
  3. 點擊“批准”,等待一個塊
  4. 點擊“退款”,等待一個塊

在此處輸入圖像描述

(根據@slacknation 在https://www.reddit.com/r/ethereum/comments/4tx13d/how_do_i_withdraw_dao_tokens_eth_after_hf_update/中的要求添加了方法 4 )


提現流程說明

將您的 DAO 轉換為 ETH 有兩個步驟。

a) 批准將 DAO 從 DAO 轉移到提款合約

第一步是批准將 DAO 從 The DAO 轉移到提款合約中。這是通過呼叫 DAO 的approve(...)函式來完成的,如下所示:

來自 The DAO 的原始碼,這裡是 TokenInterface.approve() 函式定義:

/// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
/// its behalf
/// @param _spender The address of the account able to transfer the tokens
/// @param _amount The amount of tokens to be approved for transfer
/// @return Whether the approval was successful or not
function approve(address _spender, uint256 _amount) returns (bool success);

這是實現上面定義的函式的 Token.approve(…) 函式:

function approve(address _spender, uint256 _amount) returns (bool success) {
   allowed[msg.sender][_spender] = _amount;
   Approval(msg.sender, _spender, _amount);
   return true;
}

一旦你呼叫了 The DAO 的approve(…) 函式,你就為取款合約創建了一個批准,以將你的 DAO 轉移到取款合約中。

b) 使用提款合​​約將您的 DAO 轉換為 ETH

第二步是呼叫Withdrawal合約的withdraw()函式將DAOs從The DAO轉移到Withdrawal合約中,並讓Withdrawal合約向您的賬戶發送等值的ETH。

以下是該withdraw()函式的原始碼:

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

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

資訊來源

thedao.slack.com 的使用者@lefteris表示,DAO 提現合約可以在0xbf4ed7b27f1d666546e30d74d50d173d20bca754找到,將 DAO 轉換為 ETH 的過程如下:

a) call dao.approve("0xbf4ed7b27f1d666546e30d74d50d173d20bca754", dao.balanceOf(youraccount))
b) call withdrawContract.withdraw()

提現合約源碼及地址

提款合約的原始碼可以在0xbf4ed7b27f1d666546e30d74d50d173d20bca754找到,如下:

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(0xbb9bc244d798123fde783fcc1c72d3bb8c189413);
   address public trustee = 0xda4a4626d3e16e094de3225a751aab7128e96526;

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

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

   function trusteeWithdraw() {
       trustee.send((this.balance + mainDAO.balanceOf(this)) - mainDAO.totalSupply());
   }
}

來自 The DAO 的原始碼(上面引用過),這裡是Token.transferFrom(...)函式:

function transferFrom(
   address _from,
   address _to,
   uint256 _amount
) noEther returns (bool success) {

   if (balances[_from] >= _amount
       && allowed[_from][msg.sender] >= _amount
       && _amount > 0) {

       balances[_to] += _amount;
       balances[_from] -= _amount;
       allowed[_from][msg.sender] -= _amount;
       Transfer(_from, _to, _amount);
       return true;
   } else {
       return false;
   }
}

一些進一步的參考資料

引用自:https://ethereum.stackexchange.com/questions/7204