Building An Ethereum-based Decentralized casino: How I Did It

Written by seniorjoinu | Published 2021/02/15
Tech Story Tags: ethereum | solidity | gambling | we-building | solidity-top-story | how-to-build-a-casino | decentralized-casino-code | hackernoon-top-story

TLDR There is no project out there that offers a simple experience like connect a wallet -> place a bet on some random number, without any kind of "login with Google" or "100 free spins" No one should be ever able to get an advantage of the casino to increase their chance of winning. Decentralized casinos can't do things the same way - they should be fair. If your casino has weak randomness, your prize fund will be stolen, because it is defined to be undetermined. Centralized casinos don't have randomness - they have algorithms to make money.via the TL;DR App

There are a lot of different gambling platforms out there. Many of them are somehow related to cryptocurrency space. But there is no project out there that offers a simple experience like connect a wallet -> place a bet on some random number -> get rewarded if your guess was correct, without any kind of "login with Google" or "100 free spins" nonsense.
Let's fix this, let's build one!
But first of all, let's define our goal. We want our casino to work this way:
  1. A user chooses some number between 0 and 99 and bets ETH on this number.
  2. The user gets notified if they win immediately after a block with this transaction is added to the blockchain (it means the result should be available in the exact same block).
  3. After this the user can send another transaction to claim their prize which is their bet multiplied by 99
The requirements are also very simple:
  1. No centralized services.
  2. No random oracles - they are cool, but we can do it without their help.
  3. Security is the first priority - no one should be ever able to get an advantage of the casino to increase their chance of winning.
Now let's answer the next question: why are there are so little projects like this in the wild? I think there are multiple reasons.
First. The nature of casinos. When I think of the word "casino" I imagine something bright, rich and luxury. Las Vegas, neon signs, gold, drugs and easy money. We are attracted by these dreams of instant wealth. And we are sure that the place that can make us rich should have billions of dollars in its safes. We don't know how much money do casinos possess in reality, but we believe there is much.
This is very important. All these luxury things won't matter if there is a big display inside the casino that shows how much money does the casino have available in the prize fund. You can't say "come on, everybody gets a million!" if everyone sees that you only have $10k.
And in the decentralized world there is such a display for everything. Everyone could check how much money your contract has on it and then adjust their expectations.
We can't fix this problem. If our casino has only 1 ETH on its balance, there is no way to win 100 ETH in it. This makes it less attractive to users - no one is becoming millionaire in one night. But we can offer transparency in exchange. We can say: "Here are the rules. No one can break them (even the casino owners). If you follow these rules, you have a fair chance to transform your $1 into $99 in seconds. No lies".
Second. Randomness. Every casino needs a reliable source of randomness. Centralized casinos don't have randomness - they have algorithms to make money and sometimes share a bit with some lucky ones. Decentralized casinos can't do things the same way - they should be fair. Moreover randomness in a decentralized casino is the key point of security - it is the armored door protecting the prize fund. If your casino has weak randomness, your prize fund will be stolen.
Randomness is hard to achieve in a deterministic environment, because it is defined to be undetermined. They are two incompatible things. However there are some tricks to obtain secure randomness in such an environment as EVM and I will teach you them.

What is luck?

When we design a centralized service, it is not a big deal to acquire random numbers - every environment provides us with some randomness primitive we could use, don't even thinking where it came from. However in a decentralized environment there is simply no such primitive - you have to figure out yourself what is secure and what is not.
For example, many of centralized pseudo-random functions use system clock under the hood. And this is quite secure unless an attacker knows the exact time interval when the function was invoked.
Decentralized pseudo-random functions can't rely on that because most of the times there is none such a clock. And if there is, timestamps are known in advance and could be manipulated by the current consensus-leader.
In Ethereum we have
block.timestamp
variable which contains the timestamp when the block was produced. This timestamp has exactly these cons I've mentioned: everyone knows that the next block will be published within the next 15 seconds or so and the miner can manipulate it a little.
And these flaws apply to any piece of data in a decentralized system that is known in advance. Which hints us that we should use something that is unknown yet. Maybe some data from future.
Okay, we need something that is unknown now, but certainly will be revealed later, and can't be modified while unknown to fit interests of the modifier. And this is exactly the case when the most obvious solution is the right one.

Blockhash is fine if assumptions applied

