Programming Project - Phase 2

Hey @Paul_Kwok

In both cases value in not defined.

function __callback(bytes32 _queryId,string memory _result,bytes memory _proof) public {

        bool flip;
        uint256 randomNumber = uint256(keccak256(abi.encodePacked(_result))) % 2;
        if (randomNumber == 0) {
            flip = true;
        } else {
            flip = false;
        emit generateRandomNumber(bets[_queryId].walletAddress, flip);

        if (bets[_queryId].predictCoinSide == flip) {
            //balance -= value;
            //playerBalance[msg.sender] += value;             
            playerRecord[msg.sender].balance = playerBalance[msg.sender];
            playerRecord[msg.sender].countWin += 1;
        } else {
            //balance += value;
            //playerBalance[player] -= value;
            playerRecord[msg.sender].balance = playerBalance[msg.sender];
            playerRecord[msg.sender].countLoss += 1;            

        //delete bet from mapping

You need to define value to be able to use it.


Hey @KryptoS

Some things to think about :slight_smile:

function initalDepositToContract()

I am not sure this function is useful.
Also you do not have a deposit function, which means that you are using initalDepositToContract during your migration but it cannot be used to deposit ether because of what the function does:

function initalDepositToContract() public payable{
     contractBalance = address(this).balance;

It would be better to write a function deposit and use that one.

function deposit() public payable {
      contractBalance += msg.value;

You have a modifier:

   modifier costs(uint cost){
        require(msg.value >= cost);

but then you also require (contractBalance > 2*msg.value); in your function playFlipCoin(), the modifier can be improved:

   modifier costs(uint cost){
        require (contractBalance > 2*msg.value);

Or if you also want to set a minimum bet amount, you can also include it in your modifier

   modifier costs(uint cost){
        require (contractBalance > 2*msg.value && msg.value >= cost);

This function:

    function resetPlayerStatus() internal {
        address creator = msg.sender;

            players[creator].countWin = 0;
            players[creator].sumWin = 0;
            players[creator].countLost = 0;
            players[creator].isActive = false;
            players[creator].coinSide = 0;
            players[creator].betAmount = 0;


Can be simplified:

   function resetPlayerStatus() internal {

Happy coding and congrats for your 1st dapp :slight_smile:

1 Like

Hi, my code is here:

Also had some issue with migrating using Truffle on Ropsten so I deployed using Remix. Demo video on GitHub as well.

Btw my JS is still a little noob-ish. :slight_smile:


Hello, here is my project:

Even though it took quite a lot of time, it still has lots of edge cases that are not taken into account. I took more heavy focus on code and documentation rather than UI.
Thank you @filip for such a great course. It helped to understand a lot (and understand that there much more to learn).


1 Like

hey @dan-i hope you are good i am trying to compile the code through node js but but sutck in one error hope you can help

here is my code:

// imports & defines

const path = require('path');
const solc = require('solc');
const fs = require('fs-extra');

// Functions

 * Makes sure that the build folder is deleted, before every compilation
 * @returns {*} - Path where the compiled sources should be saved.
function compilingPreperations() {
    const buildPath = path.resolve(__dirname, 'build');
    return buildPath;

 * Returns and Object describing what to compile and what need to be returned.
function createConfiguration() {
    return {
        language: 'Solidity',
        sources: {
            'test.sol': {
                content: fs.readFileSync(path.resolve(__dirname, 'contracts', 'test.sol'), 'utf8')
            'AnotherFileWithAnContractToCompile.sol': {
                content: fs.readFileSync(path.resolve(__dirname, 'contracts', 'AnotherFileWithAnContractToCompile.sol'), 'utf8')
        settings: {
            outputSelection: { // return everything
                '*': {
                    '*': ['*']

 * Compiles the sources, defined in the config object with solc-js.
 * @param config - Configuration object.
 * @returns {any} - Object with compiled sources and errors object.
function compileSources(config) {
    try {
        return JSON.parse(solc.compile(JSON.stringify(config)));
    } catch (e) {

 * Writes the contracts from the compiled sources into JSON files, which you will later be able to
 * use in combination with web3.
 * @param compiled - Object containing the compiled contracts.
 * @param buildPath - Path of the build folder.
function writeOutput(compiled, buildPath) {

    for (let contractFileName in compiled.contracts) {
        const contractName = contractFileName.replace('.sol', '');
        console.log('Writing: ', contractName + '.json');
            path.resolve(buildPath, contractName + '.json'),

// Workflow

const buildPath = compilingPreperations();
const config = createConfiguration();
const compiled = compileSources(config);
writeOutput(compiled, buildPath);

and here is the output:

Hi @Ritesh_Verma

Follow this FAQ: FAQ - How to downgrade Node.Js


still getting the same error when downgraded the nodejs to 10.21.0
my solidity version is 0.6.2

please open your terminal and type node -v. Post a screenshot here :slight_smile:

delete the folder build and node-modules then compile and retry.
If still fails push your code on GitHub and post the link here

Hey @ble4h

Congrats for your first dapp!
Some considerations for you :slight_smile:

uint public rate;
Is this used to exclude fees from the user bet?
If that is the case, there is a method you can call that returns the exact fees required to call the oracle.

In your function __callback() you are not checking the proof sent by the oracle.
This is something you can easily implement and that would make your contract much safer.

  function placeBet (uint input, uint amount) public returns (bool) {
    require (minBet <= amount && balance[msg.sender] >= amount && amount <= maxBet);

What happens if your contract balance is 1 ether, the user bets 1 ether and wins? Will your contract be able to pay the user?

You can find the docs here:
You can take a look at my project example here:

Well done once again!

done everything as you said still error isn’t resolved yet please help

Thank you, Dan. but I cannot add the value argument in the __callback function. Can you advise how I can read the value from the UI inside the __callback function? I cannot use the msg.value as well, because it does not allow me to use msg.value if the __callback function is not payable.

Thanks @dan-i for review feedback. Will note them as improvements in future projects. :slight_smile:

1 Like

You are more than welcome! If you need suggestions just let us know.

1 Like

Hi @Ritesh_Verma

I checked your repo and I see that you are not using Truffle.
Have you taken the Solidity 201 course? If not you can start from this video:

Happy learning,

Hey @Paul_Kwok

The callback function is called from an external contract, therefore you cannot pass it as parameter as you would usually do.
Maybe use value is not the right choice.

You could save it somewhere, a struct?



uint public rate;
This is just the payout rate if the bet wins. Usually not a good idea to just double it I think :slight_smile: Thanks for the tip on the gas. I did consider getting the cost of transaction to call the oracle and ‘tax’ the user as well but wanted to keep it simple.

If the user’s balance (on contract) exceeds the contract’s actual balance it wouldn’t be able to pay the user. So the contract would need to have a large enough balance in the first place.
I did think of adding a require if the bet is too large, and contract doesn’t have enough balance would be good. But the owner can add more ETH to the contract balance if needed.
But I was thinking of the contract always having enough (based on probability calculations) and there’s a MaxBet limit of 5 ETH. So, a user wouldn’t be able to keep doubling to ‘get back’ their losses after losing a losing streak. And the <2x rate helps with this too.

Thanks for the feedback! Will take a look at yours.

1 Like

Hi Dan,

Here is my github

can you give me some idea, why there is an error on function playflipCoin2, though I have not any transaction to pay the amount into the contract?

transact to Coinflip2.playFlipCoin2 errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.

Completed phase 2.
Not a very pretty front-end but does the job, wanted to learn solidity mostly. Will take the js for blockchain dev course after this.

Github url:

Seems to be working. :slight_smile: