Programming Project - Phase 2

To all the students with the gas error in Ropsten.

Please try to deploy now, I had the same issue today but it seems fixed.

Cheers,
Dani

2 Likes

For me it was the same, but setting the gas to 4 000 000 worked.

The faucet, though, drips again. It didn’t yesterday and before.

Is there any way to test for time requirements by unit testing? If I need a certain amount of time to pass before a function can be executed, how do I test this? Thanks

Hey @JeffE

I have replied here: Ethereum coinflip dapp discussion
I look at all the topics so no need to post the question in two different ones :slight_smile:

Let me know if you need help.

Cheers,
Dani

1 Like

So, having finally deployed the contract, I tried my dapp and found out that you can place a bet and you can deposit, but cannot win anything or withdraw.
It looked like the contract was never even calling the oracle. So I went back and tried to just re-write Filip’s Oracle code in Remix. It compiles and deploys for me, but when calling the update function, I get this:

image
If it is an issue in my Metamask, it would also stop my dapp from getting anything from oracle…?

Hey @MarcisB

That is not an issue with Metamask, you contract is most likely hitting a revert() statement.
Have you deployed you contract on Ropsten?

Also keep in mind that the first call to the oracle is free, all the other ones have a fee that is paid by your contract.

If you are calling update() in you constructor when you deploy your contract, you are basically using your free oracle call, make sure that your contract has enough funds to pay the fee for the next calls.

Try these things, if you still have the issue post your code here.

Cheers,
Dani

2 Likes

Hi all,

finally I also got this betting app running. However, I have to admit that the interface is still very clumsy.

Let me right away note that I did not implement the oracle solution. In my opinion it trades miner manipulation for oracle provider manipulation, which might be just as bad. I think I have come up with an onchain solution that can neither be exploited by attacking contracts, nor by miners (at least not in a way that is profitable for them). Though a short search on the web did not yield any results, it is of course possible that this is already well-known and that I am reinventing the wheel here… or that it can be exploited in a way that I did not think of…

No matter what, I am very interested in your opinions, insights and thoughts on the idea! Let me get into it:

Description

Betting vs. a liquidity pool

I have implemented a liquidity system, where providers can deposit/withdraw ethereum to the contract.
Over time, they will earn money through fees. However, in the short term they also might lose money, if the players get lucky and win a disproportionally large amount of their bets (by chance). In the long run these fluctuations should cancel out.

Source of randomness

The main idea is to use a FUTURE blockhash (at a fixed block height relative to the placement of the bet) together with the players address. In combination with a maximum bet amount and the rule that each address can only place one bet at a time, this construction makes miner manipulation infeasible.

The important lines of code are:

  function won() public view returns(bool){
    require(bet[msg.sender].amount>0,"nothing to evaluate");
    require(bet[msg.sender].blocknr+1<block.number,"too early to evaluate");
    if (block.number>bet[msg.sender].blocknr+n256) {return(false);}
    if (uint(keccak256(abi.encodePacked(blockhash(bet[msg.sender].blocknr+1), msg.sender)))%2==1){return(true);}
    else {return(false);}
  }

Here n256 is simply 256. (For testing it is convenient to reduce this number…)
bet[msg.sender].blocknr corresponds to the block number when the bet was placed.

Note that this system needs to have access to the blockhash of the block following the block where the bet was placed. Since this is only possible for the 256 last blocks, older bets will automatically be counted as lost, if the player didnt claim his win until then.

Contract address

The current version of this contract is deployed at the address 0xB04D24fac12D10e29bEe4dbD135A6C4BBE080487 on the kovan test network.
In order to test the contract using the interface in the repository (linked below) you can start a local http server (e.g., using python3, by ā€œpython -m http.serverā€ in the root directory of this repository). Then connect to it (usually http://127.0.0.1:8000) in your browser and connect your metamask using kovan testnet.

What do you think? Would this work, or is it flawed in some way? (That there will be bugs is clear… I mean the general idea.)

Thank you all already! And thx to @filip for the nice course. You were completely right that coding a project on ourself is the best practice afterall. I watched a fair amount of videos of the course again to get it done;)

Best,
Philipp

1 Like

Hi guys, I run into a problem I cannot overcome…

when deploying my contract with truffle on ropsten and sending flip() tx I get alert in my metamask: ā€œTransaction error. Exception thrown in contract code.ā€ after confirming this transaction fails…
In remix I get the same notification as MarcisB (Gas estimation failed)…
Do you have any advice?
Here is my code: https://github.com/Ulakal/Coin-Flip-phase-2

Hi Ula,

i am not sure, but I guess this require statement,

        require (waiting[msg.sender] = false);

in your setAbet function throws. You need a == here.

