Programming Project - Phase 2

Thank you so much for posting this, you are my lord. I’ve been stuck on this for the past day and this was my exact issue. Thanks! :smiley:

1 Like

Hey @enrico

I haven’t forget about you, I tried to use your contract but seems like you are not receiving a callback from the oracle.
https://ropsten.etherscan.io/address/0xA136105c17d677FcF8a601BC5A75659c67712F3D

I am trying to deploy a new instance of your contract with few modifications but Ropsten today does not want to cooperate
Screenshot 2021-01-29 at 14.31.06

I will update you asap.

Cheers,
Dani

1 Like

I’m stuck with an issue mate!
I want the user to choose Heads(0) or Tails(1)
for now the player wins if randomNumber is 0 but I want to change that so the player choose but dunno how to do it…


        if(randomNumber == 0){
            betting[_queryId].result = true;
            betting[_queryId].player.transfer((betting[_queryId].totalBet) * 2);
            balance -= betting[_queryId].totalBet * 2;

Hey @Lamar

Your function will have a parameter (example: uint _choice) and your function will contain something like

if(randomNumber == _choice) {
    ... code for user win
} else {
    ... code for user loss  
}

This is the general idea, improve it and make sure to verify the user input.
Keep in mind that a coin flip game is basically a boolean choice (false or true , 0 or 1).
Make sure that the user _choice is either 0 or 1 :slight_smile:

I wrote a easy to read contract if you want to take some inspiration: https://github.com/dani69654/CoinFlip/blob/master/contracts/CoinFlip.sol

Keep me posted,
Dani

Hey there Dani,
I appreciate your help, I am still getting an error when trying to install npm i @truffle/hdwallet-provider
Again any and all help is appreciated. I haven’t been able to solve this on my own and have spent an embarrassing amount of time stuck on it. I have re-watched the course and have carried on to writing my own contracts and practicing getting to the point of having my contracts running in ganache and experimenting with front-end programming and connecting the two. Here is picture of the error I get when running the above command:

I have 1 test eth in my wallet whos mnemonic is in my .secret file, my project secret and ID from infura are entered in the correct places in my config.js file however when I truffle migrate --network ropsten I get:

Again any and all help is most appreciated. Thanks for your time.

Thank u so much!

But I’m totally confused, or just a bit:P

When you have time, could u please take a look at my git to see how off I am and what to do…?
https://github.com/liberacion/coinFlip/blob/main/coinFlipDapp.sol

Thanks!

1 Like

I got it deployed to ropsten using remix but I’d love to know where I’m going wrong using truffle

Here is my Coin Flip dApp deployed on the Ropsten testnet! I don’t think my recording software could capture when I moved away from the main browser window to interact with Metamask, but everything works correctly. In the future, I’m hopefully going to swap Bootstrap for React for the UI.

Github: https://github.com/matthewwatman/coinflip-dapp

Recording: https://drive.google.com/file/d/1TzoOlrsN8DajAW-v_0GKa_hXVUFSTu3-/view?usp=sharing

1 Like

Hi @okcrypto

From your screenshot I can confirm that you are not facing any issue with your hd wallet provider.
The error message you see in the screenshot below is telling you that your wallet does not have enough funds to migrate your contract.
Screenshot 2021-02-01 at 11.35.27

Consider the mnemonic phrase you are using, make sure that the 1st account has enough funds and you will be able to deploy.

Happy coding,
Dani

Hi @Lamar

You have to save the user choice in your function flip then you compare that choice with the random number in function _verifyResult.

Also your function update should return the queryId otherwise you cannot use the queryId as key for the mapping betting in your function flip.

function flip(uint _choice) public payable costs(0.01 ether) {
      require(_choice == 0 || _choice == 1);
      require(wait[msg.sender] == false);

      wait[msg.sender] = true;

      update();
      
/** 
 * How can you use queryId if it is not returned?
*/
      betting[queryId] = Bet({player: msg.sender, totalBet: msg.value, result: false}); 

      emit betPlaced(msg.sender, queryId, msg.value);
  }
1 Like

Thanks I’`m trying to solve this but the queryId is killing me. As soon as I change something I get totally confused, have had to little sleep I think:P

I have a state var as u can see below, and in the update function when making the call to the oracle I put that in the state variable, is that okay?
I’m totally lost with saving the user choice in the flip because of the querys, I think I need a couple of hours break:P

When reading your code I get a bit confused of all the queryId’s id _queryId etc.

And when I want to return that, I have it in the state var while you use query_id to put the call in and thereafter using mapping u put it in the Id of your struct.

ps. Thanks for the help, I really appreciate it!!

bytes 32 queryId;

//update
queryId = provable_newRandomDSQuery(
           QUERY_EXECUTION_DELAY,
           NUM_RANDOM_BYTES_REQUESTED,
           GAS_FOR_CALLBACK
           );

Hey @Lamar

Sorry I have not noticed that you are using a state variable to save the query id.
That is not a good choice, as you need to consider that multiple players can use your contract therefore that variable would change continuously.

I strongly suggest to remove that state variable.

Check this out:

function flip(uint _choice) public payable costs(0.01 ether) {
      require(_choice == 0 || _choice == 1);
      require(wait[msg.sender] == false);

      wait[msg.sender] = true;

      bytes32 queryId = update();

      betting[queryId].player = msg.sender;
      betting[queryId].totalBet = msg.value;
      betting[queryId].choice = _choice;
      // No need to set `result` to false because it is false by default.
      emit betPlaced(msg.sender, queryId, msg.value);
  }
  function update() internal returns (bytes32) {
       uint256 QUERY_EXECUTION_DELAY = 0;
       uint256 GAS_FOR_CALLBACK = 200000;
       bytes32 queryId = provable_newRandomDSQuery(
           QUERY_EXECUTION_DELAY,
           NUM_RANDOM_BYTES_REQUESTED,
           GAS_FOR_CALLBACK
           );
       emit LogNewProvableQuery("Provable query was sent, standing by for the answer");
       return queryId;
   }
function _verifyResult (uint _randomNumber, bytes32 _queryId) internal {

        if(_randomNumber == betting[_queryId].choice){
            betting[_queryId].result = true;
            betting[_queryId].player.transfer((betting[_queryId].totalBet)* 2);
            balance -= betting[_queryId].totalBet * 2;
        }
        else{
            betting[_queryId].result = false;
            balance += betting[_queryId].totalBet;

        }
        delete(betting[_queryId]);
        delete(wait[betting[_queryId].player]);

        emit betRecieved(betting[_queryId].player, _queryId, betting[_queryId].choice,      betting[_queryId].totalBet, betting[_queryId].result);

}

If I was you, I would implement another requirement in your function flip() to make sure that your contract has enough balance the pay the user in case he wins :slight_smile:

thanks for your help :slight_smile:

Ok, I have to do this now or I’ll end up tweaking the details forever.
Here is the repo: https://github.com/slavab77/Cointoss


1 Like

Thank u so much!

If I put in in my struct then? instead of a state var at top I could put it in my struct?

And about the require, thanks for taking that up, I wanted to as you if my require statement is good or not. I’m using this modifier for my flip function:)

modifier costs(uint cost){
       require(balance >= msg.value * 2);
       require(msg.value >= cost && msg.value <= 1 ether, "min bet is 0.01 ether and max bet is 1 ether");
       _;
   }
1 Like

Hey @dan-i sorry been mad busy on other crypto projects.

So i go to my Project folder with PS.

S E:\Crypto\Etherium-course-advanced\Coinflip> ls

then after i run ls

i see

`Directory: E:\Crypto\Etherium-course-advanced\Coinflip

Mode LastWriteTime Length Name


d----- 14/12/2020 20:45 build
d----- 14/12/2020 20:35 contracts
d----- 14/12/2020 20:35 migrations
d----- 14/12/2020 20:35 test
d----- 14/12/2020 20:15 Frontend
d----- 19/01/2021 21:16 node_modules
-a---- 01/02/2021 21:16 4254 truffle-config.js
-a---- 01/02/2021 21:20 73 .Secret
-a---- 19/01/2021 21:17 102558 package-lock.json`

next command i run is npm install truffle-hdwallet-provider

then NPM WARN appear.

“See image”

1 Like

I noticed that u use add/sub etc using safemath, does that lower gas cost or is it more for security reasons?

1 Like

Hey @Rob_McCourt nice to have you back :slight_smile:

The package you’re trying to install is deprecated, use this one instead npm i @truffle/hdwallet-provider

Cheers,
Dani

1 Like

Hey @Lamar

It is for security reason, use SafeMath is not an option but it is mandatory.
Without SafeMath your project can be hacked.
Once you’ve completed the Solidity 201 course, I highly suggest the Smart Contract Security course (my favourite one): https://academy.ivanontech.com/products/ethereum-smart-contract-security

Have a great day!
Dani

Hey @enrico

You have modified the default uint256 GAS_FOR_CALLBACK = 20000; therefore the oracle contract does not have enough gas to call your contract back.
Set the value back to 200000.

Cheers,
Dani

1 Like