Dapp-a-day 15: Maker Darts

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@nexusdev·
0.000 HBD
Dapp-a-day 15: Maker Darts
![dapp-a-day-15 2x](https://cloud.githubusercontent.com/assets/6280810/18021133/a66bef38-6be5-11e6-9f2f-3b6ed6e86860.png)

---
*Today's dapp is a bit bigger than the dapps we've covered [previous days](https://steemit.com/ethereum/@nexusdev/dapp-a-day-14-dsroles-a-dsauthority-that-manages-up-to-256roles), 
so this post is commensurately longer.*

[Maker Darts](https://github.com/makerdao/maker-darts) is a RANDAO implemented as a
gambling game where participants are incentivized to both provide "as random as
possible" input and to punish participants who are insufficiently random. It's a
fairly complex set of contracts developed with an eye toward both allowing
simplifying layers to be built on top and ferreting out any potential
misalignments of incentive which might detract from the randomness of the
RANDAO's output.

There are simpler RANDAOs out there, but this one is significantly less trusting
than those. No oracles are consulted, and user experience has been sacrificed in
the name of flexibility and security at every possible opportunity. (Hence the
eye toward allowing others to build simplifying layers on top of this!)

This dapp works as a good example of how one might use 
[Nexus Development](https://nexusdev.us)'s [ERC20](https://github.com/nexusdev/erc20)
smart contracts.

### A high-level description of the game's mechanics from the README:

> A game is initiated when a user posts a bet of arbitrary size, a hash of a
> salt value plus a target value, the minimum number of other participants they
> desire, the winner's reward (an integer percentage of the losers' bets the
> winners may claim), the number of winners this game, the lengths in blocks of
> the commitment, revelation, and tabulation rounds, and the symbol of the token
> being used for placing bets. They may also optionally offer a fee to
> incentivize participants with lower risk tolerance to join. (It is not
> recommended that the fee exceed half the size of the bet, as this attenuates
> the incentive participants have to provide unpredictable input.)
>
> To join a game, a prospective participant must post a bet equal to the bet of
> the person who created the game, a hash of a salt value plus a target value,
> and the ID of the game they wish to join.
>
> New participants may only join during the commitment round. If the commitment
> round ends without enough participants joining, the round is cancelled and
> participants may request refunds.
>
> Once the commitment round ends, the revelation round begins. During this
> round, participants submit their salts and target values. Following this, each
> participant calls a function to calculate their random number. Each random
> number consists of the salts and targets of every other participant sha3'ed
> together in order of commitment hash, with the salt and target of the calling
> participant transposed to the beginning of the list.
>
> Though at this point each participant has received a unique random number from
> the DAO, the smart contract still holds the participants' bets. At this point,
> the half of the participants whose chosen targets end up furthest from their
> random numbers may call a function to reclaim half their bet. The half closest
> to their targets call the same function to reclaim their original bet plus
> half, as well as the bets of users who submitted commitment transactions but
> then failed to reveal. The function also distributes participation fees to
> each player. Participants have a number of blocks equal to the sum of the
> commitment, revelation, and tabulation round lengths to call this function.
> Any bets and fees not collected during this time are lost forever.

As described above, Maker Darts provides the unique mechanic of allowing users
to directly "beat the house" by better predicting the output of a round than the
other players. The whole game, after all, boils down to one of predicting the
RANDAO's output. Particpants may be incentivized to participate, and the game's
creator may even choose to waive the winner's reward, which would of course
amount to paying people to give you any input whatsoever and is thus not
particularly recommended. (Why should I waste the cycles to submit a random
number if I'm not disincentivized from just submitting '0' along with everyon
else? Ideally Maker Darts becomes the haunt of degenerate gamblers armed with
hardware RNGs and huge neural networks to suss out correlations in the RANDAO's
inputs and eventual output. Ideally.)

Returning to the format of previous posts, there are two primary contracts
involved in making Maker Darts work.

**[The lobby](https://github.com/makerdao/maker-darts/blob/master/contracts/lobby.sol)**,
as the name suggests, allows people with similar preferences regarding game
settings to find each other. It also provides two `MakerDartsGame` factory
functions. The first, `createZeroSumGame`, creates a simple 5 participant game
with no participation reward, 12 block rounds, 3 winners, and 50% of the losing
players' bets being distributed to the winners (the other 50% being held as
incentive to report in despite an obvious loss). It takes the size of the bet
which each participant must make as its first parameter, expressed in the
smallest unit of the ERC20 token specified via the function's second parameter,
the address of an ERC20 token, and a boolean representing whether to create the
game in `debug` mode as its third. It returns the address of the resulting game.

**Note:** the third parameter should always be `false` unless you're running unit
tests and need to be able to fast-forward the game by spoofing the current block
number. This parameter is exposed on the game contract as the public `debug`
property. When playing the game live, never join a game whose `debug` property
is set to `true`! End-user-facing UIs should hide such games entirely.

The second, `createGame`, takes the same parameters as the other function and
also returns a game address. However, it does not set any of the game's other
properties. The caller must call the necessary `set` functions themself.

The lobby emits a `GamePending` event with the game's address upon game creation.

**[The game](https://github.com/makerdao/maker-darts/blob/master/contracts/game.sol)**
encapsulates a single Maker Darts game. Breaking apart the lobby and the game
contract like this allows a single game to potentially break without breaking
any other games. End-user-facing UIs can then change in order to remove and
disallow any potentially problematic games in the future.

Each game has an owner whose job it is to set up and start the game. Game set up
consists of calling the following functions in any order:

- `setParticipants(uint256)`: The number of participants this game will accept
  and needs before it can be started.
- `setParticipantReward(uint256)`: The amount to pay each participant for
  participating. Can be useful for attracting participants faster.
- `setCommitmentBlocks(uint256)`: How long the commmitment round will be, in
  blocks.
- `setRevealBlocks(uint256)`: How long the reveal round will be, in blocks.
- `setCalculationBlocks(uint256)`: How long the calculation round will be, in
  blocks.
- `setWinnerCut(uint8)`: What percentage of each loser's bet will be put into
  the winner's pot.
- `setWinners(uint256)`: How many winners will be chosen.

`createZeroSumGame` handles calling all these functions for the game owner, but
they may call any of them again in order to change any of the game's parameters.

At this point, the game owner may start the commitment round by first granting
the game an allowance on the ERC20 token of `betSize + participants *
participantReward` and then calling `startGame` with their own commitment hash.
The game will emit a `GameStarted` event. The game's parameters are locked at
this point.

Participants may then join by granting an allowance on the chosen ERC20 token to
the game of `bidSize` and calling `joinGame` with their commitment hash.

If the game fails to attract enough participants during the commitment round, or
if the game fails such that nobody can claim their winnings after all the rounds
have completed, participants may call the `requestRefund` function with their
commitment hash and get back the money they put into it. The `requestRefund`
function will only pay out in the event of a stalled game after twice the sum of
each round's blocks has passed. This gives winners time to prove the game isn't
stalled by claiming their rewards. Once a reward has been claimed, no refund may
be claimed. In addition, if the game stalls and rewards are paid out, the game
owner forfeits the portion of their stake set aside for participant rewards and
the participants are granted their promised rewards.

A Commit event is emitted each time a new player joins.

Once the commitment round is past, the reveal round begins. Participants must
then call `revealBet` with their commitment hash, the target number they bet on
(as a bytes32 value), and the salt they added to the number to obfuscate their
guess (which, together with the target, constitutes the commitment hash's
preimage).

A Reveal event is emitted each time a player reveals.

After the reveal round ends, the calculation round begins. Each participant
calls `calculateResult` with their commitment hash, receiving a unique random
number. The unique random number is bitwise XOR'ed with the user's target. The
participants with the smallest resulting numbers win.

A Result event is emitted each time a player calculates their random number.

Finally, once the reveal round ends, participants may call `claim` with their
commit hash in order to receive either their winnings or the remainder of their
bet, plus any participation reward. At this point the game has ended.

A Claim event is emitted each time a player makes a claim.

There are also a few extra getter functions which UI developers may find useful:

- `getBet(bytes32) constant returns (address, bytes32, bytes32, bytes32, uint)`
- `getDistance(bytes32) constant returns (uint256)`
- `getResult(bytes32) constant returns (bytes32)`

For more details, please consult [the Maker Darts
repository](https://github.com/makerdao/maker-darts).

---
https://nexusdev.us
https://github.com/nexusdev
👍 , , , , , , , , , , , , , , , , , , , , , , ,