I want to simulate the DAO recursive attack. Can you please define the steps for simulating the attack with Truffle using the TestRPC.
-
This is a good example of how to DAO exploit works ethernaut.zeppelin.solutions/level/…– Daniel Luca CleanUnicornCommented Mar 9, 2018 at 19:10
-
@cleanunicorn add this as answer please.– ivicaaCommented Mar 9, 2018 at 19:16
-
I've added the link as an answer with an explanation– Daniel Luca CleanUnicornCommented Mar 9, 2018 at 19:41
2 Answers
- Create your contract
DAOHack.sol
and save it in contracts folder. - Create
2_deploy.js
migration file and store it in migrations folder. - Specify network parameters in
truffle.js
. - Compile contracts by running
truffle compile
. - Run
ganache-cli
on the port specified intruffle.js
. - 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
.
-
its not working correctly. also there are many changes that we need to do for deploying the contract. Commented Mar 27, 2018 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)()) {
_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 calldonate()
with Ether value. This value will be saved for your address - Have a default payable function that calls
withdraw()
again - Call
withdraw()
function onReentrance
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.