Best,
Philipp

2 Likes

Have you tried resetting your account in Metamask? I’ve found this works for me most of the time. I’ve noticed Metamask throwing errors when I change things like the from account or gas to be sent etc. Hopefully that does the trick, otherwise good luck solving the issue…

Yep, I didn’t give it enough gas :man_facepalming:t5:
Thanks!

This is the current state of my project:

  • The contract works as expected - it communicates with the oracle and sends money to the player in case of a winning bet.
  • I couldn’t get the event listener to work. Nothing appears when the __callback is executed.
  • withdraw works only if I pass the desired value in wei. If I try this:
    let withAmount = $("#withdraw").val();
    let withConfig = {
        value: web3.utils.toWei(withAmount,"ether")
    }

or this:

    let withAmount = $("#withdraw").val();
    let withConfig = withAmount*1e18

I get this:

withdrawErr

Here is the GitHub:

Also, I’m still trying to figure how to upload the node_modules folder.

Hello, I’m having some trouble with phase 2 of the project. I’ve struggled for a week trying to find a solution on my own but I couldn’t find out what is wrong.

All the problems can be found here, in the Coinflip_vOracle.sol file:

Github Link

https://github.com/Uy4n/Coinflip_vOracle

Current problems:

  • If I uncomment require(msg.sender == provable...), then the code fails to deploy on Remix.

  • The flipCoin function seems to work on Remix, but the player’s balance never changes after making a bet. This leads me to believe that the code is not working. I’m guessing it might be because I’m not using a real testnet, so I can’t properly use the provableAPI.sol file and the associated __callback function.

The withdrawFunds and getBalance functions work.

Is there any more testing I can do on Remix, or do I have to migrate myself to a real testnet (e.g. Ropsten) to fully test my code?

Hello.
You can find my project in github: https://github.com/acul71/FlipCoin_with_Oracle/
And see a demo video here: https://youtu.be/bix-_HLK66I

Bye Luca
Note: I declared the event listener just once otherwise if I put it in the bet function (called every time the user make a bet) I have 2,3,4…n event listener as n bets

         // Handle the betResult event
        contractInstance.events.betResult( (error,res) => {
            if(error) {
                console.log("error=", error)
                myAlert(`Error: ${error}`, "alert-danger", 5000)
            } else {
                console.log("betResult res=", res)
                const win = res.returnValues.value
                console.log("win=", win)
                if (win > 0) {
                    msg = "CONGRATULATION YOU WON " + web3.utils.fromWei(win.toString()) + " ether"
                    myAlert(msg, undefined, 5000)
                    textareaAdd(msg)
                } else {
                    //myAlert(`SORRY YOU LOST ${betAmount} ether`, "alert-danger", 5000)
                    msg = `SORRY YOU LOST !`
                    myAlert(msg, "alert-danger", 5000)
                    textareaAdd(msg)
                }
                updateBalance()
            }
            
        })
1 Like

I tested my contract with remix and it was working.
require(msg.sender == provable…) the code fails to deploy for what reason ? (Report the error go the red highlight)
The starting code of the contract for remix is this:

// SPDX-License-Identifier: MIT
import "./Ownable.sol";
//import "./provableAPI.sol";

import "github.com/provable-things/ethereum-api/provableAPI.sol";
pragma solidity 0.5.12;

contract FlipOracle is Ownable, usingProvable {

To test make sure you are in ENVIRONMENT: injected Web3
This is what it looks like when you are deploying:

Also you can try the provableAPI test in remix and see if it works (remember that you have to wait 1 minute or so to get the oracle to call the __callback funcion):

1 Like

@MarcisB

I couldn’t get the event listener to work. Nothing appears when the __callback is executed.

https://web3js.readthedocs.io/en/v1.3.0/web3-eth-contract.html?highlight=events#contract-events

Declare a listener for the event generatedRandomNumber in main.js:

contractIstance.events.generatedRandomNumber( (error,res) => {
            if(error) {
                console.log("error=", error)
            } else {
                console.log("res=", res)
                // Do your stuff
           }
})

1 Like

Hey @Ula

What suggested by @smileBTC is correct.
Check this require statement require (waiting[msg.sender] = false); because you are comparing two values (booleans in this case), you should use ==.
Give it a try and let us know.

Happy learning,
Dani

2 Likes

Hey @MarcisB

let withAmount = $("#withdraw").val(); returns a string. Make sure to convert it to integer before passing it to the function.

Happy learning,
Dani

2 Likes

Yes you’re right! Thank you very much, silly mistake :see_no_evil:

1 Like

Yes, true, it was a typo :upside_down_face: struggling wiht listening events, so I think I’ll be back here…

1 Like