Programming Project - Phase 2

Can someone help me with web3.js: I have this function in solidity:

function ContractInputMoney() public onlyOwner payable costs(100000000000000000 wei) {
        balance += msg.value;
    }

And I want to call this function in main.js, how do I do it? I tried many things, for example:

function letOwnerInput(){
  contractInstance.methods.ContractInputMoney().call();
}
//or
function letOwnerInput(){
  contractInstance.methods.ContractInputMoney().send({from: accounts[0], gas: 3000000, value: 100000000000000000}, function(err, res){});
// I also tried this without accounts, gas or the function
}

But it doesn’t work. Do you have any suggestions? Many thanks

Hi @CryptoDev
Can you share your error message ?

Hi @illyushin

Do not hesitate to re-watch the video if you have any issues or try to have a look at the web3js documentation, you can find answers for this question on google with the first request:

Also can you be more explicit, because "it doesn’t work " doesn’t really give us information about the issue you are facing.
(No metamask interaction ? The balance is not update ? Metamask shows you an error, if yes which one ?)

In your case you need to use send because your function is payable and it’s altering the state. As explained in the videos this functions are asynchronous so you need to wait for the promise to be resolve.

Why are you not using the .then() to get the return value of your asynchronous call ?

https://academy.ivanontech.com/products/ethereum-smart-contract-programming-201/categories/1993907/posts/6667999

2 Likes

Hi,

I am here again with questions.
I took the opportunity to learn a bit more about Provable and hoping to use it to get some API data from other website.
I found a video that Filip made earlier: https://www.youtube.com/watch?v=aDDTBQ3qmiI&t=3s
And I tried to write a contract to get the ETH price from coinbase, however, when I deployed it on Remix, there is no button to click to show the price, it only shows the Calldata.
Does anyone know why? Thank you in advance!


Here is the code, very similar to the code from Filip’s video:

pragma solidity 0.5.12;
import "provableAPI.sol";

contract TestAPI is usingProvable {

   string public ETHUSD;

   event LogNewProvableQuery(string description);

   function Price() public {
       //updatePrice();
   }

   function __callback(bytes32 _queryid, string memory _result) public {
       require (msg.sender == provable_cbAddress());
       ETHUSD = _result;
   }

   function updatePrice() public payable {
       if (provable_getPrice("URL") > address(this).balance) {
           emit LogNewProvableQuery("Provable query was NOT sent, please add some ETH to cover for the query fee");
       } else {
           emit LogNewProvableQuery("Provable query was sent, standing by for the answer..");
           provable_query("URL", "json(https://api.pro.coinbase.com/products/ETH-USD/ticker).price");
     
       }
   }
}

I think its working didnt get an error and could deploy my contract to the ropsten network could be the restart after installing git or something was done by the other devs.

I searched for hours and ended up using literally every way possible of writing this line of code and figuring out how it may work. I just came here as a last resort to maybe have a nice tip on what I did wrong :frowning: You helped me finding the problem now tho, in my “ownable” contract, where I set “onlyOwner” was the wrong compiler version of solidity, now it works!! Will post my Dapp today soon :slight_smile:

1 Like

Hi @Golden_Pig_Coin

You didn’t deployed the right contract, the one you deployed is Buffer, you should deploy TestAPI, also you are using a custom network i ll suggest you to use ropsten to test the provable api

1 Like

Hi @gabba,
thank you very much for your reply.
Now I have changed it, connected through Ropsten network on Metamask and deployed the contract at the address of the account on the Ropsten network.
But when I click “updatePrice” button, it shows “transact to TestAPI.updatePrice pending …”
MetaMask window did not pop up to ask me to confirm transaction. What is the Calldata part? Do I need to fill something there?

– SOLVED –

I am stuck with the very last part that has to work on my Dapp, its a button to allow the player to withdraw all his money he won from the coinflip. This is the solidity code:

function UserWithdrawMoney() public {
        uint toTransfer = result[msg.sender].userEarnings;
        balance -= toTransfer;
        result[msg.sender].userEarnings = 0;
        msg.sender.transfer(toTransfer);
    }

And again, I am literally sitting for over 2 hours to find the correct web3.js code to call this function, but nothing works… This should actually work if im not mistaken?

function giveUserMoneyBack(){

  contractInstance.methods.UserWithdrawMoney().send();

}

// or something else I tried, since send() takes a JSON object as an argument:
function giveUserMoneyBack(){

  var userBalance = contractInstance.methods.seeEarnings().call();

  then(contractInstance.methods.UserWithdrawMoney().send({value: userBalance}));

}

But it does not open metamask and it doesnt reset the earnings of the user to 0 … does anybody got tips? It is correctly connected to the button, I tested alert(“hi”); in the JS function and it works when I press the button. So it has to be that there is a specific way to write the web3.js code, so that the user receives a transaction from the contract. In remix my solidity code is working btw.

