Programming Project - Phase 1

Finally completed phase 1 of the project. https://github.com/Rolfarion/coinflip_dapp
It took me a while to figure out… But it was fun to do and i like the result! :grinning:

Also tried to make a little video to show functionality:

@Rolf
Amazing work done!

The contract is well written :+1:

Very precise, usage of events and modifiers and function visibility.

Keep it up!

1 Like

@Uyan
Keep up the learning.

All the best for phase 2. :+1:

1 Like

Ready to move to phase 2 of hooking up the oracle, here is phase 1.
I found all aspects fun; solidity, javascript and UI/UX thought process


@Lumyo
Apologies for the delay.
The problem was with the Kovan network, due to high influx of deployment, the test networks like Kovan, Ropsten etc. get slowed down.

I was easily able to deploy now:

Thanks

1 Like

Thanks ! It worked for me too now ! :slight_smile:

Hi Taha,

Sorry about the delay in posting this. I am enrolled in classes at University as well and I’m having a hard time balancing both. The link to the repository is below:

1 Like

After several tries and support of this forum, i present my first dapp.
Not perfect, but i like the result :slight_smile:

project

Source Code:

1 Like

Here is the progress I’ve made so far:

pragma solidity >=0.4.21 <0.7.0;

contract Coinflip{

    uint public balance;
    address internal owner;

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

    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }

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

    function coinflip() public payable costs(1000000000000 wei) returns(uint){
        require(msg.value >= 1000000000000 wei);
        uint betBalance = msg.value;
        uint toTransafer = 0;
        uint luck = random();

        if(luck == 1){
            toTransafer = betBalance *2;
            balance -= betBalance;
        }
        else{
            toTransafer = 0;
            balance += betBalance;
        }
        msg.sender.transfer(toTransafer);
        return toTransafer;
  }

    function random() private view returns(uint){
        return now % 2;
  }

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

It works in Remix. Now moving on to the testing phase.

1 Like

I need help with the migration file. I want to send funds to a coin-flipping contract

const Coinflip = artifacts.require("Coinflip");

module.exports = function(deployer, accounts) {
  deployer.deploy(Coinflip);

  // find out how to transfer ether to the contract upon deploymet
   Coinflip.msg.sender.transfer({from: accounts[5], to: Coinflip.address, value: web3.utils.toWei("100", "ether")});
};

Hey @rostyslavdzhohola

The migration file uses Javascript, therefore it won’t understand commands given by using Solidity language.
In order to send Ether to your smart contract during the deployment, you 1st need to make sure that your constructor is set to payable as per example below:

constructor () public payable {}

Then you migration should look like this:

const People = artifacts.require('People');

module.exports = function(deployer,networks,accounts) {
  deployer.deploy(People,{from:accounts[0], value:10**18});
};

I have added few lines just to test that the migration works fine and sends 1 ether (10**18) to my contract when deployed.

const People = artifacts.require('People');

module.exports = function(deployer,networks,accounts) {
  deployer.deploy(People,{from:accounts[0], value:10**18}).then(async () =>{
    let instance = await People.deployed();
    let balance = await instance.getContractBalance();
    console.log("The contract balance is: " + balance.toString());
  })
};

Cheers,
Dani

1 Like

Finished, all works but couldn’t get tests working properly

Hey @m8rix

Have you had issues with testing your smart contract with Truffle?
If you want help please pick a test that does not work so that we can check it together :slight_smile:

Cheers,
Dani

1 Like

Hi @dan-i,

This is my current results:

Actually, I had errors before commenting out the truffleAssert.eventEmitted too

     AssertionError: Event filter for flipResult returned no results
Events emitted in tx 0x76d01250a54903c30d90aec7959f685ad904f33949981f6705c47aa8e4660b54:
----------------------------------------------------------------------------------------
flipResult(0: 0xBA09012F2826f639E744A479808204B90b4f771A, 1: true, __length__: 2, player: 0xBA09012F2826f639E744A479808204B90b4f771A, result: true)
----------------------------------------------------------------------------------------

@filip
I am not sure why when I run the python server on local host I get this:
I know is some sort of config issue I am doing but not sure why it isn’t running my Coinflip contract.

Forget it I figured it out… I was running the server on the wrong folder.

