Programming Project - Phase 1

running into some issues with balance of contract owner

// SPDX-License-Identifier: MIT
pragma solidity 0.5.12;

contract FiftyFiftyBettingExchange {

    enum FlipResult { Heads, Tails}

    address public owner;
    uint public balance;

    constructor() public {
        owner = msg.sender;
        balance = msg.sender.balance;
    }

    modifier restricted() {
        if (msg.sender == owner) _;
    }

    function randomFlipResult() private view returns (FlipResult){
        return (now % 2 == 0) ? FlipResult.Heads : FlipResult.Tails;
    }


    function headsOrTails(FlipResult guess) public payable returns (FlipResult){
        require(guess == FlipResult.Heads || guess == FlipResult.Tails, "You must make a guess");
        require(msg.value > 0, "You must bet more than zero");
        require(balance <= msg.value, "Contract cannot accept a bet this size right now");

        //perform coin Flip
        FlipResult flipResult = randomFlipResult();




        if(guess == flipResult){
            //move from owner acc to sender
            balance -= msg.value;

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

        }else{

            balance += msg.value;
        }

        return flipResult;

    }
}

@Emmett
Thanks for reaching out!

To check an address balance, we use mapping

For example:
mapping(address=>uint) public balance;

To execute:
balance["0xsda......"]

Will give output as uint in wei

Hello, here are the screen shots for phase 1 of the project

2 Likes

@Taha but I don’t think I need to store any mapping of address balances. The only balance I need to store is the contract owner balance surely.

User making the bet just sends in a bet amount , then as long as the contract hs enough of a balance to match this then the bet can take place . (sure the contract can eventually go bankrupt but thats another issue)

To send funds to the contract, you need a payable fallback function.

source: https://solidity.readthedocs.io/en/v0.5.3/contracts.html#fallback-function

Check out this example:

//payable fallback function
function() external payable {
    }

//your flipCoin function
function flipCoin () public payable costs(100 wei) {
        require(msg.value <= (houseBalance / 3), "The bet amount cannot exceed the payable jackpot!");

        if (random() == 0) {
          //Winning
            result = true;
            reward = msg.value;
            msg.sender.transfer(reward * 2);
        } else {
            result = false;
            //address(this) give the address of the current contract
            address(this).transfer(msg.value*2)
        }
        houseBalance -= reward;
        emit FlipCoinResult(msg.sender, result, reward);
    }

As you can see this needs to be done with the contract address.

Yes address(this) gives you the current contract address. It is an in-built solidity function which helps you to get the address of the current contract.
address(this).balance help you get the balance of the current contract.

To enable sending funds to the contract, you need a fallback function
https://solidity.readthedocs.io/en/v0.5.3/types.html#contract-types

Mapping is needed to get the balance of an address.
What error are you getting?

Hope this helps!

Happy coding :slight_smile:

@CodyM
Great to see you progress!

In this function from your contract:

 function flipCoin () public payable costs(100 wei) {
        require(msg.value <= (houseBalance / 3), "The bet amount cannot exceed the payable jackpot!");

        if (random() == 0) {
          //Winning
            result = true;
            reward = msg.value;
            msg.sender.transfer(reward * 2);
        } else {
            result = false;
            reward = -msg.value;
        }
        houseBalance -= reward;
        emit FlipCoinResult(msg.sender, result, reward);
    }

can you elaborate line:
reward = -msg.value?

or it should be

reward -= msg.value ?

Overall, the contract looks fine,

  1. :+1: You are declaring function call fee in flipCoin()

Try adding onlyOwner modifier and safemath library.

Happy coding :slight_smile:

@Emmett
Apologies, are you talking about contract balance or contract owner balance.

Here it looks like contract owner balance. :thinking:

Here you are asking for contract balance :slight_smile:

We can get contract balance with address(this).balance

You can also add the following validation for checking whether the contract has enough balance for the player to place bet or not.

require(address(this).balance >= ((amountBet) * 2),"Not enough balance in pot to cover your bet");

Hello, after couple of days i manage to put everything together but still i cant figured out how to setup my coin action gif for my bet actions loading/win/loose. As well i struggled to get user balance and contract balance on the website.
here is my GitHub https://github.com/p4perclip/Coinflip
Rest seams to work fine, i just want to finish my front end before i start Phase 2 and testing.

Screen from transaction:

I’m having an issue with testing my contract. The first test passes as expected, but the second test does not. I am expecting it to fail as I have requirements of at least 20 finney and that only the owner can deposit. It keeps reverting the second test.

const FlipOut = artifacts.require("FlipOut");
const truffleAssert = require("truffle-assertions");

contract ("FlipOut", async function(accounts){
    let instance;
    let owner;
    let user;

    const finney_0 = await web3.utils.toWei("0", "finney");
    const finney_1 = await web3.utils.toWei("1","finney");
    const finney_10 = await web3.utils.toWei("10", "finney");
    const finney_11 = await web3.utils.toWei("11", "finney");
    const finney_19 = await web3.utils.toWei("19", "finney");
    const finney_20 = await web3.utils.toWei("20", "finney");
    const finney_50 = await web3.utils.toWei("50","finney");
    const finney_500 = await web3.utils.toWei("500","finney");
    const ether_1 = await web3.utils.toWei("1", "ether");

    beforeEach(async function(){
        instance = await FlipOut.new();
        owner = accounts[0];
        user = accounts[1];
    });


    it("Should allow owner to deposit at least 20 finney into the contract", async function(){
        await truffleAssert.passes(await instance.depositToContract({value: finney_20, from: owner}), truffleAssert.ErrorType.REVERT);
        await truffleAssert.passes(await instance.depositToContract({value: ether_1, from: owner}), truffleAssert.ErrorType.REVERT);
    });

    it("Shouldn't allow owner to deposit less than 20 finney into the contract, nor should it allow user to add funds", async function(){
        await truffleAssert.fails(await instance.depositToContract({value: finney_50, from: user}), truffleAssert.ErrorType.REVERT);
        await truffleAssert.fails(await instance.depositToContract({value: finney_19, from: owner}), truffleAssert.ErrorType.REVERT);
    });

})

