Programming Project - Phase 1

Hey @Mucha_Julius

Seems like that function is missing in your contract ABI.
Migrate your project once again truffle migrate --reset then take the abi and retry.
If you keep getting the same error post your code here and I will take a look.

Happy learning,
Dani

1 Like

Coding a project takes always more than anticipated :slight_smile:
I like the result, well done :muscle:

2 Likes

Hey @Lucus

I checked you contract CointToss.
Follow my debugging step by step:

Letā€™s change it to return false.

  • You declared the function flip () as view but because you are modifying the contract state, you have to remove view.

function flip() external returns(bool)

  • This code will never be executed, therefore you have to move it before the return. Keep in mind that a function interrupts its execution as soon as if hits a return statement.
 else if(heads == false) { // if not heads(winning side), execute _;
            return(false); // not sure how to code this response
            attempts++; //1+ to attempts counter
        }

Fix these ones, there are other logic bugs that you will see once fixed these :slight_smile:

Try to play with them and keep me posted.

Cheers,
Dani

2 Likes

Hey @DylanKress

Please paste you contract code here, just by reading your function placeBet I cannot spot the error :slight_smile:

Happy coding,
Dani

1 Like

Thank you :smiley:
how would i change this around?
require(_setBet == 0 || 1, "please choose either 1 or 0")

1 Like

Hey @dan-i I posted the code a bit above

hey @Lucus

The correct syntax is
require(_setBet == 0 || _setBet == 1, "please choose either 1 or 0")

happy coding,
Dani

Hey @DylanKress

Yup I saw the screenshot, but I would like to copy and paste your code in remix to try it :slight_smile:

Please click on the icon shown below and paste your code there.

Schermata 2020-10-21 alle 12.57.22

pragma solidity =0.5.12;

contract CashFlip {

    //State Variables
      address payable public player = msg.sender;
      uint public playerBet;
      uint public playerGuess;
      bool public playerWin;
      uint public totalPayout;
      uint public oneWei = 1 wei;
      event alertWin ();
      event alertLoss ();
      event betSubmitted ();
      address payable public owner;

    //Sets Owner Properties
constructor() public payable {owner = msg.sender;} modifier onlyOwner() {require (msg.sender == owner, "Not owner!");_;}

    //View Contract Balance
function getBalance() public view onlyOwner returns (uint) {
    return address(this).balance;}

    //Deposit ETH to Contract
function depositETH (uint _amount) public payable onlyOwner {}

    //Withdraw ETH from Contract
function withdrawETH (uint _amount) public onlyOwner {
    owner.transfer(_amount);}

    //Intakes Player Inputs from Client-Side App
function placeBet (uint _playerGuess, uint _playerBet) public payable {
    playerGuess = _playerGuess;
    playerBet = _playerBet * oneWei;
    totalPayout = _playerBet * 2 * oneWei;
    emit betSubmitted ();}

    //Randomizes Coin Toss and Determines Win Conditions
function randomFlip () public {
    uint result;
        if (now % 2 == 0) {
            result = 0;}
            else {result = 1;}
        if (result == playerGuess) {
            playerWin = true;}
            else {playerWin = false;}}

    //Pays Player Upon Win
function payPlayer () public payable {
    if (playerWin == true) {
        msg.sender.transfer(totalPayout);
        emit alertWin ();}
    else {emit alertLoss ();}}


}
1 Like

Hey @DylanKress

Lets check the code.

function placeBet (uint _playerGuess, uint _playerBet) public payable {
    playerGuess = _playerGuess;
    playerBet = _playerBet * oneWei;
    totalPayout = _playerBet * 2 * oneWei;
    emit betSubmitted ();}
uint _playerGuess, uint _playerBet

As far as I do understand, _playerGuess should be 0 or 1 (head or tail), and _playerBet is the amount of Ether that the user wants to bet.

You do not want to have uint _playerBetas parameter because you have to use the value that the user is sending to the function () which is correctly set as payable.
You should also make sure that uint _playerGuess is either 0 or 1.

This should be:

function placeBet (uint _playerGuess) public payable {
    require(_playerGuess == 0 || _playerGuess == 1);
    playerGuess = _playerGuess;
    playerBet = msg.value;
    totalPayout = playerBet * 2;
    emit betSubmitted ();
}

Same thing for function function depositETH (uint _amount) public payable onlyOwner {}
You donā€™t need to ask uint _amount.

Regarding your function randomFlip():

function randomFlip () public {
    uint result;
    if (now % 2 == playerGuess) {
        playerWin = true;
        
    } else {
        playerWin = false;
        
    }
}

