Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Address comments for PR 6 #7

Merged
merged 8 commits into from
Aug 18, 2019
Merged

Conversation

JakeLin
Copy link
Owner

@JakeLin JakeLin commented Aug 17, 2019

In this PR, I addressed the comments for PR #6

@adelRestom I have addressed all your comments except for the App.js.

App.js

  1. Very important thing we usually do is to protect the user from losing Ether on function calls that would fail; we do that by first calling the function with .call() which runs it locally/simulation (locally => no transaction => no mining => no gas consumed => no Ether lost), if that call doesn't fail then we proceed to actually call the function (i.e. call it without .call.
  2. You used on('transactionHash'), also use on('receipt') to inspect the receipt status (that it's == 1) and to inform the user of a successful transaction

For the first comment, do you call all the send method like
await contract.methods.split(beneficiary1Address, beneficiary2Address).call();
before

await contract.methods.split(beneficiary1Address, beneficiary2Address).send({
  from: accounts[0],
  value: web3.utils.toWei(etherToSplit, 'ether')
});

For the second comment, I have checked the receipt in the promise call - see tx variable, please.

  const tx = await contract.methods.split(beneficiary1Address, beneficiary2Address).send({
        from: accounts[0],
        value: web3.utils.toWei(etherToSplit, 'ether')
      }).on('transactionHash', txHash => {
        this.setState({ splitMessage: `Transaction ${txHash} submitted, waiting for the network to mine` });
      }).on('receipt', receipt => {
        console.log(receipt);
      });
      console.log(tx);

I print out receipt and tx, they are exactly same.

@xavierlepretre can you please have a look as well? thanks

@xavierlepretre
Copy link
Collaborator

What Adel meant is:

const result = await contract.methods.split(beneficiary1Address, beneficiary2Address).call(...
if (result) {
    do the .send

@xavierlepretre
Copy link
Collaborator

xavierlepretre commented Aug 17, 2019

As for the receipt, I see you are checking its status 👍 . You could also check the presence of the expected event.

@JakeLin
Copy link
Owner Author

JakeLin commented Aug 18, 2019

@xavierlepretre @adelRestom

I have tried out the following code

   const result = await contract.methods.split(beneficiary1Address, beneficiary2Address).call({
        from: accounts[0],
        value: web3.utils.toWei(etherToSplit, 'ether')
      });
      console.log(result);
      const tx = await contract.methods.split(beneficiary1Address, beneficiary2Address).send({
        from: accounts[0],
        value: web3.utils.toWei(etherToSplit, 'ether')
      }).on('transactionHash', txHash => {
        this.setState({ splitMessage: `Transaction ${txHash} submitted, waiting for the network to mine` });
      });
      if (tx.status) {
        const contractBalance = web3.utils.fromWei(await web3.eth.getBalance(contractAddress));
        this.setState({ splitMessage: `Transaction ${tx.transactionHash} got mined successfully.`, contractBalance });
      } else {
        this.setState({ splitMessage: `Something went wrong with transaction ${tx.transactionHash}.` });
      }

I found out whether the transaction fails or not in await contract.methods.split(beneficiary1Address, beneficiary2Address).send(... , await contract.methods.split(beneficiary1Address, beneficiary2Address).call(... will always returns an object of Result like
Screen Shot 2019-08-18 at 11 32 14 am

Can you guys tell me how can I meet @adelRestom 's requirement?


function withdrawAll() external onlyOwner whenKilled {
uint256 balanceToWithdraw = address(this).balance;
require(balanceToWithdraw > 0, "Balance must be grater than zero to withdraw!");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line of code becomes irrelevant because the normal withdraw is locked now.

function isKilled() public view returns (bool) {
return killed;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this functionality part of the Pausable contract, we want to protect the user from accidentally calling this function by turning it into a 2 step-process:

  1. The user pauses the contract
  2. The user kills the contract (the kill function checks that the contract is paused)

@@ -27,8 +27,8 @@ contract Pausable is Ownable {
emit LogPaused(msg.sender);
}

function unpause() public onlyOwner {
require(paused, "Can't unpause a non-paused contract!");
function resume() public onlyOwner {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a modifier called whenPaused; you'll need it for "kill" function anyway.

@@ -11,6 +11,9 @@ contract Splitter is Pausable {

mapping (address => uint256) public balances;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll also need to update your migration script and test file to pass the value to the constructor when calling new().

@adelrustum
Copy link

Regarding the .call() returned object, I thought it would throw an exception for a failed call that you can catch with a .catch().
Try to change your split function so that it returns a boolean and add return true; at the end of the function, this way you can check the returned boolean value so it would be like Xavier's code (let result = contract.func.call; if result == true..then call send).

@JakeLin JakeLin merged commit 842b855 into master Aug 18, 2019
@JakeLin JakeLin deleted the feature/address-comments-for-pr-6 branch August 18, 2019 23:28
@JakeLin
Copy link
Owner Author

JakeLin commented Aug 19, 2019

@adelRestom I have followed your advice to add return true in the function like

  function split(address _beneficiary1, address _beneficiary2) external payable whenRunning whenAlive returns(bool) {
    require(_beneficiary1 != address(0) && _beneficiary2 != address(0), "Beneficiary's address must not be zero!");
    require(msg.value > 0, "Must split more than zero ether!");

    if (msg.value.mod(2) == 1) {
      balances[msg.sender] = balances[msg.sender].add(1);
    }
    uint256 half = msg.value.div(2);
    balances[_beneficiary1] = balances[_beneficiary1].add(half);
    balances[_beneficiary2] = balances[_beneficiary2].add(half);
    emit LogSplitted(msg.sender, msg.value, _beneficiary1, _beneficiary2);
    return true;
  }

And add the call() check in App.js like

      const result = await contract.methods.split(beneficiary1Address, beneficiary2Address).call({
        from: accounts[0],
        value: web3.utils.toWei(etherToSplit, 'ether')
      });
      if (!result) {
        return;
      }

However, even I send 0 wei to the contract, result is still true. I also tried the same approach in withdraw function. They always return true when I call call().

So I don't know how can I check before I send().

@adelrustum
Copy link

@xavierlepretre can you please remind me how we used to do this? ☝️

@xavierlepretre
Copy link
Collaborator

I cloned your repo, checked out this branch, replaced 9545, npm installed both folders, truffle migrated into Ganache, npm started.
When I open in the browser, I get:

index.js:1375 TypeError: contract.methods.owner is not a function
    at App.componentDidMount (App.js:64)
console.<computed> @ index.js:1375

@xavierlepretre
Copy link
Collaborator

I would try to console.log(typeof result) and console.log(JSON.stringify(result)) to collect more info.

@JakeLin
Copy link
Owner Author

JakeLin commented Aug 20, 2019

@xavierlepretre I just merged the PR, can you rebase master?

@adelrustum
Copy link

I'm looking at my old work and I had something like:

return myContract.myFunction.call()
.then(() => myContract.myFunction())
.then...more code
.catch(error => console.log(error));

So the catch would show the error.

@JakeLin
Copy link
Owner Author

JakeLin commented Aug 21, 2019

thanks @adelRestom I am working on project 2 and 3 to try to make meet the deadline, will come back to this soon.

@xavierlepretre
Copy link
Collaborator

I still have the same error when loading the web page:

index.js:1375 TypeError: contract.methods.owner is not a function
    at App.componentDidMount (App.js:64)
console.<computed> @ index.js:1375

@JakeLin
Copy link
Owner Author

JakeLin commented Aug 21, 2019

@xavierlepretre sorry, for some reason, I didn't commit the fix to github. I have pushed the commit 522d3d8 now, it should be OK now.

@xavierlepretre
Copy link
Collaborator

xavierlepretre commented Aug 22, 2019

Now I get a revert on withdraw. "Balance must be grater than zero to withdraw!"
Even though it tells me that the account I split to has 0.5 Ether.

@JakeLin
Copy link
Owner Author

JakeLin commented Aug 22, 2019

That's weird, may I come back to this later? I am trying to finish the other projects

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants