Programming Project - Phase 2

Does anyone experiencing issues with the migrating contract on the Ropsten network right now ? Yesterday it worked perfectly, today it takes forever, or doesn’t work at all. If you are reading this post later, check if you had same issue this time around.

1 Like

@Filip,

Im getting an error when I try to deploy my Dapp to the ropsten network. I see it is deploying my other .sol files and some test faucet is taken from my account. But my last contract does not deploy. What am I doing wrong?

1 Like

My Dapp works great until I try to use any provable functions (i.e. provable_newRandomDSQuery). Then it either doesn’t compile, or compiles but throws an exception when I opened up Metamask while trying to pay the gas on a transaction.

Also, attempting to include the provable sol file using
import “github.com/provable-things/ethereum-api/provableAPI.sol”;

Leads to a compile error:
Compiling your contracts…

Error: Error: Could not find github.com/provable-things/ethereum-api/provableAPI.sol from any sources; imported from C:/Programming/Solidity/CoinFlip-contract/contracts/CoinFlip.sol
at Object.compile (…\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\workflow-compile\legacy\index.js:72:1)

Please help. Would be great to be able to hook up this oracle. TIA

The link you shared is not active - if you go into the provable-things github and goto the provableAPI.sol it directs you to provableAPI_05.sol
Which will take you here:
https://github.com/provable-things/ethereum-api/blob/master/provableAPI_0.5.sol

Good luck

Thanks for the reply. Even that still gives me the same error message:

Compiling your contracts…

Error: Error: Could not find https://github.com/provable-things/ethereum-api/blob/master/provableAPI_0.5.sol from any sources; imported from C:/Programming/Solidity/CoinFlip-contract/contracts/CoinFlip.sol
at Object.compile (…\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\workflow-compile\legacy\index.js:72:1)

Admittedly I didn’t import from a URL - I copied the code from that link and saved it in my project folder in a file called provableAPI.sol and then in my contract just imported it from the project directory like you do with all other importing and this worked from me.
I personally prefer doing it this way as the code isn’t going to change before I can deploy it unless I change it, whereas a linked github file may be subject to change at any time

import "./provableAPI.sol";

and contract inheritance is

Contract CoinFlip is usingProvable { 
.....
}

Good luck

1 Like

Yeah, that’s what I tried first and that seemed to be compiling okay but when I called any provable functions it just errors out in the Metamask window. If I comment out all the provable functions and use my own stuff, it works great. So it’s a mystery to me why it doesn’t like the provable functions.

1 Like

Are you using the right contract name in the inheritance? The provableAPI.sol file has many different contracts depending on your needs. If you can’t progress, link your project and tag Dani and she will know what’s going on I’m sure.
Good luck

1 Like

I figured it out. I hadn’t actually migrated to Ropsten and was still migrating like normal local code so of course the transactions were erroring out. It’s been over a week since I watched the videos and setup that side of this project so I had forgotten that step. Good thing I take good notes. Just need to read them from time to time. :wink:

1 Like

@rostyslavdzhohola @Nicksta

Hey guys, is the issue with Ropsten fixed?
It was down couple of days ago but should be back running now.

cheers,
Dani

1 Like

I had finally made my Dapp work:
https://github.com/RostyslavDzhohola/Coinflip-test-Project

1 Like

Yes, it works fine now. However, I had issue with oracle not returning a callback function with the result lately.

It is not working for me. It fails at the last confirmation block

1 Like

That’s happened to me a few times as well.

1 Like

Hi! Here’s a video of my Coin Flip Dapp in action!
https://www.youtube.com/watch?v=rU6PQopHAnI

Code is here: https://github.com/billytaylor/coin-flip-dapp - Enjoy!

Cheers
Billy

1 Like

Hey @smileBTC and Anyone else,

I’ve taken the time to implement a liquidity pool style in my dApp. Again, thanks for the idea SmileBTC. Now I have had the time to look more closely at the random number generator in your function won(), above.

if (uint(keccak256(abi.encodePacked(blockhash(bet[msg.sender].blocknr+1), msg.sender)))%2==1){return(true);}

