I want to simulate the DAO recursive attack. Can you please define the steps for simulating the attack with Truffle using the TestRPC.

  1. Create your contract DAOHack.sol and save it in contracts folder.
  2. Create 2_deploy.js migration file and store it in migrations folder.
  3. Specify network parameters in truffle.js.
  4. Compile contracts by running truffle compile.
  5. Run ganache-cli on the port specified in truffle.js.
  6. Deploy contracts to test network by running: truffle migrate.

If you will need any address of smart contracts later you can copy them on this step.

Next you can either make a test or create small app.

  • In case of test you will have to create your test and just run truffle test test/DAOHack.js.
  • It would be too broad to describe how to create app, cutting to the chase, when the app is ready you will just run your server like lite-server.

For more detailed explanation consider diving into Truffle docs.

Note that TestRPC is now Ganache-cli.

| improve this answer | |
  • its not working correctly. also there are many changes that we need to do for deploying the contract. – anand011090 Mar 27 '18 at 12:56

A very good proof of concept of how the DAO hack works is this https://ethernaut.zeppelin.solutions/level/0xf70706db003e94cfe4b5e27ffd891d5c81b39488

There are a few steps how to reproduce this.

You need a contract like this one

pragma solidity ^0.4.18;

contract Reentrance {

mapping(address => uint) public balances;

function donate(address _to) public payable {
    balances[_to] += msg.value;

function balanceOf(address _who) public constant returns (uint balance) {
    return balances[_who];

function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
    if(msg.sender.call.value(_amount)()) {
    balances[msg.sender] -= _amount;

function() payable {}

Then you need to create an contract account that will send funds to Reentrance contract. This will be your point of exploit.

Your contract needs to be able to:

  • Send funds to Reentrance, specifically call donate() with Ether value. This value will be saved for your address
  • Have a default payable function that calls withdraw() again
  • Call withdraw() function on Reentrance

Having the default payable function that calls withdraw() creates an infinite loop. It is an infinite loop but it stops when the whole gas is used up. So the more gas you send, the more loops is able to iterate, thus withdraw more funds.

Because the gas is finished the balance is never updated, but the Ether remains sent.

| improve this answer | |

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