Provable fairness is guaranteed by the following three components:
- Real-world physical randomness: Our hamster Mia’s unpredictable movements play a major role in generating the outcome of the marble race.
- Smart Contract: escrows bets until winners are paid out or all players are refunded.
- Provable live video stream: guarantees that the draws and races have not been pre-recorded or tampered in any way.
Our complete system is engineered in a provably fair manner. This means that it is possible for everyone to verify that the outcome of any race has been generated in a legit way and that all winners have been paid out. As a gambler you can satisfy yourself that neither the operator nor any other player did tamper the results or bets. Furthermore, you can be sure that an attempt to do so is in any case detectable.
Unlike other blockchain betting sites, where you have to understand and apply complicated mathematical formulas to verify the fairness, with Mia you can just watch the live stream of the race video and easily verify which marble has won and that the race itself was live (see Provable live video stream for more info).
Real-world physical randomness
The outcome of the race is determined by the starting position of the marbles and their physical interactions with moving obstacles on their way down the racetrack.
The first type of obstacles are diamond shaped wooden blocks. They are mechanically connected to the hamster wheel and rotate whenever the hamster is running in the wheel.
The second type of obstacles are wooden pegs. Their vertical positions are defined by the latest Ethereum block hash (see "Provable live video stream" for more details) and also influence the marbles raceway.
The race start is also triggered by the hamster: it starts after the hamster ran a distance of 2 kilometers in his wheel.
Bets are placed by players in the Ether crypto currency (ETH) into our smart contract which is running on the Ethereum network.
The contract takes care of escrowing the bets until a winner is announced and all winning bets are paid out or, as in the highly unlikely case of a disaster, all bets are refunded. These two cases are the only way to transfer ETH out of the contract. This fact is apparent in the state diagram of the contract (Fig. 1) with the transition-methods highlighted in red being the only ones with outgoing ETH.
The state diagram also visualizes that from any state (except the initial state "seeding") there exists a sequence of transitions that will result in either the winners being paid out or the betters being refunded. These sequences consist of public state transitions (dashed arrows) which can be called by anybody on the Ethereum network.
The contract is implemented as a state machine, with 5 states and transitions between them. The first 4 states are only reachable in a linear way: one after another (counter clockwise in the state diagram).
These 5 states are as follows:
- Seeding: This is the initial state of the contract for a new round. After the operator (owner) calls seedPots(), the contract is transitioned to the next state with the jackpot filled up with the seed amount.
- Accepting bets: In this state, bets can be placed by calling the placeBet() method. Bets are held in escrow by the contract and can only be released when reaching the "Paying out" or "Refunding" state. Also, whenever Mia finishes a workout (stops running in the wheel), the distance run is written to the contract with the miaFinishedWorkout() method. This method automatically transitions to the next state once the workoutThreshold constant (currently 2km) is reached.
- Race in progress: In this state, no more bets are accepted. The race is started automatically after there are 12 confirming blocks. This is to safeguard against chain reorganizations and prevents front running. Once the race has finished and the winner is written to the contract with the setWinningMarble() method, the contract is transitioned to the next state.
- Paying out: When reaching this state, paying out the winners of this round can start with the payoutWinners() method. This method is normally called by the operator but can also be invoked by anybody else, should the operator fail to do so. After paying out the last winner, the contract automatically transitions to the "Seeding" state.
- Refunding: This is a special state that ideally should never be reached under normal conditions. It is only reachable through the claimRefund() transition which is callable only 2 days after the round started from the "Accepting bets" and "Race in progress" states. The delay is there to make it less attractive for the operator to use this functionality, since waiting 2 days means no further race can take place and thus less profit for the operator. At the same time this functionality provides security for the players by giving them a way to get their wagers back in the case the operator should not provide a valid winner for the current round in a timely manner. Once in state "Refunding" the refundAll() method can be called multiple times. When the last player was refunded in the last call to refundAll(), the contract automatically transitions to the "Seeding" state.
The contract is published at 0x721a46E7e05d3236A9F8bc411CfFd974a1E28C8F where you can also inspect its source code.
Provable live video stream
Until recently, it was not possible to stream a video signal of a random event from the real world over the internet and prove that the captured events are live (recorded and streamed in real-time).
This limitation made video streaming unsuitable for online gambling. Proof that the video stream is live and is not prerecorded or otherwise tampered by the operator is a prerequisite for online gambling in this form.
We provide a provable live video stream by combining real-world physical randomness with realtime blockchain data. We do this is by taking the block hash of the latest ethereum block, taking 8 bits from it and replicating these 8 bits on the racetrack where the marbles roll down.
When the race is in progress and the marbles pass the pegs, they are in physical interaction with the pegs. This interaction can not be faked once recorded, while at the same time, it provides proof that it was recorded at the time as this block hash was published.
The 8 wooden pegs in the image above represent 8 bits from the first byte of the latest block hash before the race starts.
- a 0 is represented by a low peg
- a 1 is represented by a high peg
This is visualized in the live stream as in Fig. 3, at each start of the race.
The live stream also shows the hex number to binary number conversion. You can look up the hex to binary conversion yourself in this table or just google for '0xff to binary'
Some points that may come up and their counter-arguments
- You could pre-record 256 (2^8) different races/peg combinations and then show the matching one:
In this case, when the race starts, the diamonds/rhombuses driven by the hamster would have to be exactly in the same position as in the recording. Otherwise it would be noticeable immediately when viewing the live stream.
- You could render the entire scene with computer generated images:
This would require the rendering engine to operate with real-time performance, which is not possible today. Even if it would become possible, the costs would be tremendous.
- A miner could forge a block which leads to his favorite peg positions:
Luckily, just having favorable peg positions does not guarantee a certain outcome of the race as there are many other physical factors involved (diamonds, other marbles). A miner would only forge a block ( i.e. holding back/throwing away a valid block, which would give him instant block reward, in exchange for the small probability of finding another more favorable block hash and not going out empty-handed) if he can be certain that a desired block hash gives him enormous gains with 100% certainty. This scenario is even more unlikely, given the fact that a rogue miner has to make a bet 12 blocks ahead of his forged block (the race-start-block, from which the peg positions are derived from) and thus has no more control whether his bet is included or not.
- Shouldn’t you use some hash algorithm for your keccak256 to 8bit mapping?
Theoretically this would be more secure, but practically this makes no difference (as computational power is not the limiting factor, see last point) and we like the simpler and more user friendly approach much more.