1

Trying to learn smart contracts. I successfully deployed a contract. Before deploying it I used the functions successfully in Remix:

enter image description here

Contract Instance:

enter image description here

But in my Vue app, I get an error:

Uncaught TypeError: this.$store.state.contractInstance(...).deposit is not a function

The app successfully detects Metamask. And Via the console I see the contract instance and the ABI. But, deposit not available as a function, only appears in the ABI arrary.

This seems to the closest to my issue, but when I tried the solution it did not work for me: https://stackoverflow.com/questions/48184969/calling-smart-contracts-methods-using-web3-ethereum.

My code ... using web3 version ^0.20.5

Component:

<template>
  <div class="container">
    <div class="row">
      <div class="col">

        <h1>Home</h1>

        <form @submit.prevent="deposit">
          <label>Deposit
            <input
              v-model="amount"
              type="number"
              min=".01">
          </label>

          <button type="submit">Submit</button>
        </form>
      </div>
    </div>
  </div>
</template>

<script>
  import {store} from '../store';

  export default {
    name: 'home',
    data: function () {
      return {
        amount: null
      }
    },
    methods: {
      deposit(event) {
        this.$store.state.contractInstance().deposit(event.target.innerHTML, {
          gas: 300000,
          value: this.$store.state.web3.web3Instance().toWei(this.amount, 'ether'),
          from: this.$store.state.web3.coinbase
        }, (error, result) => {
          if (error) {
            console.log(error)
          }
        })
      }
    },
    mounted () {
      console.log('dispatching getContractInstance')
      this.$store.dispatch('getContractInstance')
    }
  }
</script>

Store:

import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
import getWeb3 from '../util/getWeb3';
import pollWeb3 from '../util/pollWeb3';
import getContract from '../util/getContract';

Vue.use(Vuex);
export const store = new Vuex.Store({
  strict: true,
  state,
  getters: {

  },
  mutations: {
    registerWeb3Instance(state, payload) {
      console.log('registerWeb3instance Mutation being executed', payload);
      let result = payload;
      let web3Copy = state.web3;
      web3Copy.coinbase = result.coinbase;
      web3Copy.networkId = result.networkId;
      web3Copy.balance = parseInt(result.balance, 10);
      web3Copy.isInjected = result.injectedWeb3;
      web3Copy.web3Instance = result.web3;
      state.web3 = web3Copy;
      pollWeb3();
    },
    pollWeb3Instance(state, payload) {
      console.log('pollWeb3Instance mutation being executed', payload);
      state.web3.coinbase = payload.coinbase;
      state.web3.balance = parseInt(payload.balance, 10);
    },
    registerContractInstance(state, payload) {
      console.log('Escrow contract instance: ', payload);
      state.contractInstance = () => payload;
    }
  },
  actions: {
    registerWeb3({ commit }) {
      console.log('registerWeb3 Action being executed');
      getWeb3
        .then(result => {
          console.log('committing result to registerWeb3Instance mutation');
          commit('registerWeb3Instance', result);
        })
        .catch(e => {
          console.log('error in action registerWeb3', e);
        });
    },
    pollWeb3({ commit }, payload) {
      console.log('pollWeb3 action being executed');
      commit('pollWeb3Instance', payload);
    },
    getContractInstance({ commit }) {
      getContract
        .then(result => {
          commit('registerContractInstance', result);
        })
        .catch(e => console.log(e));
    }
  }
});

escrow.sol

pragma solidity ^0.4.11;

