The HelloWorld withdrawAll() into MetaMask via Web3

Hello… I’m building off of the HelloWorld contract. I’m building a Web3.js interface. Now, I’m trying to call the withdrawAll() function back into my wallet.

The following code doesn’t throw any errors and returns the amount in gwei… but funds never get transferred or sent. any suggestions or tips?

Solidity:

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

Javascript:

document.getElementById('withdrawButton').addEventListener('click', () => {
     console.log('withdraw the funds !');
     myContract.methods.withdrawAll().call()
         .then(function (result) {
               console.log(result);
         });
});
1 Like

Here is a GIST of my Solidity Code:

1 Like

Here is the relevant call from my JS file:

        document.getElementById('withdrawButton').addEventListener('click', () => {
            console.log('withdraw the funds !');
            myContract.methods.withdrawAll().call()
                .then(function (result) {
                    console.log('then')
                    console.log(result);
                }).catch(function (err) {
                    console.log('catch');
                    console.log(err);
                }) 
        }); 

and here is the whole thing, if you must see it.

console.log('Hi dApp!'); 
const web3 = new Web3(Web3.givenProvider);
var myContract;
var account;
const address = "0x70b1E0a47CE9095fe6d7ffa88FD1e792c9E59C8f";
const abi = [
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": false,
                "internalType": "string",
                "name": "name",
                "type": "string"
            },
            {
                "indexed": false,
                "internalType": "uint256",
                "name": "number",
                "type": "uint256"
            },
            {
                "indexed": false,
                "internalType": "bool",
                "name": "senior",
                "type": "bool"
            }
        ],
        "name": "personCreated",
        "type": "event"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": false,
                "internalType": "string",
                "name": "name",
                "type": "string"
            },
            {
                "indexed": false,
                "internalType": "bool",
                "name": "senior",
                "type": "bool"
            },
            {
                "indexed": false,
                "internalType": "address",
                "name": "deletedBy",
                "type": "address"
            }
        ],
        "name": "personDeleted",
        "type": "event"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": false,
                "internalType": "string",
                "name": "name",
                "type": "string"
            }
        ],
        "name": "saidHello",
        "type": "event"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "balance",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [],
        "name": "close",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "internalType": "string",
                "name": "name",
                "type": "string"
            },
            {
                "internalType": "uint256",
                "name": "number",
                "type": "uint256"
            }
        ],
        "name": "createPerson",
        "outputs": [],
        "payable": true,
        "stateMutability": "payable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "internalType": "address",
                "name": "creator",
                "type": "address"
            }
        ],
        "name": "deletePerson",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [
            {
                "internalType": "uint256",
                "name": "index",
                "type": "uint256"
            }
        ],
        "name": "getCreator",
        "outputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "getPerson",
        "outputs": [
            {
                "internalType": "string",
                "name": "name",
                "type": "string"
            },
            {
                "internalType": "uint256",
                "name": "number",
                "type": "uint256"
            },
            {
                "internalType": "bool",
                "name": "senior",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "owner",
        "outputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [
            {
                "internalType": "address",
                "name": "",
                "type": "address"
            }
        ],
        "name": "people",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "id",
                "type": "uint256"
            },
            {
                "internalType": "string",
                "name": "name",
                "type": "string"
            },
            {
                "internalType": "uint256",
                "name": "number",
                "type": "uint256"
            },
            {
                "internalType": "bool",
                "name": "senior",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "sayHello",
        "outputs": [
            {
                "internalType": "string",
                "name": "hello",
                "type": "string"
            }
        ],
        "payable": false,
        "stateMutability": "pure",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [],
        "name": "withdrawAll",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }
];
 

