4

From the blog post The White Hats and DAO Wars: Behind the Scenes, the Goodies intend to:

develop the smart contracts that will be used to distribute ETC to the addresses holding DAO Tokens at block 1,919,999.


Update 00:57 Aug 20 2016 UTC

From ETC withdraw contract to be reviewed, the DAOBalanceSnapShot contract at 0x180826b05452ce96e157f0708c43381fee64a6b8 will be used to determine The DAO Token Holder's (DTH) balances at pre-hard-fork block 1,919,999.

  • Daobalance directory, containing the dao_balance_snapshot.sol contract and the script that generates the data. This is populated from the ETH chain but is deployed in the ETC chain and contains the DAO Token Holder balances at the time of the hard fork. This contract is already deployed and filled with data in the ETC chain at 0x180826b05452ce96e157f0708c43381fee64a6b8. You can test it live using the following interface in 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);


How can I verify that my The DAO token balance is correct when the Goodies provide an ETC refund on the Ethereum Classic chain?

6

Updated 00:57 Aug 20 2016 UTC - using BigNumber to accurately compute the totalSupply figures.

Checking Your The DAO Token Balance

From ETC withdraw contract to be reviewed you can check your The DAO token balance at pre-hard-fork block 1,919,999 using geth synced to the Ethereum Classic chain using the following commands:

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


Alternatively, you can verify your The DAO token balances at block 1,919,999 in theDAOTokenBalance_20160819_155742UTC_balance.xlsx. You may have to right mouse click -> Save Link As to download the spreadsheet to your computer.



Checking All DAO Token Balances

The script getTheDAOTokenBalance finds all addresses involved in the CreatedToken and Transfer The DAO events and queries each of these addresses against The DAO's balanceOf(...) function, AT block 1,919,999.

The script additionally reconciles this results against the DAOBalanceSnapShot contract at 0x180826b05452ce96e157f0708c43381fee64a6b8 (with ABI here) that the Goodies intend to use to determine the number of The DAO tokens each address owns at block 1,919,999.

The results are that my script calculate the same number of The DAO tokens for each address compared to the Goodies' DAOBalanceSnapShot contract and the totals are the same.

There is a summary at github.com/bokkypoobah/TheDAOETCTokenBalance. You can find all the CreatedToken events in theDAOTokenBalance_20160819_155742UTC_creation.txt, all the Transfer events in theDAOTokenBalance_20160819_155742UTC_transfer.txt and all balances at block 1,919,999 in theDAOTokenBalance_20160819_155742UTC_balance.txt and theDAOTokenBalance_20160819_155742UTC_balance.xlsx.

My script finds a total of 22,092 non-zero accounts with a total of 1,153,816,598.7024671407837618 DAOs. My script queries the Goodies' DAOBalanceSnapShot contract and finds the same DAO total. The DAOBalanceSnapShot contract has a totalSupply attribute that returns the value 11538165987024671407837618 or 1,153,816,598.7024671407837618 DAOs.The Goodies' DAOBalanceSnapShot contract accurately represent the balances of DTH's accounts at the pre-hard-fork block 1,919,999.

And checking theDAO's totalSupply() at pre-hard-fork block 1,919,999 using geth confirms the total supply figure.

> 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"



The Script

To use the following script, you will have to download the Classic blockchain using geth --oppose-dao-fork console. Note that you cannot use the --fast parameter as this will exclude the intermediate results required for the debug.traceTransaction(...) API query required to determine the correct addresses involved in the token creation. The script will take over half a day to execute, depending on the speed of your processor and disk.

The script getTheDAOTokenBalance follows:

#!/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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.