Newbie here, making my very 1st Smart Contract (a rock/paper/scissors game).

I'm using 0.5.11 because that's what the tutorial I'm learning from is taught in.

I'd like to call my payable placeBet function with 3 parameters:

  1. The wager
  2. The address of Player 1
  3. The address of Player 2

I want Player 1 and Player 2 to send the wager amount to my contract.

But I'm having trouble implementing this.

  • So what exactly is your problem with the current code? With the current code anyone can deposit Ethers in the contract with placeBet so it should work. The only thing needed for depositing Ether is the payable keyword in the function name - no other code is needed. Commented Jun 28, 2020 at 14:50
  • @LauriPeltonen The problem is I only want the 2 players to be able to deposit ether, the contract should be locked to everyone else. I also want the 2 players to deposit the exact same amount, only one time.
    – antoniopgs
    Commented Jun 28, 2020 at 14:56

2 Answers 2


You current logic is not working, because if you are not using .transfer(msg.value), but using .transfer(<ETHER_VARIABLE>) then transfer method is using the contract balance to send the ether. Apparently you contract has 0 balance, because you are not forcing users to actually deposit the ethers into the contract balance on method placeBet.

One solution might be to force both users to deposit the ethers into the contract balance at method placeBet() and allow them to play only when both did made the deposit. Then on method play() the contract will have enough balance to send ethers to the winner (because players previously made their deposits). This way you should also build withdrawDepositedAmount method for the scenario when player 1 deposit ether amount and player 2 dissapear and not finishing the deposit, so player 1 not end up with "locked" ethers.


As stated in the comments you want only those two players to be able to deposit, and the deposit amount has to be the same.

So what you need is:

  1. Anyone else sending Ethers to the contract causes a revert so the transaction is reverted. This can be done with a require

  2. Whenever Player1 or Player2 (whichever is first) deposits an amount you wait for the other one to store the exact same amount - revert if different

  3. Revert if the wager amount is zero

You don't need to check for address balances because the wager should already be in - they don't need to have double the required wager. So the Ether is already stored in the contract at the start of the function.

So something like this should work:

uint wagerAmount;

function placeBet(uint _wager, address payable _address1, address payable _address2) external payable {
    require(msg.sender == _address1 || msg.sender == _address2);
    require(msg.value > 0);
    if (wagerAmount == 0) {
        // if this value is not set yet, set it. This is the first player to set the wager
        wagerAmount = msg.value;
    else {
        require(wagerAmount == msg.value);
        // start game

Note that the code allows one player to play against himself, but I guess that's ok.

Also, as a general security note, this kind of game is superly flawed: the other player can wait for the other player to send his move and then send a transaction which wins whatever the other player chose.

  • Is there a way to fix that security issue? Can I make it so that the transactions are only sent after both players pick their move? Sorry if it's a dumb question, I'm just starting out. Thanks!
    – antoniopgs
    Commented Jun 28, 2020 at 15:14
  • It's a very valid and common question, no worries :) There is no trivial way around it - you can consider something like hashing the answers with a salt, for example, and both parties reveal their salts once the betting transactions are in. Commented Jun 28, 2020 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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