After doing some reading, I think I know something, and know I don’t know more. Haha… So I come with some small findings and a couple questions…

From the docs (linked) I learned of this…
https://solidity.readthedocs.io/en/v0.7.4/units-and-global-variables.html?highlight=block.#block-and-transaction-properties

“The blocks can be influenced by some degree”… As Smile wrote, it is to make “miner manipulation infeasible” not to eliminate it. As such, I was hoping some people can help me get an understanding of what kind of commitment would be needed to “cheat” this contract.

If new blocks are mined every 5 seconds or so on the Kovan Testnet would the attacker have to act within the time it takes to read that a user has transacted with the contract, create a fake next blockhash and knowing the address of the sender check to see if it would have a desired outcome. If not try another fake blockhash until successful or until the network as a whole has created the next block at which point they cannot continue with the attack?

If I’m thinking of this correctly, does this mean that the attacker would need 51% of the network hash power (or a substantial %)? Would they need to be able to not only create a blockhash for the the next block for the random number function, but also then another block more to commit their attack to the larger network and have the network come to consensus on their attack? Although it does seem possible to attack this it does not seem profitable to do so? Could this method then be used in Mainnet production?

I’m very interested in the possibility to create a “random” function on chain and I hope to get feedback about this topic so I can really understand it well. Thank you for any input you may have. :smile:

1 Like

Any tips for debugging errors like this?

The first transaction seems to go off without a hitch, but then I get this error when I try to run a second transaction.

1 Like

Not sure about your specific case, but generally I had these types of errors occur when my front end allowed the attempt at a transaction that my backend wouldn’t accept. One example was when my front end allowed metamask transaction for withdrawing more funds than existed in the contract.

I hope this helps. Good Luck :+1:

1 Like

I believe I figured out my issue. Well, mostly. It still happens from time to time, but it usually works now.

I’m not sure why it is this way though. Please allow me to explain and maybe someone can please help shed some light on why this is working like this…

So the user hits the Start Bet button and we call a solidity function called triggerCoinFlip(). This records the bet amount and calls to get the random number from the Oracle.

Right after executing that in main.js, we have code execute that adds an event listener on the generatedRandomNumber event. When this fires, it calls a solidity function called handleFlippedResult(). Previously, I was invoking this function using .call() because this function doesn’t actually intend to send the money, only stores the bet value in a winnings mapping for the user to later call withdrawAllProfits() to actually get the money in their wallet.

Anyway, I noticed that if I call this function with .send(accounts[0]) then everything works BUT, when this executes, I get a second transaction window that opens up in Metamask and if I confirm it (and pay a little gas) everything goes through correctly. This just seems wonky, like why should I need another transaction to store the data? This isn’t a payable function.

This is also awkward because if the user receives a 0 from the Oracle (signifying that they lost the bet) then the transaction window still pops up but with no benefit to the end-user.

Here’s the code for handleFlippedResult():

    function handleFlippedResult(bytes32 id, uint result) public
    {
        emit debugPrintUInt("flipResult: ", result);
        Bet memory currBet = Betting[id];

        require(currBet.betAmount >= 1 wei, "User has to bet something.");

        Waiting[currBet.player] = false;

        // User doubled their money!
        if(result == 1)
        {
            // msg.value contains the bet amount so double it and send it back to the user.
            uint doubledBet = currBet.betAmount * 2;

            // Balance cannot go negative.
            require((balance - doubledBet) >= 0, "Balance cannot go negative.");

            // Subtract winnings from total balance.
            balance -= doubledBet;

            // Balance cannot go negative.
            require(balance >= 0, "Balance cannot go negative.");

            // Store the players winnings in a mapping.
            uint currentWinnings = Winnings[currBet.player];
            currentWinnings += doubledBet;
            Winnings[currBet.player] = currentWinnings;

            emit debugPrintUInt("currentWinnings: ", currentWinnings);
            emit debugPrintUInt("Winnings[currBet.player]: ", Winnings[currBet.player]);
        }
        else
        {
            // User lost all bet money.
        }

        delete Betting[id];
    }

