Search code examples
nearprotocolassemblyscript

How play method works at "NCD.L1.sample--lottery" contract?


Here is the contract repo. https://github.com/Learn-NEAR/NCD.L1.sample--lottery

I don't understand the play method here https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/2bd11bc1092004409e32b75736f78adee821f35b/src/lottery/assembly/lottery.ts#L11-L16

 play(): bool {
    const rng = new RNG<u32>(1, u32.MAX_VALUE);
    const roll = rng.next();
    logging.log("roll: " + roll.toString());
    return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
  }

I don't understand the winning process but I'm sure it is hidden inside this method. So can someone explain how this play method works in detail?


Solution

  • To understand the winning process we should take a look at the play method in the lottery.ts file in the contract.

    https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/2bd11bc1092004409e32b75736f78adee821f35b/src/lottery/assembly/lottery.ts#L11-L16

        play(): bool {
            const rng = new RNG<u32>(1, u32.MAX_VALUE);
            const roll = rng.next();
            logging.log("roll: " + roll.toString());
            return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
          }
    

    There are a couple of things we should know about before we read this code.

    • bool
    • u32
    • f64
    • RNG<32>

    bool means that our play method should only return true or false.

    u32 is a 32-bit unsigned integer. It is a positive integer stored using 32 bits.

    u8 has a max value of 255. u16 has a max value of 65535. u32 has a max value of 4294967295. u64 has a max value of 18446744073709551615. So, these unsigned integers can't be negative values.

    f64 is a number that has a decimal place. This type can represent a wide range of decimal numbers, like 3.5, 27, -113.75, 0.0078125, 34359738368, 0, -1. So unlike integer types (such as i32), floating-point types can represent non-integer numbers, too.

    RNG stands for Random Number Generator. It basically gives you a random number in the range of u32. And it takes two parameters that define the range of your method. In that case, the range is between 1 and u32.MAX_VALUE. In other words, it is 1 and 4294967296. The next line creates a variable called roll and assigned it to the value of rng.next().

    So, what does next() do? Think rng as a big machine which only has one big red button on it. When you hit that big red button, it gives you a number that this machine is capable of producing. Meaning, every time you hit that button, it gives you a number between 1 and u32.MAX_VALUE

    The third line is just about logging the roll into the console. You should see something like that in your console roll: 3845432649

    The last line looks confusing at the beginning but let's take a look piece by piece.

    Here, u32.MAX_VALUE * this.chance we multiply this max value with a variable called chance which we defined as 0.2 in the Lottery class.

    Then, we put <f64> at the beginning of this calculation because the result always will be a floating number due to 0.2.

    Then, we put <32> at the beginning of all to convert that floating number into unsigned integer because we need to compare it with the roll which is an unsigned integer. You can't compare floating numbers with unsigned integers.

    Finally, if the roll less than or equals to <u32>(<f64>u32.MAX_VALUE * this.chance) this, player wins.