I have just started coding some basic smart contracts with solidity and have a question on how to approach a particular problem. I hope I can make it make sense.

If I were to create a smart contract for a simple game, lets say its a dice rolling game where two players can play once another and wager some sort of game token or Ethereum that they have a balance of in the smart contract.

One player challenges another, the dice is rolled, a function in the smart contract decides the winner and they get the winnings.

My question is whats the fastest way to handle the contract verifying both players balances when they enter their wagers and then verify that they both agreed to play on another.

Right now in my mind it seems like one player would challenge another with a wager, the next player would have to agree and set their own wager, and then the first would have to confirm that. This would take multiple smart contract operations and players would be waiting for everything to get mined and written to the blockchain, especially if one of them used a low amount of gas or something.

What would be the proper approach for something like this?

  • For that type of interaction you may want to research about state channels.
    – Ismael
    Feb 14, 2018 at 3:59

1 Answer 1


I would create a contract that stores wagers. A player can create a wager by calling a createWager method on your contract, which would be payable. When they call the createWager method they would also send the amount they wish to wager. A very crude example below. Someone can then take the wager by a subsequent call.. also sending the value. Very crude example below. You'd need to add some methods for finding open wagers (where one side hasn't joined yet), as well as a mechanism for canceling a wager that's been created, but not yet taken .. to free up the initiator's ether.

contract BettingGame {
    struct Wager {
        address player1;
        address player2:
        uint amount;
    Wager[] public wagers;

    function createWager(uint _amount) public payable {
        require(msg.value == _amount);
        Wager memory w = Wager(msg.sender,0,_amount);
        uint wagerId = wagers.push(w) - 1; // this can be published in an event.  You'll need a method that can lookup open wagers  (where player2 is 0 and return those ids).

    function takeWager(uint _id) public payable {
        Wager storage w = wagers[_id];
        require(w.player2 == 0);
        require(msg.value == w.amount);
        w.player2 = msg.sender;

From your web3 app

bettingGame.createWager(someAmountInWei, { from: myaddr, value: someAmountInWei});
  • Keep in mind, generating random numbers can be a challenge.. for more on that: ethereum.stackexchange.com/questions/191/…
    – Howard
    Feb 13, 2018 at 23:15
  • Thanks for the reply! That seems like a good approach. How about the timing. With this setup would I be expecting the players to wait for each other for an extended period of time while the blockchain does it's thing?
    – Dan
    Feb 14, 2018 at 4:06
  • Correct. The extent would be dependent upon the attention of your players, their willingness to spend on gas, and how many transactions are flying about at the time. On average, blocks are mined ~every 15 seconds.
    – Howard
    Feb 14, 2018 at 13:46
  • I know this may be a little bit late, but hope you can explain something. Are you sure about what you said regarding the event? If the user looks up for EVENTS where player2 is 0, then that means he will also get past events that have been already played. From my understanding, events cannot be overwritten in the EVM.
    – Iulian
    Jan 5, 2020 at 14:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.