Dapp-a-day 15: Maker Darts
ethereum·@nexusdev·
0.000 HBDDapp-a-day 15: Maker Darts
 --- *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
👍 nexusdev, cass, anonymous, inferno, taoteh1221, thenakedgod, darknet, eeks, nicoleta, litali, analyzethis, zer0sum, velourex, gazm, helikopterben, steempower, summon, fminerten1, nikolai, kolik33, aaseb, alina1, stevenh512,