Tokens

當 Goodies 在 Ethereum Classic 鏈上提供 ETC 退款時,我如何驗證我的 The DAO 代幣餘額是否正確?

  • July 1, 2017

從部落格文章The White Hats and DAO Wars: 幕後,Goodies 打算:

開發智能合約,用於將 ETC 分配到區塊 1,919,999 持有 DAO 代幣的地址。

更新時間 2016 年 8 月 20 日 00:57 UTC

待審核的 ETC 撤回合約中,位於 0x180826b05452ce96e157f0708c43381fee64a6b8 的DAOBalanceSnapShot合約將用於確定 DAO 代幣持有者(DTH)在硬分叉前區塊 1,919,999 的餘額。

  • Daobalance 目錄,包含 dao_balance_snapshot.sol 合約和生成數據的腳本。這是從 ETH 鏈填充的,但部署在 ETC 鏈中,並包含硬分叉時的 DAO 代幣持有者余額。該合約已經部署並填充了 ETC 鏈中 0x180826b05452ce96e157f0708c43381fee64a6b8 的數據。您可以使用 geth 中的以下介面對其進行實時測試:

var daobalancesnapshot_abi =

$$ {“constant”:true,“inputs”:[],“name”:“totalSupply”,“outputs”:[{“name”:"",“type”:“uint256”}],“type”:“function”},{“constant”:false,“inputs”:[],“name”:“seal”,“outputs”:[],“type”:“function”},{“constant”:true,“inputs”:[],“name”:“totalAccounts”,“outputs”:[{“name”:"",“type”:“uint256”}],“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”:true,“inputs”:[],“name”:“sealed”,“outputs”:[{“name”:"",“type”:“bool”}],“type”:“function”},{“inputs”:[],“type”:“constructor”} $$; var daobalancesnapshot = web3.eth.contract(daobalancesnapshot_abi).at(“0x180826b05452ce96e157f0708c43381fee64a6b8”);

daobalancesnapshot.balanceOf(YOURACCOUNTHERE);

當 Goodies 在 Ethereum Classic 鏈上提供 ETC 退款時,我如何驗證我的 The DAO 代幣餘額是否正確?

更新時間 2016 年 8 月 20 日 00:57 UTC -BigNumber用於準確計算totalSupply數字。

檢查你的 DAO 代幣餘額

要審查的 ETC 撤回契約中,geth您可以使用以下命令同步到乙太坊經典鏈,檢查硬分叉前區塊 1,919,999 處的 DAO 代幣餘額:

