Skip to content

Security: dax-classix/Rouleth

Security

Security.md

#Contract Security : www.rouleth.com

Following the DAO hack, ethereum users have realized that the security of smart contracts is something that should not be taken lightly. The hack of the DAO was performed due to a flaw in the smart contract and is not at all a bug of ethereum. The rouleth contract incorporates several security features that makes it secure against several potential attacks on smart contracts that have been identified by the community. I will list those potential threats below and explain how I secured the contract against them.

1) Recursive call attack : (DAO ATTACK) http://vessenes.com/more-ethereum-attacks-race-to-empty-is-the-real-deal/ The attacker exploits the fact that when a contract sends ether to another contract it also executes the code in the destination contract. If the destination contract is malicious, it could try to ask the first contract to send the money again. If the first contract does not update the balances before sending, the attacker is allowed to withdraw several times a single amount. The rouleth code is immune to such attack for several reasons. First of all, all balances are updated before the money is sent. So even if the attacker was able to call the rouleth contract again for a second reccursive withdraw, he will not be able to withdraw more than his total balance. Second, since we use basic send() functions in the rouleth contract (and not call() like in the DAO), the rouleth would not send enough gas to the attacker contract, so the attacker will not be able to execute the rouleth functions again. Third and most importantly, we always check if the player/investor is allowed to call the function before we allow him to. So for instance a player that tries to spin the wheel recursively, to win multiple time his payout for the same bet, would not be allowed to. When a player spins the wheel the first time, the contract changes the progress of this user from "waitingForSpin" to "waitingForBet" and since the spinTheWheel function always check that the user is indeed waitingForSpin, he will not be able to call it a second time.

2) Silent failing sends : call stack attacks

http://martin.swende.se/blog/Devcon1-and-contract-security.html There is a limit specifying how deep contracts can call other contracts; currently set to 1024. If a contract invokes another contract (either via CALL or CALLCODE), the operation will fail if the call stack depth limit has been reached. The failure is signalled to the caller by putting a 0 on the stack (the regular stack). This behaviour makes it possible to subject a contract to a “call stack attack”. In such an attack, an attacker first creates a suitable depth of the stack, e.g. by recursive calls. After this step, the attacker invokes the targeted contract. If the targeted calls another contract, that call will fail. If the return value is not properly checked to see if the call was successfull, the consequences could be damaging. For instance, if the Rouleth was vulnerable to this threat, when the investor array is full and a new investor wants to buyout a previous investor, this new investor could devise a call stack attack to make the send to the previous investor fail. The previous investor money would stay (and be stucked) in the rouleth but the previous investor would be erased from the investors list. This would however not benefit the attacker since he could not withdraw the amount. In any case, I have used a method of safe send using the following code " if (previous.send(balance[previous])==false) throw; " . This code would cancel the whole transaction if an attacker were to try such an attack. If the send to the previous investor fails, this calls a "throw" which reverts the whole operation (the investor that was supposed to be buyout would not be and would still be in the investor list with the ability to withdraw his/her funds).

3) Griefing attacks : http://vessenes.com/ethereum-griefing-wallets-send-w-throw-considered-harmful/ The previous threat and the solution we implemented (using if ( .send(balance[previous])==false) ) could however expose the contract to an other vulnerability. A failed send reverts the whole transaction. One could invest in the rouleth from a contract that makes any send to its address fail. If the execution of the whole contract was dependent on this send, the whole contract would be stalled and investors could not withdraw because of this investor's griefing wallet. However the Rouleth is immune to this attack because every investor can withdraw their funds individually and don't trigger transactions to other users. So in the case of such an attack, only the attacker would loose funds and the rest of the contract would keep running as before. The only benefit that an attacker could have through this method is that he could secure himself an investor seat in the casino by causing any buyout attempt to fail. But I have the ability to increase the array of investors if needed and allow more investor to come in. Also this small potential benefit would not harm the casino in any ways, since balances, withdraws, investments and plays would not be affected.

4) Stalled contracts : (Governmental Fail)

https://www.reddit.com/r/ethereum/comments/4ghzhv/governmentals_1100_eth_jackpot_payout_is_stuck/ In the Ethereum Virtual Machine, we pay transaction fees (gas) for any computation the contract code runs. There is a limit of currently a bit less than 5Million per block. Hence if the contract has to execute more computations than that, it will not be able to work anymore and be stalled. When he designs a smart contract, the developper must be sure that his contract can scale. Operations that are at first rather inexpensive (such as reading a list of players of 2 elements) can become very expensive when there are many users (ex. the same player list can now be composed of 1000 elements). So from the start, the developper has to create contract mechanics that scale well to avoid such computationnal cost growth. In the Rouleth, we have decentralized the execution of the code and every player has to make the computation for his play only. The gas cost of playing should remain the same no matter how many players played before you. Only 2 features of the contracts are more gas expensive and require the use of a list of elements. To avoid any scaling problem, I have thus made sure that these lists will always be short enough such that the maximum possible list will still be short enough to execute within the gas per block limits. The first of these 2 features is the investor array. We have to keep a list of all investors in the rouleth in order to share profits and losses in the right maner. We could have used a token system with an ICO, but the Rouleth implements a dynamic investment mechanism where you can join, leave, and join again at (almost) any time. For this purpose we keep track of the profit and losses and when there is a change in the investor structure, we update all investors balances using the list of investors. To avoid any problem of gas for this operation, the list of investor is currently limited to 50 elements and can be extended up to 150. This way we will always be under the gas limits per block. The second feature that requires some loop over a list of elements is the resolution of expired gambles when the player does not spin the wheel in the imparted time of 200 blocks currently. However because of the limit of 200 blocks (which can be lowered if needed) we can make sure that the number of gambles we have to scan will always be small enough in terms of gas costs.

#Additional security measures and failsafe counter-measures : That's it for the list of known and important issues. If more were to be found, I will scan the contract immediatly to make sure it's not vulnerable to them. A few failsafe measures have been implemented in the contract to be able to secure the funds preemptively at any time.We can use the disable betting function to stop the contract if there was some kind of potential cheating or hacking via the playing functions. If the investment/withdraw functions were at risk, I can also set the lockPeriod to 0, such that any investor can withdraw their funds from the contract immediately. In such a case investors will have to withdraw their funds quickly before someone tries to use the potentially discovered exploit. The same measures could be use at any time to counter any potential exploit.

The contract has been extensively tested and reviewed by several developpers and security experts. However, no true security audit has been performed and even if it was the case, Ethereum remains a new platform and there is always a risk of unintended consequences as the DAO hack showed recently.

If you choose to invest in the Rouleth, please remember that you will be pioneering the potential of ethereum blockchain and this can not be considered at all as a sure investment. Review the code if possible and invest under your own responsability. Thanks for your support.

Any questions, concerns, comments and criticizisms ? Contact me : whysos3rious at whysos3rious dot com

www.rouleth.com

There aren’t any published security advisories