Blockchain-based P2P betting

The Ethereum network, widely known in a narrow circle of blockchain developers, has already established itself as a convenient and stable platform for the development of smart contracts. We are try to make smart contracts available to unprepared users, offering simple but practically useful contracts. We have recently developed the betting smart contract called Bet Me.

At the heart of the contract is a bet of two opponents. They reinforce confidence in their own right using a monetary bet. The loser loses money, and the winner takes it all. In this article, I will go into more detail on this.

What does blockchain have to do with this?

Let’s begin with a question rarely asked by the authors of articles on blockchain: is blockchain really necessary in this case? What tasks is it difficult to solve with the help of an oral or a legal agreement, but is easy with the help of blockchain?

If two people have a face-to-face dispute, this often results in a new trial. “That’s not what I meant”, “External circumstances influenced the outcome; otherwise I would have been right”, “I did not really bet with you, and you just made it up” and the other possible excuses typical for oral bets between those who know each other well and aren’t betting much money.

In case of serious bets and relatively distant acquaintances, it is often advisable to conclude a written agreement and detail in it the essence of the dispute, the rates, the criteria for making the decision and any other conditions that the parties consider important. Such an approach has a number of limitations.

  • Most often it is necessary to involve a lawyer, or even two, one on each side; otherwise an important point might get forgotten, which may lead to financial losses.
  • Often the contract covers only the obligations of the parties, while it does not cover the responsibility for possible violation of the obligations. As a result, it is too easy for one side not to pay, and extremely difficult and expensive for the other side to get their money through the court.
  • Or it may be that both sides insist on their rightness, and even resorting to court does not guarantee that the winner will receive the money.
  • It may also be that the losing side has no money, and even the court’s decision will not force it to pay its debts, despite all the obligations.

Blockchain (and the Ethereum network in particular) supports working with money. (We will refer to Ethereum cryptocurrency as the money; although it is not entirely correct, it is convenient and reflects the true state of affairs because Ethereum can be easily exchanged for fiat money, and vice versa). At the same time, in Ethereum, it is possible to set the agreements as a set of specific rules; it will be simply impossible not to fulfil them. So, our smart contract takes money from each side and freezes it until the occurrence of specific events. A set of specified program rules will allow the winner to withdraw money. This is just what we need.

Implementation

A set of rules governing a dispute can be implemented in a variety of ways. Below, we will talk about what we did for users of the Smartz platform.

Two sides are involved in a bet. The one who creates a contract on the Ethereum network is called the Owner [of the contract], and his counterparty is called the Opponent. The contract Owner specifies a textual statement, which he/she considers to be true. The Opponent bets that the statement is false. The decision on the outcome of the dispute is made by an independent Arbiter, whose candidacy is acknowledged by both the owner and the opponent. The Arbiter receives a commission fee of some percentage from the amount involved in the dispute.