geth --fast --oppose-dao-fork console
// Allow the chain to sync
> var daobalancesnapshot_abi = [{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"seal","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"totalAccounts","outputs":[{"name":"","type":"uint256"}],"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":true,"inputs":[],"name":"sealed","outputs":[{"name":"","type":"bool"}],"type":"function"},{"inputs":[],"type":"constructor"}];
undefined
> var daobalancesnapshot = web3.eth.contract(daobalancesnapshot_abi).at("0x180826b05452ce96e157f0708c43381fee64a6b8"); 
undefined
> daobalancesnapshot.balanceOf(YOURACCOUNTHERE);
123456

或者,您可以在 theDAOTokenBalance_20160819_155742UTC_balance.xlsx 中驗證區塊 1,919,999 處的 DAO 代幣餘額。您可能必須點擊滑鼠右鍵 -> 將連結另存為才能將電子表格下載到您的電腦。


檢查所有 DAO 代幣餘額

腳本getTheDAOTokenBalance查找CreatedToken與The DAO 事件相關的所有地址,並根據 The DAO 的函式 AT 塊 1,919,999Transfer查詢每個地址。balanceOf(...)

該腳本還將此結果與位於0x180826b05452ce96e157f0708c43381fee64a6b8 (此處帶有 ABI )處的DAOBalanceSnapShot合約進行核對,Goodies 打算使用該合約來確定每個地址在第 1,919,999 塊處擁有的 DAO 代幣的數量。

結果是,與 Goodies 的合約相比,我的腳本為每個地址計算了相同數量的 The DAO 代幣,DAOBalanceSnapShot並且總數相同。

github.com/bokkypoobah/TheDAOETCTokenBalance上有一個總結。您可以在 DAOTokenBalance_20160819_155742UTC_creation.txt 中找到所有CreatedToken事件,在DAOTokenBalance_20160819_155742UTC_transfer.txt中找到所有事件,以及TransferDAOTokenBalance_20160819_155742UTC_balance.txtDAO_ls915742UTC_balance.txt中找到第 1,919,999塊的所有餘額。

我的腳本總共找到 22,092 個非零賬戶,總共 1,153,816,598.7024671407837618 個 DAO。我的腳本查詢 Goodies 的DAOBalanceSnapShot合約並找到相同的 DAO 總數。該 DAOBalanceSnapShot合約有一個totalSupply屬性,返回值 11538165987024671407837618 或 1,153,816,598.7024671407837618 DAO。Goodies 的DAOBalanceSnapShot合約準確地表示了 DTH 在硬分叉前區塊 1,919,999 的賬戶餘額。

totalSupply()在硬分叉前的區塊 1,919,999 處檢查 DAO,geth確認總供應量。

> var theDAOABIFragment = [{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"type":"function"}];
undefined
> var theDAOAddress = "0xbb9bc244d798123fde783fcc1c72d3bb8c189413"
undefined
> var theDAO = web3.eth.contract(theDAOABIFragment).at(theDAOAddress);
undefined
> theDAO.totalSupply(1919999).toString(10);
"11538165987024671407837618"

劇本

要使用以下腳本,您必須使用geth --oppose-dao-fork console. 請注意,您不能使用該--fast參數,因為這將排除debug.traceTransaction(...)API 查詢所需的中間結果,以確定令牌創建所涉及的正確地址。該腳本將需要半天以上的時間來執行,具體取決於您的處理器和磁碟的速度。

腳本getTheDAOTokenBalance如下:

#!/bin/sh
# ------------------------------------------------------------------------------
# Retrieve The DAO Creation and Transfer events, collecting addresses. Then 
# retrieve the pre-hard-fork balances and the current balances for these 
# addresses.
#
# v2 improvements
# * Summing totals as BigNumbers instead of floats
# * Only including non-zero balances at block 1919999 in counter
#
# Usage:
#   1. Download this script to getTheDAOTokenBalance .
#   2. `chmod 700 getTheDAOTokenBalance`
#   3. Run `geth console` in a window.
#   4. Then run this script `./getTheDAOTokenBalance` in a separate window.
#
# Enjoy. (c) BokkyPooBah 2016. The MIT licence.
# ------------------------------------------------------------------------------

DATE=`date -u +%Y%m%d_%H%M%S`
OUTPUT=theDAOTokenBalance_${DATE}UTC_all.txt
CREATION=theDAOTokenBalance_${DATE}UTC_creation.txt
TRANSFER=theDAOTokenBalance_${DATE}UTC_transfer.txt
BALANCE=theDAOTokenBalance_${DATE}UTC_balance.txt

geth attach << EOF | egrep "^Header|^Data|^Stats|^Footer" > $OUTPUT
var theDAOABIFragment = [{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"type":"function"}, {"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"CreatedToken","type":"event"}, {"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"}];
var theDAOAddress = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413";
var theDAO = web3.eth.contract(theDAOABIFragment).at(theDAOAddress);

var theDAOTokenBalancePreHardForkABI = [{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"seal","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"totalAccounts","outputs":[{"name":"","type":"uint256"}],"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":true,"inputs":[],"name":"sealed","outputs":[{"name":"","type":"bool"}],"type":"function"},{"inputs":[],"type":"constructor"}];
var theDAOTokenBalancePreHardForkAddress = "0x180826b05452ce96e157f0708c43381fee64a6b8";
var theDAOTokenBalancePreHardForkContract = web3.eth.contract(theDAOTokenBalancePreHardForkABI).at(theDAOTokenBalancePreHardForkAddress);

// The DAO created in block 1428757 Apr-30-2016 01:42:58 AM +UTC
var creationStartBlock = 1428757;
// First The DAO creation event with non-zero extraBalance in block 1520861 May-15-2016 09:00:16 AM +UTC
var creationWithExtraBalanceStartBlock = 1520861;
// Last The DAO creation event in block 1599205 May-28-2016 08:59:47 AM +UTC
var creationEndBlock = 1599205;
// First The DAO transfer event in block 1599207 May-28-2016 09:00:07 AM +UTC, but use block above
var transferStartBlock = creationEndBlock + 1;
// Last The DAO transfer
var transferEndBlock = eth.blockNumber;
// Pre hard-fork block
var preHardForkBlock = 1919999;
// Hard-fork block
var hardForkBlock = 1920000;

// Collect addresses
var addresses = {};

// --- Get creation events ---
var startBlock = creationStartBlock;
var endBlock = creationEndBlock;

// Testing
// startBlock = creationWithExtraBalanceStartBlock - 5;
// endBlock = creationWithExtraBalanceStartBlock + 5;

var theDAOCreatedTokenEvent = theDAO.CreatedToken({}, {fromBlock: startBlock, toBlock: endBlock});
console.log("HeaderCreation\tTokenOwner");
var i = 0;
theDAOCreatedTokenEvent.watch(function(error, result) {
 addresses[result.args.to] = 1;
 i = i + 1;
 console.log("DataCreation\t" + i + "\t" + result.args.to);
});

// --- Get transfer events ---
var startBlock = transferStartBlock;
var endBlock = transferEndBlock;

// Testing
// startBlock = transferStartBlock;
// endBlock = transferStartBlock + 10;

var theDAOTransferEvent = theDAO.Transfer({}, {fromBlock: startBlock, toBlock: endBlock});
console.log("HeaderTransfer\tFrom\tTo");
i = 0;
theDAOTransferEvent.watch(function(error, result) {
 addresses[result.args._from] = 1;
 addresses[result.args._to] = 1;
 i = i + 1;
 console.log("DataTransfer\t" + i + "\t" + result.args._from + "\t" + result.args._to);
});

// --- Get balances ---
var currentBlock = transferEndBlock;

console.log("HeaderBalance\tNumber\tAddress\tPreHardForkDAO\tPreHardForkDAOContract\tPreHardForkDAODiff\tCurrentDAO\tChangeDAO\tPreHardForkETH\tCurrentETH\tChangeETH");
var daosPreHardForkTotal = new BigNumber(0);
var daosPreHardForkContractTotal = new BigNumber(0);
var daosCurrentTotal = new BigNumber(0);
var nonZeroAccounts = new BigNumber(0);
i = 0;
for (var address in addresses) {
 i = i + 1;
 var checkAddress = "0xda0031fab25270778386a2dcac0bb934a288c464";
 var daosPreHardFork = theDAO.balanceOf(address, preHardForkBlock);
 var daosPreHardForkContract = theDAOTokenBalancePreHardForkContract.balanceOf(address);
 var daosPreHardForkDiff = daosPreHardFork - daosPreHardForkContract;
 var daosCurrent = theDAO.balanceOf(address, currentBlock);
 if (daosPreHardFork != 0 || daosPreHardForkContract != 0) {
   nonZeroAccounts++;
 }
 var daosChange = daosCurrent - daosPreHardFork;
 var ethsPreHardFork = eth.getBalance(address, preHardForkBlock);
 var ethsCurrent = eth.getBalance(address, currentBlock);
 var ethsChange = ethsCurrent - ethsPreHardFork;
 daosPreHardForkTotal = daosPreHardForkTotal.plus(daosPreHardFork);
 daosPreHardForkContractTotal = daosPreHardForkContractTotal.plus(daosPreHardForkContract);
 daosCurrentTotal = daosCurrentTotal.plus(daosCurrent);
 console.log("DataBalance\t" + i + "\t" + address + "\t" + 
   (daosPreHardFork/1e16).toFixed(16) + "\t" + (daosPreHardForkContract/1e16).toFixed(16) + "\t" + (daosPreHardForkDiff/1e16).toFixed(16) + "\t" + 
   (daosCurrent/1e16).toFixed(16) + "\t" + (daosChange/1e16).toFixed(16) + "\t" + 
   (ethsPreHardFork/1e18).toFixed(18) + "\t" + (ethsCurrent/1e18).toFixed(18) + "\t" + (ethsChange/1e18).toFixed(18));
}

console.log("Stats\tnonZeroAccounts\t" + nonZeroAccounts);
console.log("Stats\tdaosPreHardForkTotal\t" + daosPreHardForkTotal.toPrecision(30) + "\t" + (daosPreHardForkTotal/1e16).toFixed(16));
console.log("Stats\tdaosPreHardForkContractTotal\t" + daosPreHardForkContractTotal.toPrecision(30) + "\t" + (daosPreHardForkContractTotal/1e16).toFixed(16));
console.log("Stats\tdaosCurrentTotal\t" + daosCurrentTotal.toPrecision(30) + "\t" + (daosCurrentTotal/1e16).toFixed(16));

console.log("Footer\tReport generated at " + (new Date()).toGMTString() + " with latest block number " + transferEndBlock);

EOF

egrep "HeaderCreation|DataCreation|Footer" $OUTPUT > $CREATION
egrep "HeaderTransfer|DataTransfer|Footer" $OUTPUT > $TRANSFER
egrep "HeaderBalance|DataBalance|Footer|Stats" $OUTPUT > $BALANCE

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