Here is the original blog post from Peter Vessenes that described the recursive calling vulnerability in DAOs : [More Ethereum Attacks: Race-To-Empty is the Real Deal](http://vessenes.com/more-ethereum-attacks-race-to-empty-is-the-real-deal/), with suggested remediation for this problem. From the post: > **The Vulnerability** > Here is some code; see if you can find the problem. > function getBalance(address user) constant returns(uint) { > return userBalances[user]; > } > > function addToBalance() { > userBalances[msg.sender] += msg.amount; > } > > function withdrawBalance() { > amountToWithdraw = userBalances[msg.sender]; > if (!(msg.sender.call.value(amountToWithdraw)())) { throw; } > userBalances[msg.sender] = 0; > } > Here's the problem: msg.sender might have a default function that looks like this. > function () { > // To be called by a vulnerable contract with a withdraw function. > // This will double withdraw. > > vulnerableContract v; > uint times; > if (times == 0 && attackModeIsOn) { > times = 1; > v.withdraw(); > > } else { times = 0; } > } > What happens? The call stack looks like this: > vulnerableContract.withdraw run 1 > attacker default function run 1 > vulnerableContract.withdraw run 2 > attacker default function run 2 > Each time, the contract checks that the user's withdrawable balance and sends it out. So, the user will get twice their balance out of the contract. > When the code resolves, the user's balance will be set to 0 however many times the contract was called. And the suggested remediations, from the post: > **Remediation Approach 1: Get Your Ordering Correct** > The recommended approach in the soon to be published upgraded solidity examples is to use code like this: > function withdrawBalance() { > amountToWithdraw = userBalances[msg.sender]; > userBalances[msg.sender] = 0; > if (amountToWithdraw > 0) { > if (!(msg.sender.send(amountToWithdraw))) { throw; } > } > } and > **Remediation Approach 2: Mutexes** > > Consider this code instead. > > function withdrawBalance() { > if ( withdrawMutex[msg.sender] == true) { throw; } > withdrawMutex[msg.sender] = true; > amountToWithdraw = userBalances[msg.sender]; > if (amountToWithdraw > 0) { > if (!(msg.sender.send(amountToWithdraw))) { throw; } > } > userBalances[msg.sender] = 0; > withdrawMutex[msg.sender] = false; > } <br /> --- And from the post by user [eththrowa](https://forum.daohub.org/users/eththrowa) in The DAO forum post [Bug discovered in MKR token contract also affects theDAO - would allow users to steal rewards from theDAO by calling recursively](https://forum.daohub.org/t/bug-discovered-in-mkr-token-contract-also-affects-thedao-would-allow-users-to-steal-rewards-from-thedao-by-calling-recursively/4947): > This bug: > https://www.reddit.com/r/ethereum/comments/4nmohu/from_the_maker_dao_slack_today_we_discovered_a/57 > Is also present in theDAO code - specifically here in the withdrawRewardFor function DAO.sol: > > if (!rewardAccount.payOut(_account, reward)) > throw; > paidOut[_account] += reward; > return true; > > and here in managedAccount.sol > > 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; > } > } > > This would allow a user to drain many times his entitlement by calling the contract recursively. Oddly enough the slockit team spotted this bug here in the proposal section: > > // we are setting this here before the CALL() value transfer to > // assure that in the case of a malicious recipient contract trying > // to call executeProposal() recursively money can't be transferred > // multiple times out of the DAO > p.proposalPassed = true; > > but missed it in the reward section.Obviously there are not yet any rewards in theDAO so this is not an issue that could cost money today. <br /> --- **Q**: When creating smart contracts, DAOs or DAPPs, what measures can I take to ensure I am not vulnerable? Test, audit, test, audit, ... . As with any software systems, there are many potential areas where bugs can creep in. And the higher value it holds, the more interest attackers will have in it. From the Ethereum blog [CRITICAL UPDATE Re: DAO Vulnerability](https://blog.ethereum.org/2016/06/17/critical-update-re-dao-vulnerability/): > Contract authors should take care to (1) be very careful about recursive call bugs, and listen to advice from the Ethereum contract programming community that will likely be forthcoming in the next week on mitigating such bugs, and (2) avoid creating contracts that contain more than ~$10m worth of value, with the exception of sub-token contracts and other systems whose value is itself defined by social consensus outside of the Ethereum platform, and which can be easily “hard forked” via community consensus if a bug emerges (eg. MKR), at least until the community gains more experience with bug mitigation and/or better tools are developed. The reddit thread [Can we please never again put 100m in a contract without formal correctness proofs?](https://www.reddit.com/r/ethereum/comments/4oimok/can_we_please_never_again_put_100m_in_a_contract/) suggest some formal correctness proof (but there can still be bugs). There will be more advisories coming out in the next few weeks - I'll update this answer. Some resources: * [Scanning Live Ethereum Contracts for the "Unchecked-Send" Bug](http://hackingdistributed.com/2016/06/16/scanning-live-ethereum-contracts-for-bugs/) (from `@Roland Kofler`'s answer in [How did “the DAO” attack happen on 17 June 2016?](http://ethereum.stackexchange.com/a/6192/1268)). * [Thoughts on The DAO Hack](http://hackingdistributed.com/2016/06/17/thoughts-on-the-dao-hack/) (also from `@Roland Kofler`'s answer in [How did “the DAO” attack happen on 17 June 2016?](http://ethereum.stackexchange.com/a/6192/1268)).