What I'm about to tell you is a very well known technique to achieve secure randomness in a distributed system with a PoW consensus. The real value of this article is in exact calculations and a source code for you to play with.
Ethereum nodes reach consensus with Proof-of-work algorithm. It means that we send our transactions to some node that takes a subset of them it likes the most (ranging by fees attached), executes them and only then (as the last step) - calculates the blockhash. The blockhash is calculated after a block is completely arranged because any change to a block leads to a different blockhash. That means that whenever the node that already did calculate a valid blockhash wants to add a transaction to the block, remove a transaction from there or change the order of transactions - it has to calculate the blockhash again.
A blockhash meets our "has-to-be-unknown-now-but-revealed-later" requirement perfectly fine - nobody knows what blockhash the next block would have until it is found and revealed. But what about "has-to-be-hard-to-modify"?
Let's suppose we calculate the random number using this simple formula:
uint randomNumber = uint(blockhash) % 100
What would it take for a bad miner to get advantage of it? Let's suppose the miner adds a transaction like "I believe the number is gonna be 55 and I bet 100 ETH on that" to the block and starts calculating the blockhash.
Making our formula so simple we also made it very powerful. The only way to affect its outcome is to modify the
blockhash
value. The only way for miner to modify this value is to keep re-arranging the block until the desired blockhash found skipping every blockhash that doesn't fit. The miner can't find the right blockhash, calculate the random number it produces and after that add the correct transaction to the block - the blockhash would also change.
This means the miner is forced to choose whether they want to publish a block to lose their bet but keep a block reward or to skip this block and continue blockhash calculation until they find a match.
Statistically the match could happen every 100 blocks (considering our formula). This means that the prize the miner could win in our casino should be more (and with a decent gap!) than a total reward for mining these 100 blocks. This leaves us with another simple formula:
Prize > BlockReward / WinChance
Until this condition is met, it is economically inefficient for miners to perform such an attack. What about exact numbers? We know the
WinChance
- we set it to 1% by ourselves. Current Ethereum's
BlockReward
is around 2.7 ETH per one block - 2 ETH just for finding the right hash and ~0.7 ETH collected as transaction fees.
This means that until the maximum prize value in our casino is less than 267 ETH (2.7 x 99) we're completely safe - no one would ever steal money from it's prize fund.
And considering current exchange rate (10.02.21, $1750/1ETH) this is actually awesome. Maximum bet size is limited by 2.7 ETH which is around $4k. This should perfectly suit like 99% of the globe. The idea of having a pretty decent chance to transform your $10 into $990 is fascinating. Add to this a complete transparency of a blockchain and a promise that everyone are forced to follow the rules of a smart contract and you get a game changer in the world of gambling services.
Yes, this technique will only work in PoW-based systems and it comes opposite to the current evolution vector of distributed ledger software, but there is still plenty of time for such a dapp to exist and entertain people. ETH2.0 is not coming as soon as we want it to come.
You can also wonder: "But a bad miner could simply place multiple bids in a single block to overcome our max prize cap". Yes, but this can be easily fixed with some nonce (unique for each bet in a single block) like this:
uint randomNumber = uint(keccak256(blockhash, nonce)) % 100
With that being said...

Welcome Honest99

So, there is actually exist such a casino now. Here it is - honest99.bet
I'm working on this project completely alone and this is a big excitement for me to finally being able to present it to public.
It is optimized mostly for mobile devices and doesn't have a lot in the prize fund, but it works and does it exactly how I described it in this article. However there are some adjustments:
  • Right now the prize multiplier value is set to 66 instead of 99 - it will automatically switch to 99 once the prize fund reaches 400 ETH (and statistically it should one day)
  • Maximum prize value is set to 200 ETH instead of 270 ETH (to make it even more unattractive to attack) and is never more than a half of the current prize fund value
  • 3% fee is kept from each prize to fund future development
Here is the source code link - github.com/Casino-Honest-99/phase1
It has 'phase1' in it because there is also a 'phase2' for this project (I overestimated my financial power when I was designing it, so it will be released some time later). If you're interested - I have an idea to turn this casino into an entire decentralized organization, members of which receive weekly dividends and are able to directly affect the protocol with the power of secure voting.
I hope this article was interesting for you and also that such a self-promotion section was appropriate. As a final, here is the complete GIST of honest99 smart contract, so you could see how compact yet powerful it is. It's MIT, so pick it up and use wherever you want.

Written by seniorjoinu | Blockchain and stuff
Published by HackerNoon on 2021/02/15