contract Escrow {
    uint balance;
    address public manager;
    address public worker;
    address private escrow;
    uint private start;
    bool managerOk;
    bool workerOk;

function Escrow(address manager_address, address worker_address) public {
        manager = manager_address;
        worker = worker_address;
        escrow = msg.sender;
        start = now;
    }

    function accept() public {
        if (msg.sender == manager){
            managerOk = true;
        } else if (msg.sender == worker){
            workerOk = true;
        }
        if (managerOk && workerOk){
            payBalance();
        } else if (managerOk && !workerOk && now > start + 30 days) {
            selfdestruct(manager);
        }
    }

    function payBalance() private {
        escrow.transfer(this.balance / 100);
        if (worker.send(this.balance)) {
            balance = 0;
        } else {
            throw;
        }
    }

    function deposit() public payable {
        if (msg.sender == manager) {
            balance += msg.value;
        }
    }

    function cancel() public {
        if (msg.sender == manager){
            managerOk = false;
        } else if (msg.sender == worker){
            workerOk = false;
        }
        if (!managerOk && !workerOk){
            selfdestruct(manager);
        }
    }

    function kill() public constant {
        if (msg.sender == escrow) {
            selfdestruct(manager);
        }
    }
}

escrowContract.js:

const address = '0xd61F9331CE61Eb27E0AB7d9b9bc75402Ea5db7f8';
const ABI = [
  [
    {
      constant: false,
      inputs: [],
      name: 'accept',
      outputs: [],
      payable: false,
      stateMutability: 'nonpayable',
      type: 'function'
    },
    {
      constant: false,
      inputs: [],
      name: 'cancel',
      outputs: [],
      payable: false,
      stateMutability: 'nonpayable',
      type: 'function'
    },
    {
      constant: false,
      inputs: [],
      name: 'deposit',
      outputs: [],
      payable: true,
      stateMutability: 'payable',
      type: 'function'
    },
    {
      inputs: [
        {
          name: 'manager_address',
          type: 'address'
        },
        {
          name: 'worker_address',
          type: 'address'
        }
      ],
      payable: false,
      stateMutability: 'nonpayable',
      type: 'constructor'
    },
    {
      constant: true,
      inputs: [],
      name: 'kill',
      outputs: [],
      payable: false,
      stateMutability: 'view',
      type: 'function'
    },
    {
      constant: true,
      inputs: [],
      name: 'manager',
      outputs: [
        {
          name: '',
          type: 'address'
        }
      ],
      payable: false,
      stateMutability: 'view',
      type: 'function'
    },
    {
      constant: true,
      inputs: [],
      name: 'worker',
      outputs: [
        {
          name: '',
          type: 'address'
        }
      ],
      payable: false,
      stateMutability: 'view',
      type: 'function'
    }
  ]
];

export { address, ABI };

getContract.js

import Web3 from 'web3';
import { address, ABI } from './constants/escrowContract';

let getContract = new Promise(function(resolve, reject) {
  let web3 = new Web3(window.web3.currentProvider);
  let escrowContract = web3.eth.contract(ABI);
  let escrowContractInstance = escrowContract.at(address);
  resolve(escrowContractInstance);
});

export default getContract;
  • According to the ABI, deposit takes no inputs, yet you are trying to pass a parameter – Raghav Sood Aug 22 '18 at 1:15
  • What version of web3 are you using? If it's the 1.0-beta, you need instance.methods.deposit. (And yes, as @RaghavSood points out, it doesn't accept a parameter.) – user19510 Aug 22 '18 at 1:26
  • @RaghavSood, maybe I am not generating the ABI correctly. I added a screenshot of remix. I can deposit funds when testing. – runningraptor Aug 22 '18 at 1:30
  • @smarx, web3 ^0.20.5 – runningraptor Aug 22 '18 at 1:33
  • @runningraptor deposit doesn't take any parameters in your screenshot either. – user19510 Aug 22 '18 at 1:37
0

Your ABI is wrapped in an extra array.

const ABI = [
  [
    {
      ...
    },
    ...
  ]
];

Remove one pair of square brackets:

const ABI = [
  {
    ...
  },
  ...
];
0

if anyone would encounter errors like

Uncaught TypeError: Cannot read property 'node' of undefined

or

Uncaught DOMException: Failed to execute 'postMessage' on 'Window'

just revert back to older version and it should works. Not sure why but you guys can check out here: https://github.com/ethereum/web3.js/issues/1986

npm install --save web3@1.0.0-beta.34

I am new to vue.js and am following a tutorial same as @runningraptor

hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.