3 ms·
I guess it would be more responsible to report the bug to the contract author first. Perhaps they will let you take it as a reward, and you'll sleep better at n
by flashmob 9y ago
I guess it would be more responsible to report the bug to the contract author first. Perhaps they will let you take it as a reward, and you'll sleep better at night and won't have a moral dilemma ;-)
Seriously though, nice find. What would be a way to defend against this?
- AgentME 9y agoThe main article mentions some defenses. Never immediately determine whether or not the user wins; the basic idea of a transaction that immediately within the block results in win or lose has to be thrown out the door. Instead, roulette-type contracts always must have the user pay in as one transaction, let the user at a later block check if they won, and then let the user withdraw any winnings in a separate transaction. An easy and pretty good way to do this is to record the block number they make their deposit, and then have the question of whether they win or lose be calculated from the hash of the block some fixed N blocks after their deposit. There are certain attacks by miners that are possible to try to force a win, but the attacks require the miners to forfeit mining rewards for blocks they calculate where they lose, and unless N is small enough for an attacker to try to generate the whole chain of deposit-wait-then-withdraw blocks, or the entire network is working together, it's likely that a different miner will create a block first and interrupt any miner trying to bruteforce a winning block. So if the winnings are under the size of the block reward amount, there's basically zero danger, and the danger is tiny unless the winnings are ridiculous. ... I hadn't thought about how possible future proof-of-stake schemes affect this though. Those might be fatal to this strategy on second thought, since it might be easy for a staker to try out many block variations. I'm not too familiar with this detail of PoS schemes though. Another common solution involves active oracles and commit-then-reveal schemes, but they generally require the oracle to be honest, or else the oracle could participate in the lottery and force its own win. There are common ways that oracles try to show their own good behavior, so people can notice if they cheat and stop depending on them. As long as it's more profitable for the oracle to continue operating than to cheat a roulette and then be shunned, things work out.
- flashmob 9y agoThanks for the explanation. Good point about staking, assuming if the validator is chosen before, then they are certain to get the chance to order the transactions in their favour. The article, as I understood, the caller predicts the outcome of the 'random' function first, and then calls if the result is favourable. It seems like yours is more efficient, as it relies on using revert() to undo all state changes, if the outcome was unfavourable, so no need to predict anything!
- AgentME 9y agoI originally considered making my contract predict the outcome of the 'random' function first, but I got lazy when I realized I could just check whether I won and revert the transaction afterward for the specific contracts I wanted to attack. It also meant that my win-forcer contract was more generic and could work against more naive roulette contracts. However, my strategy would not work against naive roulette contracts that immediately on deposit calculate whether you won, but don't tell you or let you get the money until later. (I didn't encounter any like that, but it's a possible flawed way someone might attempt to make their contract defend against attacks.) To attack those, you would need to do the article's strategy of predicting the 'random' outcome first before making the deposit (or have your win-forcer contract automatically check the random outcome for you, and only make the deposit if it knows you'll win).