2

I have a simple contract:

pragma solidity ^0.4.0;
contract Festival {


    address owner;
    uint8 max;
    address[] entered;

    function Festival(uint8 _max) {
        max = _max;
        owner = msg.sender;
    }

    function joinFestival()
    {
        if(entered.length < max)
            entered.push(msg.sender);
    }


}

For example we set max=3. So let's say we call this function from some web page using web3.js

Festival.deployed().then(function(fest){
  return fest.joinFestival({from:web3.eth.accounts[0], gas: 100000});
});

Okay, great. When first guy calls the function we get something like that:

if(entered.length < max) // yes, length == 0, success, we can join!
   entered.push(msg.sender) //joined

After a while, when the transaction has been confirmed, second guy call the function:

if(entered.length < max) // yes, length == 1, success, we can join!
   entered.push(msg.sender) //joined

And now the interesting part. 3rd and 4th guys are trying to join at the same time.

3rd guy:

if(entered.length < max) // yes, length == 2, success, we can join!
   entered.push(msg.sender) //joined

And now his transaction is pending. At the moment the 4th guy is calling this function the 3rd guy transaction is still pending:

 if(entered.length < max) // yes, length == 2, success, we can join!
    entered.push(msg.sender) //joined

And so, the problem is in the last call. The thing is that this guy will get TX error and all gas will be spend. Since gas=ether, it is a very bad situation. My question is: how can we prevent this situation? I have only one way in my mind: check in web page .js file for pending blocks and if there is a transaction sent to our contract and the state of a contract is 'entered.length == 2' just throw an error to the 4th guy. If you have any suggestions it would be great. Thank you.

  • 2
    One possibility is to split the purchase of tickets in two operation, reserve and payment. Something like airplanet tickets, if you fail to pay then the next guy will be able to purchase the ticket. – Ismael Aug 23 '17 at 21:42
  • The problem is that if I don't 'fail to pay' the next guy spends all gas for nothing. – Muchacho Aug 23 '17 at 23:52
  • Are you sure it works like this? I was under the impression that it would depend on who gets ordered first in the block. – thefett Aug 24 '17 at 0:54
  • 1
    @Muchacho since blockchains are decentralized there's no way to determine beforehand if a transaction will fail. It is possible that between your check and transaction is sent another transaction may appear in another node accross the globe. You can only try to minimize the expense of gas in the case of a failed transaction opting ot use return instead of throw. – Ismael Aug 24 '17 at 1:14

Your Answer

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

Browse other questions tagged or ask your own question.