Feel free to ask questions or discuss below!
Itās instructive to replicate the DAO hack, thanks for the example.
One critical concept that I overlooked is the fact that the Attacker contract has to have a balance in the DAO contract which is accomplished by using the Attacker.payMe() function call when setting things up. It wouldāve been more clear to me to name it say Attacker.contribute() to reiterate that the attacker contract is obtaining a balance in the DAO with itās address so it can successfully pull off the hack.
On the DAO hacks section I didnāt know if you were going to include the code, like Iāve seen Filip do, so I started coding the contract from scratch as you did and that was educational on itās own. I made a couple mistakes, one was not including payable on the anonymous function of the Attacker contract which was the hardest to trouble shoot, but it a learning experience to make it work like it should.
Great demonstration of DAO hack, thank you!
What is going in my mind is what basically happen if sending of Ether somehow fails
but balance was already set to 0. Does in this case contract trying to retrieve Ether is left without money,
because balance was set to 0, but transaction has failed?
Iām trying to create this case, but I canāt find the way to make transaction fail,
but surely in real world scenario this can happen.
RE: library freeze attack
One thing that wasnāt discussed is how the contract using the library could have protected itself from this vulnerability. Drawing from what Filip talked about in the last section, instead of hard coding the library address you could use the Proxy pattern.
I fiddled around with this concept a bit, but it seems the proxy pattern is a bit more complicated than the following- which complies but fails when the function is called. Iām guessing it doesnāt like redefining the lib variable.
// constructor
function Fundraiser(address libAddress) {
lib = Library(libAddress);
}
// allow the owner to point the library to a different address if needed
function initLibrary(address addr) onlyOwner {
lib = Library(addr);
}
An internet search for articles on the proxy pattern revealed something rather complicated using ādelegatecallā:
@ivan The solution you give to prevent the hack is missing one little thing:
You reset the balance of the sender from the mapping without storing it into a local variable, and therefore will then send 0 wei to the sender, even if his balance wasnt 0, because you are accessing the mapping after setting its value to 0.
Correct, just noticed that as well when I saw the video
I was wondering how to withdraw funds from the Fundraiser using the other addresses? I get error when trying to withdraw. How to withdraw inital deposit for each address?
I think the contract reverts if it fails so that the balance reverts to the previous balance not zeroā¦ I havenāt looked at the code, but I think thatās how that works.
How I am able to prevent the parity hack? Just use a constructor with setting adress owner=msg.sender ? This would be enough or?
In the parity hack the initialize function was the problem so without checking if the owner is calling this function you will still have an issue.
You should
initializing the library.
Creating a boolean to check if the init function has already been called or making it only accessible by the owner of the contract.
Making the init function internal.
or not creating a kill() function for a library were two ways to avoid this āāhackāā ^^
Agree I think the video should be slightly updated to show correct way how to fix the hack @ivan @filip @gabba
Otherwise great job with the demonstration!
I noticed this as well. Apparently, the solution in the video is still flawed today.
As others have noted. The video āDAO Hack - Replicating the Vulnerability Part 2ā correctly shows the attack, but the solution provided is incorrect since you are setting balances[msg.sender]=0 and then you send the value of balances[msg.sender which you have just made 0.
wrong
balances[msg.sender] = 0;
msg.sender.call.value(balances[msg.sender])();
fixed
uint balanceAmount = balances[msg.sender];
balances[msg.sender] = 0;
msg.sender.call.value(balanceAmount])();
So basically the DAO hack could be prevented if the balance was updated to zero first before sending ether? Awww that sucks
Nice section! Very informative!
could be prevented if the balance was updated to zero first before sending ether?
That is correct, keep that in mind
Happy learning,
Dani
Regarding the library freeze, can we use a constructor to set the owner initially and then just remove the initOwner()
? Would that fix the issue
Hi, in the DAO hack, @ivan
1- I didnāt understand how this : Fundraiser(fundraiserAddress).contribute.value(msg.value)() ; works,
I know that it will contribute money to the fundraiser but I donāt understand how it does that , it looks strange .
2- Here :
balances[msg.sender] = 0;
msg.sender.call.value(balances[msg.sender])();
This sounds incorrect , it should use for example :
uint amount = balances[msg.sender];
balances[msg.sender] = 0;
msg.sender.call.value(amount)();
3- I do not understand how an attacker can modify the fundraiser smart contract by adding this function:
function getFunds() returns (uint){
return address(this).balance;
}
if an attacker is able to modify the contract, this means that he can make modifications to make it insecure and then , he can attack it .
Regarding the topic of dependencies, Ivan was explaining about the removal of a dependent library which in turn, the smart contract using it, all of a sudden is not working.
In Android, any java programs or I believe in Node.js, if you have a dependent library, it will automatically download it, include or package it to your app. So if someone deleted it from the repository(or github), you app will not be affected and will still work, right?
So does it mean that solidity will always rely on that repository on where your dependent resides because it is not downloading it as part of the package?
So to be sure your smart contract will always work, you must have a copy of that library locally and part of your smart contract.
Does my question makes sense?