1

i have made a contract that 2 users participate in the smart contract, both users do the same steps however i notice it that user1 pay more gas ( transaction gas and execution gas ) than user 2

any idea to make it fair for both ?

this is one of the outputs for javascript VM

Account 1: 0xca3[player1]

Commit phase —————————

Transaction cost : 85799 gas

Execution cost : 62927 gas

Reveal phase ————

Transaction cost : 45485 gas

Execution cost :22613 gas

Account 2: 0x147 [player2]

Commit phase —————————

Transaction cost : 66397 gas

Execution cost : 43653 gas

Reveal phase ————

Transaction cost : 45357 gas

Execution cost :22613 gas

pragma solidity ^0.4.24;

contract rpsgame {

mapping (string => mapping(string => int)) scenarioMatrix;

address player1;
address player2;
uint currentGameCost = 0;
uint RevealTime;
bytes32 player1ChoiceHash;
bytes32 player2ChoiceHash;
string public player1Choice;
string public player2Choice;

function register (string choice, string randStr) payable notRegisteredyet()  sentCash(5 wei) {
    // players register , and input their (ether value >=5) and their choice + random String
    if(player1 == 0)
    player1=msg.sender;
    else if (player2 == 0)
    player2=msg.sender;
    if (msg.sender == player1)
          player1ChoiceHash = sha3(sha3(choice) ^ sha3(randStr));
    else if (msg.sender == player2)
        player2ChoiceHash =sha3(sha3(choice) ^ sha3(randStr)) ;

} 




function rpsgame() 
{   // constructor :executed only once , list all possible scenarios of the game 
    scenarioMatrix["rock"]["rock"] = 0;
    scenarioMatrix["rock"]["paper"] = 2;
    scenarioMatrix["rock"]["scissors"] = 1;
    scenarioMatrix["paper"]["rock"] = 1;
    scenarioMatrix["paper"]["paper"] = 0;
    scenarioMatrix["paper"]["scissors"] = 2;
    scenarioMatrix["scissors"]["rock"] = 2;
    scenarioMatrix["scissors"]["paper"] = 1;
    scenarioMatrix["scissors"]["scissors"] = 0;
}



modifier notRegisteredyet() {  // to make sure the that the same player doesn't register twice'

    if (msg.sender == player1 || msg.sender == player2)
     revert();
     else
      _;

}



 modifier sentCash(uint amount) {

 // checks that Ether value is >= 5
 if (msg.value < amount) {
    revert();
}
 //   its sets the decided amount of ether after updating what the first player entered. 
 //player2 can check that by press DisplayEther tab.

 if (player1 == 0) {
    currentGameCost = msg.value;
} 
else if (msg.value != currentGameCost) {
    revert();
}

_;

}



 function revealHand(string choice, string randStr)

{  //time to reveal the choices by input again the choice+random string and will checks
   //if hashedchoice+random string matches the initial ones.
     RevealTime == now;


    if (msg.sender == player1 && sha3(sha3(choice) ^ sha3(randStr)) == player1ChoiceHash)
        player1Choice = choice;
    if (msg.sender == player2 && sha3(sha3(choice) ^ sha3(randStr)) == player2ChoiceHash)
        player2Choice = choice;
}


 function play() returns (int w ){
     // time to find the winner , 0= tie , 1=player1 , 2=player2
        if (bytes(player1Choice).length != 0 && bytes(player2Choice).length != 0){

        int winner = scenarioMatrix[player1Choice][player2Choice];
        if (winner == 1)
            player1.transfer(this.balance);
        else if (winner == 2)
            player2.transfer(this.balance);

        else
        {
            player1.transfer(this.balance/2);
            player2.transfer(this.balance);
        }


        // to reset game 
       player1Choice = "";
        player2Choice = "";
        player1 = 0;
       player2 = 0;
       currentGameCost=0;
        return winner;
    }

   else if (now > RevealTime + 60)
    {
        // approx 1 mintue of waiting if only one player revealed,the ether goes directly to them.
        if (bytes(player1Choice).length != 0)
            player1.send(this.balance);
        else if (bytes(player2Choice).length != 0)
            player2.send(this.balance);
    }

   else
    return -1;
}



// getter function for player2 to see the amount of ether should be deposited


function DisplayEther () constant returns (uint amount) {

     return currentGameCost;
 }

}

  • It would be impossible to answer that without seeing the smart contract and the transactions. The gas cost could vary based on something as small as the number of zeros versus non-zeros in an address, or whether new values were being added to storage versus old values changed, etc. Without knowing the transactions and smart contract involved, it's impossible to speculate. – user19510 Nov 14 '18 at 1:13
  • can i know what do you mean by zero or non -zeros? – Jack.Mc Nov 14 '18 at 10:59
  • @smarx , i have added the code , please check it :) – Jack.Mc Nov 14 '18 at 11:22
  • I literally mean the number 0 versus a different number (e.g. 1). – user19510 Nov 14 '18 at 13:01
  • Completely unrelated to this question, note that your commit/reveal scheme is insecure. "paper" ^ "scissors" == "scissors" ^ "paper", so player 2 can selectively reveal either "paper" or "scissors" depending on what player 1 revealed. (In fact, either player can reveal any move.) You can fix this by concatenating rather than XORing. – user19510 Nov 14 '18 at 13:56
2

The first player to call register bears the cost of changing currentGameCost from 0 to whatever payment was attached.

Changing a value in storage from a zero to a non-zero value costs 20,000 gas. This is approximately the difference between the gas costs of the two calls.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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