Here’s the JavaScript code I use to invoke that function:

    // First start listening for generatedRandomNumber events.
    // Listen for the event only once. This way is preferred here because everytime
    // the user places a bet, it will otherwise add another listener so then
    // after 4 bets you see the callback fire 4 times.
    //contractInstance.events.generatedRandomNumber({}, function(error, randResult)     // <-- adds event listener each time startBet() is called. This could lead to multiple of the same callback firing for one event.
    contractInstance.once('generatedRandomNumber', {}, function(error, randResult)
    {
        console.log("generatedRandomNumber event fired!");
        console.log(randResult);
        console.log("id: " + randResult.returnValues._queryId);
        console.log("result: " + randResult.returnValues._randomNumber);
        contractInstance.methods.handleFlippedResult(randResult.returnValues._queryId, randResult.returnValues._randomNumber).send(accounts[0]).then(async function(flipResult)
        {
            let currWinnings = await contractInstance.methods.getWinnings().call();
            console.log("curr getWinnings() currWinnings: " + currWinnings);
            updateMetrics();
            let formattedCurrWinnings = web3.utils.fromWei(currWinnings.toString(), "ether");
            $("#winnings_output").text(formattedCurrWinnings);

            console.log("currWinnings: " + formattedCurrWinnings);
            if(randResult.returnValues._randomNumber == 1)
            {
                $("#result_output").text("You won!");
            }
            else
            {
                $("#result_output").text("You lost!");
            }

            let blockchainBalance = await web3.eth.getBalance(contractAddress);
            let formattedBalance = web3.utils.fromWei(blockchainBalance.toString(), "ether");
            console.log("blockchainBalance: " + formattedBalance);
            $("#total_balance_output").text(formattedBalance);
        });
    });

Anybody know why I have to do it this way, or any tips for improvement?

Thanks!

On another note, the output looks almost like the handleFlippedResult() function is called twice with a single transaction as shown in the output below.

flipResult: 1
currentWinnings: 2000000000000000
Winnings[currBet.player]: 2000000000000000
flipResult: 1
currentWinnings: 2000000000000000
Winnings[currBet.player]: 2000000000000000

Am I doing something strange when I invoke the function or setup the event listener that could be causing the double output?

Maybe we’re not actually calling the function twice, but I’m somehow adding my event listeners twice. Here’s that code (see debugPrintUInt and debugPrintBool):

    // This will bring up a window in Metamask asking for permission for the website to access your Metamask information (not private keys).
    window.ethereum.enable().then(function(accounts)
    {
        // abi string is a template of the specification of what the contract is (i.e. what type of functions it has, what the functions are called, what type of arguments those functions take, what they return)
        // This is so the Javascript knows what arguments and types it's going to send to the contract and what to expect in return.
        // You get the abi from the truffle project as long as you have compiled and deployed the contract first.
        // Go into your truffle project's build/contracts folder and look for <nameofcontract>.json (so People.json in this PeopleProject example) this is a generated file created by truffle when you deploy your contract
        // Copy the entire abi array that shows up at the very top of the function and paste it into a new file (called abi.js).
        // Inside abi.js set a new var abi = []; that entire array.
        //
        // address is the address of the contract so it knows where to send these requests/transactions.
        //contractInstance = new web3.eth.Contract(abi, address);
        contractInstance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]});
        console.log(contractInstance);
        console.log(contractInstance.methods);
        console.log(contractInstance.events);
        updateMetrics();

        console.log("accounts[0]: " + accounts[0]);

        // Listen for uint output events from the contract so you can more easily see the value of variables in Solidity.
        contractInstance.events.debugPrintUInt({}, function(error, printResult)
        {
            console.log("" + printResult.returnValues._label + printResult.returnValues._value);
        });

        // Listen for bool output events from the contract so you can more easily see the value of variables in Solidity.
        contractInstance.events.debugPrintBool({}, function(error, printResult)
        {
            console.log("" + printResult.returnValues._label + printResult.returnValues._value);
        });
    });