Programming Project - Phase 2

Hi @Paul_Kwok

Why is your function testRandom() calling __callback()?
It is most likely failing because of the require in callback

 function __callback(bytes32 _queryId,string memory _result,bytes memory _proof) public {
        
        require(msg.sender == provable_cbAddress());

When you see this error always look for a require statement that fails

VM error: revert. revert The transaction has been reverted to the initial state.

Finally after a loooong time!

https://github.com/kostka-tech/coin-flip-dapp

Hi there,

my code for the contract and the UI can be found at:
https://github.com/rkindle/Coinflip/tree/Optimization

Contract seems to be working fine. Have been upgrading it from my initial version to handle multiple games which seems to be working. The DApp is even usable but not conveniently as I am struggling with the use of events. Several attempts on doing so did fail and I am could not yet find where my mistake lays. The contract side seems to be fine but I am not managing to use the event listener.
I would highly appreciate some advice as all the resources I found on the web did not do the trick so far.

Thanks,
Ralf

@Taha My html and css took one hour and that was easy, but the smart contract is difficult for me, I’ve been trying for 3 days 6 hours a day and I only have this and I’m confused, I’ve tried to use minimum code due to gas costs any push towards the right direction would help alot!

and the modifier, I’ve used in in the function flip but I put msg.value because I want it to be the amount the user puts but I think it’s wrong, the code itself don’t give any errors in Remix IDE. But I know that it have no functionality…

pragma solidity 0.5.12;
import "./Ownable.sol";

contract CoinFlip is Ownable{

  uint public balance = address(this).balance;
 
  mapping(address => uint) balanceOf;
 
  modifier costs(uint cost){
       require(msg.value >= cost);
       _;
   }
    
  function pseudo() public view returns(uint){
    return block.timestamp % 2;
  }

  function getBalance()public view returns(uint){
      return address(this).balance;
      }

  function flip() public payable costs(msg.value) {
    
      if (pseudo() == 0) {
        msg.sender.transfer(msg.value * 2);
        balance -= msg.value;
      } 
       else {

          balance += msg.value;
     }
        
  }
  function withdrawAll() public onlyOwner returns(uint) {
        msg.sender.transfer(balance);
        return balance;
  }
  
  }

yes. I had been using truffle to finish part 1, but I found that it’s easier to debug on remix. once it’s debugged, I am going to use truffle for the testing and front end

Hi @rkindle

Congrats for your dapp!
I wrote an FAQ that hopefully clarify your doubts about events: FAQ - How to listen for events

Once you understood how to use events, check the web3 docs https://web3js.readthedocs.io/en/v1.2.11/web3-eth-contract.html#events and look for event.once (I think it’s the best solution in this case).

Happy learning,
Dani

Hi @Lamar

I edited your post to make you code readable.
When you post your code on the forum, click on the simbol:

And paste your code as shown:
Screenshot 2021-01-13 at 18.27.43

There are some logic errors in the code you’ve posted.

function flip() public payable costs(msg.value) {
        if (pseudo() == 0) {
            msg.sender.transfer(msg.value * 2);
            balance -= msg.value;
        } 
        else {
            balance += msg.value;
        }
    }

Consider the function above.
If a user bets 1 ether and wins, your contract will pay back 2 ether msg.sender.transfer(msg.value * 2); however your modifier costs only require require(msg.value >= cost);

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

In the same function:

 if (pseudo() == 0) {
            msg.sender.transfer(msg.value * 2);
            balance -= msg.value;
        } 

You are paying back msg.value * 2 but you are only decreasing the contract balance by msg.value.

Fix these bugs and try again.

Happy learning,
Dani

Tank you @dan-i, I will keep that in mind!

So if i change my modifier to modifier costs(uint){
require(balance >= msg.value * 2);
_;
}

Will that do the trick?

and I changed the balance -= msg.value to msg.value *2; will that solve it?

And still after this changes, I feel like I’ve have a long way to go to finish my smart contract, I’ve stucked with the idea that I have to use as little code as possible due to gas fees, even if this is just in the course but I can’t get that out of my head. What should I do next in the smart contract?
I have the js left also.

Hi @Lamar

This makes much more sense now :slight_smile:

So if i change my modifier to modifier costs(uint){
require(balance >= msg.value * 2);
_;
}

Will that do the trick?

and I changed the balance -= msg.value to msg.value *2; will that solve it?

At this stage, because you are learning do not be afraid of writing code.
Once you get used to Solidity you will be able to optimise your code.

Now you have two options to move forward:

1- Write tests in Javascript (as Filip teaches in the Solidity 201 course).
2- Write a basic GUI in javascript.

Once done you can implement the oracle so that you will use real random numbers and not a pseudo one.

Happy learning,
Dani

Oh sorry, I just noticed that I posted in the phase 2 when I’m in phase 1, lol!

Okay thanks, I will add some event handlers also in the smart contract but besides from that, is the smart contract okay to be used or do I need to add more functionality, and also, my mapping(address => uint) balanceOf; do i actually need this and why?

my mapping(address => uint) balanceOf; do i actually need this and why?

You are not using it I see. But you should tell me the reason behind that mapping since your code it :smiley:
Keep me posted and let me know if you have questions!

I used that line of code earlier in the first course, and I tought it was needed, but It’s useless cuz I don’t have a usecase for it. My code seem to work without it and but I got confused reading all the posts in the project on mapping, and I think it’s needed depending on how you code the smart contract right?

Hi @dan-i

I have finished the course. I am working on my own project. When I have questions which forum thread can I ask? Please let me know.

Thank you.

1 Like

Hey @oneworldcoder

The forum is focused on the Academy courses, but you can surely open your own thread and discuss your project with other students.
I might take a look from time to time to see how that is progressing.

Good luck with your project, this academy really gives you a solid knowledge that you have to use, increase and challenge.
Never give up :muscle:

Good luck colleague :slight_smile:
Dani

2 Likes

@dan-i I have a question, when I check the contract balance in ganache it shows 0 ether
but I’ve connected it to ganache, then why is my contract not getting the ganache address balance? Do I need to change my code in the smart contract?

Hi Dani,

thank you very much for the reply and the resources. I have read through them and the web3 documentation link is what I was looking into several times.
Still it seems not to be working for me as expected the following code from my main.js:

contractInstance.events.queryResultReceived({filter: {player: userAccount}, fromBlock:0}, function(error, event){console.log(event)});

Results in the following message in the developer console:

Uncaught TypeError: Cannot read property 'events' of undefined
    at main.js:48

This message does appear what ever I have tried it seems I am missing something very basic.
The initialization of the contract in my code is pretty close to what you have written in your FAQ

This is the solidity code from the contract for the event:
Definition:

  event queryResultRecieved(
    address indexed player,
    uint won,
    uint randomNumber,
    uint headstails
    );

Emition in _callback of provable:

emit queryResultRecieved(bets[_queryId].creator, won, randomNumber, bets[_queryId].headstails);

Sofar I was able to resolve all the issues I ran into by searching on the net an trying but this one is giving me troubles and it looks like I am missing something very basic.

Just in case my main.js code without the functions I call (left the comented event listeners in which I tested; also tried to put the event code at several location in the main.js to test):

var web3 = new Web3(Web3.givenProvider);
var contractInstance;
var contractAddress = "0xb69561B73f386D17B583Ec41c134A8a928169e14";
var coinSelection = "99";
var userAccount = "Not Connected";

$(document).ready(function() {
    window.ethereum.enable().then(function(accounts){
      contractInstance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]});
      userAccount = accounts[0];
      console.log(contractInstance);
      $("#playerAdress").text(userAccount);
    });
    contractInstance.event.queryResultReceived({filter: {player: userAccount}, fromBlock:0}, function(error, event){console.log(event)});
    /*
      contractInstance.event.queryResultRecieved({
        filter:{userAccount}
      ).on('data', function(event){
        var data = event.returnValues;
        console.log(data); // same results as the optional callback above
      }).on('error', console.error);*/

    /*contractInstance.queryResultRecieved({filter:{player: userAccount}
    }).watch(function(error, result){
      if (!error){
        console.log(data);
        console.log("Player " + result.player);
        console.log("Won " + result.won);
        console.log("Random Number " + result.randomNumber);
        console.log("Heads or Tails " + result.headstails);
      }
    });*/

    $("#flip_coin").click(flipCoin);
    $("#deposite").click(contractDeposite);
    $("#withdrawPartial").click(withdrawPartial);
    $("#withdrawAll").click(withdrawAll);
    $("#refresh").click(jackpotBalance);
    $("#getPlayer").click(lastResult);
    $("#initPayout").click(initiatePayout);
    $("#queryCheck").click(checkForQuery);
    $("#coin_heads").click(selectHeads);
    $("#coin_tails").click(selectTails);
    $("#players").click(getNumberOfPlayers);

});

Thank you,
Ralf

Thanks @dan-i. It will be great if you can suggest some.

Hey Ralf,

Wrap that in a function as I think that the code tries to read contractInstance before it is initialised.

 window.ethereum.enable().then(function(accounts){

.then() means that the function will be executed only when window.ethereum.enable is executed.
Move contractInstance.event inside the window.ethereum.enable function.

I have not tested it but give it a try and let me know :slight_smile:

Also feel free to look at my example project (nothing fancy just clear code for students to read): https://github.com/dani69654/CoinFlip

Have a nice weekend and keep me posted!
Dani

Hi @Lamar

when I check the contract balance in ganache it shows 0 ether
but I’ve connected it to ganache, then why is my contract not getting the ganache address balance?

Your contract does not get funded automatically by Ganache, you have to deposit ether into it.
Are you sending ether to your contract?

Regards,
Dani

Hi @KryptoS

Can you please clarify your question?
I wrote a long review of your project already :slight_smile:
Programming Project - Phase 2