I have commented out the lines one at a time and they are both failing (or rather not passing as I expect them to fail). I have changed both of them to truffleAssert.passes instead of ā€˜fails’ and they still don’t work. I have gone over the code many times and can’t see why the truffleAssert function is not working for these tests…any suggestions from anyone in the know??

I’ve done some work. It looks like working, but I took an event result from a request result like the below… And I feel it’s weird because it’s not getting the result directly from the ā€œeventā€. What’s the proper way to get the event results?

 contractInstance.methods.flip(side).send(config)
    .then(res => {
        var result = res.events.coinFlipped.returnValues.result;

1 Like

I am confused with some things… in my migration when I do this:

deployer.deploy(FiftyFiftyBettingExchange, {value: web3.utils.toWei("10","ether"), gas: 6000000});

Does this call the constructor or is this a different kind of operation?
Does the constructor need to be payable to do this. And which account is the eth coming from ?
Does this transfer balance from the owner automatically to the contract ? and of so do I even need to store an owner balance variable in the contract ?

And over at the UI side:
if I do
contractInstance = new web3.eth.Contract(abi, "0x2c2D9E87eCFbCb9758df8cf063C71d3C9DBE5304", {from : accounts[1]});

this calls the constructor right ? and gets a kind of local interface to the remote contract that resides on the blockchain

Phase 1.

phase1

Step 1: You can hide all the gif elements on load of index.html

<script type="text/javascript">
      $("#coin_fliped").hide();
      $("#big_win").hide();
      $("#big_loose").hide();
    </script>

Step 2: in your main.js
when the user wins, while calling the win function

      $("#big_win").show();

when the user looses, while calling the lost function

      $("#big_loose").show();

When loading

      $("#coin_fliped").show();

and use hide(), wherever necessary.

I also see that you have created a function named bet() which give the result but you haven’t called it

Please do the above :slight_smile:

To get contract balance change to this in your getBalance():

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

address(this).balance should return the balance of the current contract.

To get balance of the user you need to specify the address of the msg.sender, that is the caller of the function

function getBalance(){
  contractInstance.methods.getBalance().call({from: 'your address').then(function(result2){
    newResult1 = web.utils.fromWei(result2, "ether");
    console.log(newResult1);
    $("#balance_output").text(+newResult1);
  });
}

Hope this helps

Please feel free to reach out for further queries!

2 Likes

@azu
Thanks for reaching out!

You need to call event with parenthesis, that is ()

I don’t see you adding parenthesis to event coinFlipped({}, ...)
Also its better for you to use a callback function to know whether the result fails or passes.

Example:

myContract.events.MyEvent({
    filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23
    fromBlock: 0
}, function(error, event){ console.log(event); })
.on('data', function(event){
    console.log(event); // same results as the optional callback above
})

reference: https://web3js.readthedocs.io/en/v1.2.0/web3-eth-contract.html#contract-events

1 Like

@cryptocrom
I don’t see any problem with the code you have shared.
Can you please share the complete code on Github?

2 Likes

Yes, this calls the constructor.

Yes, the contractor needs to be payable and the ETH is coming from the msg.sender's account. The account/address deploying the contract.

If this is what you have mentioned in the contract. That 10 ETH should go to the contract then that will happen.

If you would like to know the owner balance, then you will need the variable.

Yes.

1 Like

Will do, I’ll set up an account later today if I get a chance and link when done, cheers

Hey mate,

I hope this is right and everything you need. I haven’t oploaded the html, css and js files for the front end to my github yet as I’m still working on them.
Also, some of the tests in the truffle testing are unfinished, I was working on them but until I solve the issue I just left it as is and went on to the front end stuff.

Thank you @Taha!
I’ll try with that way.

1 Like

@Taha I’m having a bit of trouble with unit testing. My coinflip app works in Solidity. The other tests I have work fine, e.g.:

Example Unit Test
it("should be able to bet on heads", async function(){
    await truffleAssert.passes(instance.flipCoin(1, {value: web3.utils.toWei("0.02", "ether")}));
  });

I’m writing a test to check that the better is paid if they win. It looks like this:

'Payment Successful' Unit Test
it("should pay the better if they win", async function(){
    await instance.flipCoin(1, {value: web3.utils.toWei("0.02", "ether")});
    const randomResult = await instance.random();
    while (random() != 1){
    //while (headsOrTails != random()){
      await instance.flipCoin(1, {value: web3.utils.toWei("0.02", "ether")});
    }
    await truffleAssert.passes(msg.sender.transfer(2 * msg.value));
  });

Whether I write let or const or just await instance.random();, the following error appears:

Error Details

The random function in question is exactly the one provided in the lecture videos. Does anyone know what the problem is? Hopefully I provided enough info.