Schermata 2020-10-21 alle 13.14.21

Happy learning,
Dani

Hey @dan-i thanks for the feedback I really appreciate it! That all makes a lot of sense.

Now Iā€™m wondering how to call these functions in the correct order to automatically generate a result and pay the player if they win. I obviously wonā€™t be in the back end clicking each function sequentially like I can in remix and thatā€™s where Iā€™m really getting stuck.

I tried writing something like this and it didnā€™t work:

function placeBet (uint _playerGuess, uint _playerBet) public payable {
    playerGuess = _playerGuess;
    playerBet = _playerBet * oneWei;
    totalPayout = _playerBet * 2 * oneWei;
    randomFlip;
    payPlayer;}```

Any thoughts there?
1 Like

@DylanKress when programming you always have multiple ways to reach a solution.
I can tell you how I would do it but you can surely find your own way.

I would make the code easier with less functions.
At the moment you are asking the user to set a bet than play.
What I would to is just a function play() instead, let me show you what I mean.

event result (bool);

function randomFlip (uint _playerGuess) public payable  {
    
    require(_playerGuess == 0 || _playerGuess == 1);
    require (msg.value >= 1 ether);
    
    if (now % 2 == playerGuess) {
        msg.sender.transfer(msg.value * 2);
        emit result (true);
    } else {
        emit result (false);
    }
}

The function above simplify your code and your contract usability.
The user just needs to set a bet amount (msg.value) and a choice (_playerGuess).
The function will pay him if the playerGuess == now % 2 and emits true if the user won.

Easy and clear code :slight_smile:

One thing is missing in my function above, what happens if the user bets 1 ether and wins, but your contract does not have enough balance to pay?

Think about it and try to solve the issue (you will need a require statement).

Let me know,
Dani

1 Like

Wow very clear and simple and barely needs any state variables!!!

@dani69654 Thinking this would be the necessary solution to the issue you pointed out.

require (address(this).balance >= msg.value * 2);

Sound about right?

1 Like

Hey Dani, i already tried that, i have even remove completely metamask and install it again. Tried with diffrent acc in ganache. Always the same errorā€¦contracts are ok?

Also sometimes when i try to go in the contract on ganache, ganache frezzes(white screen) and i need to restart itā€¦

Sounds perfect @DylanKress :slight_smile:

Hey @Spartak

You have posted two different issues in your previous posts.

The first one was

ā€œALERT: Transaction Error. Exception thrown in contract code.ā€

And this is indeed related with your contract that was hitting a revert statement somewhere.

The new issue that you posted is different and depends by Metamask

RPC Error: Error: [ethjs-rpc] rpc error with payload {ā€œidā€:1642721289067,ā€œjsonrpcā€:ā€œ2.0ā€,ā€œparamsā€:

The only way to fix the 2nd one is indeed to reset Metamask which works 99.9% of the times. If this is not working for you I can suggest to try with a different browser but this should be really the last option.

Let me know,
Dani

1 Like

Sorry to bother you, but can you pls check main.js and Flip_coin contract that i posted?
I am new to programming so maybe i am missing something?

Hey Dani,

I changed up my code from scratch because I wanted to restart, last one felt sloppy.
Hopefully this one seems to function better than the last. Any suggestions or additions I should make?
(Can also be found https://github.com/lucusra/CoinToss./blob/main/Dapp.sol)

pragma solidity 0.7.0;

// SPDX-License-Identifier: UNLICENSED

contract CoinToss {

    uint public betChoice = 3;

    uint outcome;

    event BetOutcome(address userAddress, uint amount, bool winOrLose);

    function setBet(uint _setBet) external payable {

        require(msg.value == 1 ether, "please send 1 ether to play");

        require(_setBet == 0 || _setBet == 1, "please choose either 1 or 0");

        betChoice = _setBet;

    }

    function tossCoin() external payable {

        require(address(this).balance == 1 ether, "you must select 0 or 1 prior to tossing");

        require(betChoice != 3, "send 1 ether to choice between 0 or 1");

        

        outcome = block.timestamp % 2;

        

        if(outcome == betChoice) {

            msg.sender.transfer(msg.value*2);

            betChoice = 3;

            emit BetOutcome(msg.sender, msg.value, true);

        } else {

            betChoice = 3;

            emit BetOutcome(msg.sender, msg.value, false);

        }

    }

    

}
1 Like

Here is a picture of my app.
Source code here: https://github.com/cpontrelli/eth-coin-flip

1 Like

@Charlie_Pontrelli ready to jump into phase two!

1 Like