The work of the contract is divided into several consecutive stages.

  1. Negotiation. Before creation of the contract, the Owner and the Opponent can negotiate in any convenient way. Having jointly decided on the Arbiter, they send an invitation to the candidate to oversee their bet. Having received the invitation, the Arbiter will see all the conditions and the corresponding State. More on this below, but for now it is important to understand that the future Arbiter must transfer this number to the contract to show on what terms he/she is willing to judge the betting parties. If the owner has established a non-zero security deposit (ArbiterPenaltyAmount), then, agreeing to the terms, the Arbiter must transfer the specified amount of Ether into the contract. After that, the corresponding amount is blocked until the Arbitrator judges the betting parties or until the Deadline for resolving the dispute. In the latter case, the Arbiter loses the opportunity to withdraw the deposit, and this amount is distributed equally among the betting parties.
  2. Initialisation. The contract Owner creates an instance of the contract and configures its parameters: the subject matter of the bet; the date until which the Arbiter must make a decision (Deadline); percentage of the Arbiter’s commission fee (fractional ≥ 0 and <100); the amount of the ArbiterPenaltyAmount deposit (it may be zero), which the Arbiter must make as a guarantee that he/she is going to judge the bet in the wording available at the time necessary. The Owner also sets the Ethereum address of the Arbiter that he/she trusts. Only the Owner of this address can later become the Arbiter.
  3. Owner’s bet. After the configuration, the Owner of the contract places his/her bet. To do this, he/she transfers any amount of Ether to the contract. This amount is the bet, and it is held at the address of the contract.
  4. Arbiter’s agreement. The Owner’s bet sets the terms of the bet. Now, the Arbiter sees the full terms of the deal: the wording of the bet, the time by which a decision must be made, and most importantly, can understand how much Ether he/she will receive as a reward. If the Arbiter is satisfied with the terms, he/she confirms his/her participation and simultaneously transfers the security deposit.
  5. Search for an Opponent. After the Arbiter’s consent, the search for an opponent begins. The Owner either pre-sets the address of an Opponent if he/she is ready to bet only with someone specific or leaves the address empty. In such case, the owner of any address on the network (except for the Arbiter and Owner) can become the Opponent. The Opponent confirms participation in the bet, calling a separate contract method, in which he/she transmits the current data version number and as much Ether, as the Owner has bet. From this moment on, the bet is considered made. Now the contract awaits either the Arbiter’s decision or the Deadline.
  6. Outcome of the bet. The Arbiter can judge the dispute in three ways. 
     — Recognise the claim as true. In this case, the contract Owner can withdraw the entire amount of Ether, except for the Arbiter’s commission fee and the deposit (if applicable): this money is withdrawn by the Arbiter, and the Opponent does not get anything. 
     — Recognise the claim as false. In this case, the Arbiter may withdraw Ether in the amount of the commission fee due to him and the amount of the deposit. The Opponent takes the rest, and the Owner does not get anything. 
     — Declare the bet undecided. For example, the owner created a dispute with the statement “A football match between teams A and B, scheduled for the next Sunday, will end with a score of 2:1 in favour of A”. If the match is cancelled, the Arbiter will not resolve the bet, but he should be able to take back his/her deposit because the problem was not his fault. Each of the parties in this case can request a transfer of Ether in the amount of their own rate from the contract address to their wallet.
  7. Money withdrawal. When the Arbiter has made a decision or the Deadline date has come, each of the parties may request the withdrawal of Ether. The contract itself will calculate how much Ether is available for withdrawal, being guided by the results of the bet.
  8. Destruction of the contract. The Owner can send a self-destruct command to the contract. This can be done either before the conclusion of the transaction (if an Arbiter was not found), or after its completion (if all parties withdrew the funds due to them). Such an opportunity will be useful if (by some magic) the address of the contract receives more Ether than planned. The probability of such an event is very low, but on the Ethereum network, one can not completely block the translation of the broadcast to the address of an arbitrary contract, and throwing frozen money is stupid.

Now a little about why you need the State Version Number. This is a number that increases with each change in the significant terms of the bet, such as the wording of the dispute, the size of the Arbiter’s commission fees or fines. When someone agrees with the terms of the bet, he/she 1) sees the actual state of the data; 2) sends a method call to the contract that registers compliance with the terms. If between the two events one of the parties (most likely, the Owner) changes a contract parameter, it will be agreed with the other data version.

For example, a candidate Arbiter enters the interface of the contract for smartz.io and sees that he/she is offered to judge 10 Ether (today it is about USD 3,000) dispute for a commission fee of 1 % (about USD 30). The candidate happily agrees and sends the confirmed transaction to the network. A dishonest Owner sees an unhandled transaction of the Arbiter in the mining pool and sends his own: changes the Arbiter’s commission fee to 0 %. The cheater puts the gas price above the average, and with some probability, miners can process his or her transaction earlier.

This is called a Front running attack. State Version Number protects against such attacks. If the transaction is processed earlier, the version number of the data in the contract will change. The Arbiter, in his transaction, sent the data version number that was less by one. Therefore, the contract will refuse to execute the transaction, and a rollback will occur. The Arbiter will review the new terms and either refuse to participate or agree by sending the current data version number.

When developing a contract that operates with Ether, one has to think through a lot of bad scenarios. What will happen if the owner of the contract decides to cheat the Arbiter? And what if the Arbiter turned out to be dishonest? And what if the Opponent is actually a hacker? Or do all three want to deceive each other because the stakes in the bet are high enough? In addition, it is necessary to take into account any possibilities for violating the normal course of the bet, when Ether will be blocked in the contract and even the Owner will not get access to it.

For example, the option of recognising the bet as insoluble has already arisen in the course of implementation. For the same reason, the sequence of stages in the bet is as follows: the Owner’s bet -> the choice of the Arbiter -> the Opponent’s bet. It may be that the Opponent has not confirmed his participation, and the Deadline is set far in the future. In order not to turn into a long-term investor, the Arbiter may refuse to participate, but only until the Opponent has placed a bet. And there are many such nuances in the contract.

