0

I am trying to implement a simple lottery as a pet project and to get into solidity coding.

I am running into an issue and I wonder what is the best way to solve it. Basically during a timeframe of a draw x participants take part. X could potentially be very big, lets say 10k. At the end of the draw winning numbers are being generated and I need to go through all participations and check whether they have won and how much. Both would be public methods accessible only to the owner.

Problem What can I do to not run into out of gas issues, especially hitting the maximum gas per block limit when the number of participants gets too large?

Now I see two ways to solve this:

method 1:

  • have a method that returns the amount of participants

  • have a central service that paginates through that amount by lets say 50 each and calls a "determine winners" method

  • have a method that then calls the payouts

  • do the same paginated method calling for the payouts

method 2:

  • have a determineWinners method that iterates through lets 50 of the total participants to check for winning numbers

  • when done and there are still unchecked participants left, store the last iteration variable (eg 50 or 100 aso) and create an event that lets a central service know, to call that method again until done

  • do the same for payouts

In general I don't like the heavy dependency on the centralised control authority of the contract. Also both methods would be very slow. Determining winners out of a pool of 10k in steps of 50 and a block time of 20 sec would already take more than an hour. 200k users would not work anymore if I run the lottery on a daily basis.

Is there some sort of best practice on how this can be done?

Do the methods presented make sense? Which one is preferable?

Are there other ways?

Thanks a lot for your help. Gordon

1 Answer 1

1

The canonical way to do this would be to have a view method that ticket holders can call to check if they've won (possibly something like getWinningNumber() or checkTicket(uint ticketNumber)), and then have a method that winning ticket holders can call to claim their winnings (which of course reverts, or does nothing, for non-winning ticket holders).

3
  • Yes, that sounds reasonable. The only problem with this is that in order to know how much the payout per category is (e.g. 3 numbers right, 4 right, 5 right etc.) I need to know the total amount of winners within one category in order to divide the payout per category with the amount of winners. If I implement a checkTicket method I can tell whether somebody has won, but I cant know how much he will receive..
    – migo
    Commented Mar 7, 2018 at 17:29
  • If you need to count the number of winners in each category, you'll have a hard time doing it on-chain. One workaround would be to break claiming into two phases: one where winners announce their claim, which adds them to a set of winners, and allows you to count the number of winners in each category, and a second phase where they take their winnings. Although this means that winners who missed the deadline for the first phase will miss out, which will annoy them.
    – James_pic
    Commented Apr 30, 2018 at 13:38
  • In practice, you're probably better off using fixed payouts, and calculating how much you need to set aside to pay for the winnings if you're unlucky (figure out say the 99.9th percentile winnings).
    – James_pic
    Commented Apr 30, 2018 at 13:41

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.