0

So user a and user b both call a function (transaction) on a deployed contract with the code as bellow.

uint numberA;
uint numberB;
address playerA;
address playerB;

function playANumber(uint number){
    if(msg.sender == playerA && numberA == 0 && number > 0){
        numberA = number;
    }
    if(msg.sender == playerB && numberB == 0 && number > 0){
        numberB = number;
    }
    if(numberA > 0 && numberB > 0){
        //dosomething
    }
}

Will the part in "do something" always get called and if not, how can I make sure that it will. Or should it be split in two, setting the number and another transaction or call to execute the code in "do something"?

I have a contract with a similar setup and 90% of the time it works but theres also that 10% where the transaction clientside does not error but when I look at the state of the contract only numberA or B is set.

EDIT:

So I'm using truffle to call a deployed contract. PlayerA and PlayerB are simultaneous calling the contract. If I just rely on a successful transaction and don't explicitly check the state only the state change of one player is actually persisted. I use two different browsers for each player. The following pseudocode is used to call the contract and then check the change. Retrying after checking if the change actually is present does get the others player number in the contract and then the dosomething part is called.

contract.playANumber(1, {from: "someAddress"})).then( (tx) => {
                                 console.log(tx);
                                 return contract.getTheNumbers.call({from:"someAddress" });
                             })
                            .then( numbers=>{
                                if( (numbers.A > 0 && iAmPlayerA()) ||
                                    (numbers.B > 0 && !iAmPlayerA() ){
                                    console.log('state is ok');

                                } else{
                                    console.log('oops try again later');
                                }
                            })

Output of Player A:

Player A output

Output of Player B:

Player B output

1

There is no concurrency in the EVM, unless you count reentrancy, which you won't have to worry about here unless you're calling out to another contract in doSomething(). Your function is always called with exactly one msg.sender.

doSomething() won't get called until both playerA and playerB have called the function at least once. This will take at least 2 calls, unless playerA and playerB are both set to the same address.

Once both number variables have been set, doSomething() will run every time it's called, unless it includes some code to clear them.

  • this is not the behaviour I'm seeing, added more info in the question – BennyM Oct 3 '17 at 8:47
  • Testing this manually is potentially confusing, write a test. Then if you're still puzzled by the results, post your test code. – Edmund Edgar Oct 3 '17 at 11:13
1

The way the blockchain works is that only one piece of code is ever run at a time. Because of this, dosomething will only run on the second call of playANumber because both numberA and numberB must be set before it can be run (one call for setting numberA and one call for setting numberB).

If you want it to always be called when either are greater than 0, then:

if(numberA > 0 || numberB > 0){
    //dosomething
}
  • this is not the behaviour I'm seeing , added more info in the question – BennyM Oct 3 '17 at 8:47
0

According to your code, //dosomething will get called with numberA > 0 and numberB > 0.

For example, lets say that A calls the transaction, THEN B calls the transaction. (A and B cannot call the transaction at the same time in Ethereum, smart contracts do not have this functionality). A will set his number to 1, and then if(numberA > 0 || numberB > 0) will not run because B isn't set yet.

Later, when B calls the contract, his number will get set to 2, and then if(numberA > 0 || numberB > 0) will now run because both numbers are now > 0.

Does this clear things up?

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.