Thank you very much, that helped a lot. I had made some changes because some parts of the code didn’t work on my computer. Question:
I assume that
then(async () =>{
could be replaced with

then(async function(){

Is that correct?

This is my testing phase:
I’ve learned the usefulness of constructors and how to send ether with
let instance = await Coinflip.new({from: accounts[0], value: web3.utils.toWei("3", "ether")});

const Coinflip = artifacts.require("Coinflip");
const truffleAssert = require("truffle-assert");
const Web3 = require("web3");

contract("Coinflip", async function(accounts){

  let instance;

  before(async function(){
    instance = await Coinflip.deployed();
  });

  let smallBet = web3.utils.toWei("0.4", "ether");
  let bigBet = web3.utils.toWei("10", "ether");

  it("should increase or decrease the Coinflip value by the betting amount", async function(){

    console.log("The balance before is: " + await instance.balance());

    await instance.coinflip({from: accounts[1], value: smallBet});

    let balance = await instance.balance();
    let floatBalance = parseFloat(balance);
    let realBalance = await web3.eth.getBalance(instance.address);

    console.log("Did you win? " + ((await instance.win_loose()) ? "Yes |:)" : "No |:("));
    console.log("The balance after is: " + await instance.balance());

    if(await instance.win_loose() == true){
      assert(floatBalance == web3.utils.toWei("2.6", "ether") && floatBalance == realBalance, "Amount didn't decrease ");
    } else {
      assert(floatBalance == web3.utils.toWei("3.4", "ether") && floatBalance == realBalance, "Amount didn't increase");
    }

    console.log("The balance after is: " + await instance.balance());
    console.log("Did you win? " + ((await instance.win_loose()) ? "Yes |:)" : "No |:(" + "\n"));

  });
  it("should pass the coinflip function", async function(){
    console.log("The balance() before is: " + await instance.balance());
    await truffleAssert.passes(instance.coinflip({from: accounts[1], value: smallBet}));
    console.log("The balance() after is: " + await instance.balance());
    console.log("Did you win? " + ((await instance.win_loose()) ? "Yes |:)" : "No |:(" + "\n"));
  });
  it("should fail to pass with bet which is lower than the contract balance", async function(){
    await truffleAssert.fails(instance.coinflip({from: accounts[1], value: web3.utils.toWei("0", "ether")})
      , truffleAssert.ErrorType.REVERT);
    console.log("The balance() is: " + await instance.balance());
  });
  it("should fail to prcess coinflip() with bet bigger than the account balance", async function(){
    await truffleAssert.fails(instance.coinflip({from: accounts[1], value: bigBet})
    , truffleAssert.ErrorType.REVERT);
  });
  it("shlould allow owner to withdraw the balance", async function(){
    await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
    console.log("The balance() is: " + await instance.balance());
  });
  it("should not allow non owner to withdraw the balance", async function(){
    let instance = await Coinflip.new({from: accounts[0], value: web3.utils.toWei("3", "ether")});
    await truffleAssert.fails(instance.withdrawAll({from: accounts[5]}), truffleAssert.ErrorType.REVERT);
    console.log("The balance() is: " + await instance.balance());
  });
  it("the contract balance() after the withdrawAll should be 0 ", async function(){
    let instance = await Coinflip.new({from: accounts[0], value: web3.utils.toWei("3", "ether")});
    await instance.withdrawAll({from: accounts[0]});

    let balance = await instance.balance();
    let floatBalance = parseFloat(balance);
    let realBalance = await web3.eth.getBalance(instance.address);

    assert(floatBalance == web3.utils.toWei("0", "ether") && floatBalance == realBalance, "Contract balance wasn't 0 after withdrawAll()");
    console.log("The balance() is: " + await instance.balance());
  });
  it("owner balance should increase", async function(){
    let instance = await Coinflip.new({from: accounts[0], value: web3.utils.toWei("3", "ether")});

    let balanceBefore = parseFloat(await web3.eth.getBalance(accounts[0]));
    await instance.withdrawAll({from: accounts[0]});
    let balanceAfter = parseFloat(await web3.eth.getBalance(accounts[0]));

    assert(balanceBefore < balanceAfter, "Balance of the owner did not increase");
  });
});

Hey @m8rix

I had a look at your code.

There were two issues in CoinFlip.sol, let’s consider the flow:

1st issue:

  • User calls the function flip ();
  • flip () calls the function testRandom();
  • testRandom() calls __callback() that does operations then deletes waiting[_queryId].

The issue here is that your function testRandom() will never return queryId to the function flip () therefore your struct does not get populated.

The 2nd issue is in the function __callback().

Consider your statement:

if(random == 1) {
			address(uint160(waiting[_queryId].player)).transfer(waiting[_queryId].value * 2);
			contractBalance -= waiting[_queryId].value;

In this case, which is the user wins case, you should subtract waiting[_queryId].value * 2.

Now let’s go into coinfliptest.js

If I well understand your testing, the assert statements are wrong.

it("should payout when flip is won")

In this case newBalance should be higher than balance.

The opposite if for it("shouldn't payout when flip is lost").

Schermata 2020-09-16 alle 10.19.11

I won’t write here all your code fixed because it’s too long. Try yourself, if you need help just DM me and I will be happy to send you the code.

Happy learning,
Dani

1 Like