$(document).ready(function () {

    var sayHelloButton = document.getElementById('sayHello-button');
    var sayHelloLabel = document.getElementById('sayHelloSpan');
    
    var getPersonButton = document.getElementById('getPersonButton');
    var getPersonLabel = document.getElementById('getPersonSpan');
    
    var createName = document.getElementById('createName');
    var createNumber = document.getElementById('createNumber');
    var createLabel = document.getElementById('createSpan');
    var createButton = document.getElementById('createButton');
   
    var getCreatorLabel = document.getElementById('getCreatorSpan');
    var getCreatorButton = document.getElementById('getCreatorButton');
    
    var newestLabel = document.getElementById('newestSpan');
    var peopleList = document.getElementById('peopleList');

    var connectButton = document.getElementById('connectToDapp');

    connectButton.addEventListener('click', () => {
        window.ethereum.enable().then(function (accounts) {
            connectAccounts(accounts);
            connectButton.style.display = 'none';
            document.body.classList.add('connectedToNetwork');
        });
    });





    function connectAccounts(accounts){
        
        account = accounts[0];

        myContract = new web3.eth.Contract(abi, address, { from: accounts[0] });
        console.log(myContract._address);
        console.log(myContract.methods);

        document.getElementById('addressSpan').innerHTML = "<a href='https://ropsten.etherscan.io/address/" + myContract._address +"' target='_blank' >" + myContract._address + "</a>";
         

        sayHelloButton.addEventListener('click', () => { 
            console.log('say hello click');        
            myContract.methods.sayHello().call()
                .then(function (result) {
                    console.log(result);
                    sayHelloLabel.innerHTML = result;
                }).catch(console.log);
        });
        
        getPersonButton.addEventListener('click', () => {
            console.log('get person click');
            myContract.methods.getPerson().call()
                .then(function (result) {
                    getPersonLabel.innerHTML = result.name + ' ' + result.number;
                }).catch(console.log);
        });  

        getCreatorButton.addEventListener('click', () => {
            console.log('get creator click');

            myContract.methods.getCreator(0).call()
                .then(function (result) {
                    console.log(result);
                    getCreatorLabel.innerHTML = result;
                }).catch(console.log);
        });


        



        document.getElementById('withdrawButton').addEventListener('click', () => {
            console.log('withdraw the funds !');
            myContract.methods.withdrawAll().call()
                .then(function (result) {
                    console.log('then')
                    console.log(result);
                }).catch(function (err) {
                    console.log('catch');
                    console.log(err);
                }) 
        }); 

        




        myContract.events.personCreated({}, (error, event) => { 
            console.log('~~~~~~~~~~~~~ PERSON CREATED EVENT ~~~~~~~~~~~~');
            console.log(event); 
            console.log(event.returnValues.name); 
            newestLabel.innerHTML = event.returnValues.name + ' ' + event.returnValues.number;
   
            let info = "<a href='https://ropsten.etherscan.io/tx/" + event.returnValues.transactionHash + "' target='_blank' >" + event.returnValues.name + " " + event.returnValues.number + "</a>";
            addToList(info);
            reflectBalance();
        });


        myContract.getPastEvents('personCreated', { fromBlock: 0, toBlock: 'latest' }, function (error, event) { })
            .then(function (event) {
                console.log(event);
                let n = event.length;
                for (var i = 0; i < n; i++) {
                    // console.log(event[i].returnValues.name, event[i].returnValues.number);
                    let info = "<a href='https://ropsten.etherscan.io/tx/" + event[i].transactionHash + "' target='_blank' >" + event[i].returnValues.name + " " + event[i].returnValues.number + "</a>";
                    addToList(info);
                }
            }).catch(console.log);
            

        function addToList(info){
            let li = document.createElement("li");
            li.innerHTML = info;
            peopleList.insertBefore(li, peopleList.firstChild );
        }







        TweenMax.set("#transactionLoader", { opacity: 0 });

        createButton.addEventListener('click', () => {
            console.log('create person click');

            // console.log(createName.value);
            // console.log(createNumber.value);
            let isValid = false;

            if ((createName.value != '') && (createNumber.value != '') ){
                isValid = true;
                TweenMax.to("#transactionLoader", 0.2, { opacity:1});
            }else{
                console.log('give me a name and number, bozo.');
            }

            
            if(isValid){
 
                let weiValue = Web3.utils.toWei('0.1', 'ether');
                
                myContract.methods.createPerson(createName.value, createNumber.value).send({ 'value': weiValue})
                    .on('transactionHash', function (hash) {
                        console.log(hash);
                        TweenMax.fromTo("#transactionLoader", 2, { rotation: 0 }, { rotation: 360, repeat: -1, ease: Power1.easeInOut, yoyo: true });
                    })
                    .on('receipt', function(receipt) {
                        console.log("on receipt");
                        console.log(receipt);
                        TweenMax.to("#transactionLoader", 0.3, { rotation:0, opacity:0 });                        
                        reflectBalance();
                        myContract.methods.getPerson().call()
                            .then(function (result) {
                                console.log(result.name);
                                createLabel.innerHTML = result.name + ' ' + result.number;
                            });
                        })
                    .on('error', function(error, receipt) { 
                        // If the transaction was rejected by the network with a receipt, the second parameter will be the receipt.
                        console.log("on error receipt");
                        console.log(error, receipt);
                    })
                
            }


        });
       
        




        function reflectBalance() {
            // This returns value in WEI
            myContract.methods.balance().call()
                .then(function (result) {
                    let value = Web3.utils.fromWei(result, 'ether');
                    // console.log(value + ' ETH');
                    document.getElementById('balanceSpan').innerHTML = value + ' ETH';
                }).catch(console.log);

        }
        reflectBalance();





    };
});