The good news is that it needs to be programmed once and used further. If the bet was formalised as a paper contract, in the event of such borderline situations, many people would have to go into each point time and again, and negotiate on how to interpret it. Blockchain lets one set the conditions, as in the contract, while imposing interpretation of the conditions on the virtual machine and always having one and only one result of their execution.

One cannot ignore the problem of an interested Arbiter. In our contract, the Arbiter decides alone. For simple situations, this is sufficient, but sometimes the risk of the Arbiter’s personal interest is unacceptable. One of the solutions is to introduce into the logic of the contract the possibility to add several Arbiters and make a decision by voting. This is quite a complicated logic, especially if you want to make it universal for all possible bets and their participants. However, the good news is that all the logic of complex collective arbitration can be made into a separate smart contract. The Owner of the bet will register the address of the contract as the Arbiter. From the point of view of the interface, such a contract should be able to call several methods from the bet contract: the consent to judge the bet, refusal to provide such consent, three versions of the decision and one method of the Ether withdrawal. Inside the arbitration contract, the decision logic can be used by most arbitrators, like the one made in the Multisignature Wallet contract, also available on Smartz.io as a constructor.

For some bets, you can replace a group of Arbiters with a contract that uses one or more oracles. Or come up with another way out (for example turn the bet into a roulette-like scenario with a random decision). And all this — without changing the contract code of the bet and without complicating the logic of its work.

Testing

We would like to say a couple of words about testing. Everybody knows that automation of testing is good. Many people actually write tests for their code themselves. Some people use the TDD approach in development — a long and well-known Test Driven Development. The key difference between TDD and simple testing is that tests are written earlier than the code. This allows you to look at the contract code from the outside, to experience possible problems and solve them in advance. In addition, when used correctly, TDD allows you to change the logic of the work much quicker, if this is required suddenly. Proper use comes with experience. TDD is not a silver bullet, as one might think when reading the numerous materials on this topic. That said, it is worrying that the development guides on Truffle and Node.js do not demonstrate the use of TDD for development on Solidity. Beginner developers develop bad habits and end up suffering a lot.

TDD implies that there is a lot of testing in the project. For example, the bet contract code takes 325 lines, and the test code for this contract consists of 2,144 lines. At some point, there were enough tests to run the truffle test for more than a minute. The development cycle in TDD implies a frequent run of tests after small code changes. In order for the development not to become torturous, Truffle had to be taught to run only the part of the tests that coincide with the transferred regular expression.

Under the hood, Truffle uses the Mocha framework to work with the tests. Mocha is able to filter the launch of tests on regulars, but Truffle out of the box cannot transfer the corresponding parameter — grep from the command line. Taking advantage of the fact that the Truffle configuration is a regular JavaScript code, I have typed in the parsing of command line arguments and the formation of parameters for Mocha. The config file which I eventually got is available on the project’s GitHub. The implementation is not very beautiful, but it works and saves a lot of time.

Summary

The dispute contract was conceived as very simple in terms of functionality, but thanks to TDD and the analysis of possible attack vectors it has evolved into an implementation that is slightly richer in terms of restrictions. The obvious drawbacks of the contract are connected with the sole decision of the Arbiter; however, they can be eliminated without modifying the contract code of the bet if the voting system of several Arbiters is implemented in a separate smart contract. In the same way, the use of oracles for disputes, in which this is possible, is implemented.

A BetMe bet contract can be tested and run using a ready-made template on the Smartz platform. This requires a Metamask extension for a desktop browser or Trust Wallet for mobile devices. Also, the source code of the contract itself is available on GitHub.

It is worth acknowledging that today the use of blockchain technologies has been essentially reduced to crypto-currencies and the release of tokens for ICO. Decentralised autonomous organisations (DAO) have not yet become a reality. But if you think about how the bet settlement systems will develop further, you can submit a register of arbitrators with a rating (e.g. based on the Token Curated Registry). Upon completion of the bets, the participants could vote for or against the arbitrators with whom they dealt, changing their position in the ranking.

On the one hand, the BetMe dispute contract is a practically applicable self-sufficient element. On the other hand, it may well become one of the bricks, from which the ecosystem of decentralised organisations will eventually evolve.

References