update: i forgot to update the abi after i changed my smart contract and deployed it ^^

Here is my finished project:


The sound went off half way throu, but I think you can still can get the just of it. Github link is here:

Hi @Golden_Pig_Coin did you send Eth to the contract to pay for the oracle fees ? You need to wait a bit for the oracle to resolve your request, emit an event on the callback.
If it’s write pending i think the issue come from remix, it doesn’t have response from the roptsen node. Make sure you have restart and reload metamask correcly

1 Like

So I got it working. Also deleted a few frames to make the video a little quicker.

You can view the code at:
https://github.com/wstrik/CoinTossDapp

1 Like

Hi @gabba
Thank you very much for your help!
I have learned a lot from you!

1 Like

Hi @illyushin

Well done to complete this project, however there 2 issues with your contract:

1 - In the __callback function if the user have win you are adding the value of the bet to the contract, i think it’s a typo because you add the value in both case if he win and if he loose.
So the balance will be incorrect

balance += oldNewBetter.userValue;

2- You are not checking if the contract have enough fund before allowing the player to bet.
Add a check in the flip() function.
In this example i have a balance of 1.6 eth but (Becaue you allow me to play 0.8 but the balance of your contract was 0.7…) so no i can’t withdraw my fund because the contract doesn’t have enough fund to pay me and the transfer function will fail.

Ps: You should also take in consideration the price of the call to the provable api

provable_getPrice("Random")

Because at some point the balance of your contract will be false

1 Like

@gabba thank you for your valueable tips! I changed the contract now and tried to consider every point you mentioned :slight_smile:

Hi
I am trying to use the code on “Remix” (before going forward). I deployed it on “Ropsten” , I do have Ethers on my wallet but the update function fails, as gas required exceeds allowance as follows:

Here is the Code:

pragma solidity >= 0.5.0 <0.6.0;

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

contract randomExample is usingProvable {
    
  uint256 constant NUM_RANDOM_BYTES_REQUESTED = 1;
  uint256 public latestNumber;
  
  event LogNewProvableQuery(string description);
  event generatedRandomNumber(uint256 randomNumber);

  constructor () public {
  update();
  }

  function __callback (bytes32 _queryId, string memory _result, bytes memory _proof) public {
  require (msg.sender== provable_cbAddress());

  uint256 randomNumber = uint256(keccak256(abi.encodePacked(_result))) % 100; //was 100 originally
  latestNumber = randomNumber;
  emit generatedRandomNumber (randomNumber);
  }

  function update() payable public {
  uint256 QUERY_EXECUTION_DELAY = 0;
  uint256 GAS_FOR_CALLBACK = 200000;

  // the provable_newRandomDSQuery will return unic id for every call to the oracle (that is also goes to yhe callback function argument):
  uint32 queryId;
  provable_newRandomDSQuery (QUERY_EXECUTION_DELAY, NUM_RANDOM_BYTES_REQUESTED, GAS_FOR_CALLBACK);

  emit LogNewProvableQuery ("provable was sent, standing by for answer..");

  } 
    
}

Any suggestions?
Thanks :slight_smile:

Hi @Guy

Remove the update from your constructor and remove the payable from your update function and it will works (anyway you are not sending eth when calling update)

 event LogNewProvableQuery(string description, bytes32 _queryId);
  constructor () public {
  }

  function update() public {
  uint256 QUERY_EXECUTION_DELAY = 0;
  uint256 GAS_FOR_CALLBACK = 200000;

  // the provable_newRandomDSQuery will return unic id for every call to the oracle (that is also goes to yhe callback function argument):
  bytes32 _queryId = provable_newRandomDSQuery(QUERY_EXECUTION_DELAY, NUM_RANDOM_BYTES_REQUESTED, GAS_FOR_CALLBACK);

  emit LogNewProvableQuery ("provable was sent, standing by for answer..", _queryId);

  }

Hi
I copied the code from Filip “as is”.
Anyway, I sent 0.01 Ether and after that, the update function was operated properly (without sending any additional payments in the next rounds…for free… )
I really like to understand what’s going on (even though it is working now…).
I understand that maybe the payable is required for the oracle callback function?

but if it is working without payable how does the gas for the callback got paid (GAS_FOR_CALLBACK = 200000) ? or maybe it is unnecessary?
/

The gas and the fee for the callback are taken from your smart contract balance. To send fund from your smart contract you don’t need this function to be payable. A function is payable if it is supposed to receive funds but yours is sending funds.

You are inheriting from the provable api contract so you are using there function in your smart contract, you are using gas and sending fees when you are calling provable_newRandomDSQuery but you also need to pay for the gas they will use to call your callback because they will send a transaction back to you.

You can look at this two function in the provableApi.sol file .

provable_newRandomDSQuery
provable_query

You got an error because the provable api was trying to send fund from your contract but your contract had an empty balance.