@Taha Could you take a peek ?

Thanks

@bhaun
Apologies for the delay.

As you can see you are not specifying the amount you would like to transfer in your withdrawAll().

  function withdrawAll() public onlyOwner returns(uint) {
        uint toTransfer = balance;
        balance = 0;
        // address(this).balance gives you the complete balance of the contract which is the amount needed to withdraw all eth.
        toTransfer = address(this).balance;
        msg.sender.transfer(toTransfer);
        return toTransfer;
    }

Should work now.

Happy coding

1 Like

Thank you @Taha … I’m getting the same results with the edits you suggested.

The thing is… it DID and DOES still wok from within the Remix.ethereum Web IDE . . It connects to Metamask, and prompts for a withdraw, and i confirm, and it works. The funds go in to the wallet, and are removed from the contract.

It DOES NOT work when i’m calling the same withdrawAll() function from the Web3 javascript code .

Is there something special about the Web3.js ?

Hey @bhaun

Try to change myContract.methods.withdrawAll().call() to myContract.methods.withdrawAll().send()

Check if it works. If it does not please upload back and front end on github and let me know.

Cheers,
Dani

2 Likes

All of my relevant code is posted above in a Gist and JS file pasted in the comments. (sorry, no proper github setup for this now.)

I’ve changed .call() to .send() and it DOES give me a different result, but with an error:

Error: Transaction has been reverted by the EVM:
{
  "blockHash": "0x36e36cc7e73f9957a6ca38fcaf5d67d6ef537761e95efd9cb580ba648716a41a",
  "blockNumber": 8657804,
  "contractAddress": null,
  "cumulativeGasUsed": 168384,
  "from": "0x358a18de592de58686559cce67bb9a89a30435ee",
  "gasUsed": 22283,
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "status": false,
  "to": "0x7a122da56d1e8105ef34f6b372a2657cb653ffb4",
  "transactionHash": "0x71e9999b4ddbe30baa566ee81052fcf9428a4f14681f6b8de8b195a640f8810b",
  "transactionIndex": 3,
  "events": {}
}
    at Object.TransactionError (web3.min.js:1)
    at Object.TransactionRevertedWithoutReasonError (web3.min.js:1)
    at web3.min.js:1
    at l (web3.min.js:1)
    at Generator.f._invoke (web3.min.js:1)
    at Generator.t.<computed> [as next] (web3.min.js:1)
    at u (web3.min.js:1)
    at i (web3.min.js:1)
    at web3.min.js:1
    at new Promise (<anonymous>)

BUT SUDDENLY ! I realized I was trying to withdraw from a different account… Only the creator can withdraw the funds !!!

It’s working! Thank you.

1 Like

Happy I was helpful :slight_smile:

3 Likes