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;
7
  • According to the ABI, deposit takes no inputs, yet you are trying to pass a parameter Aug 22, 2018 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, 2018 at 1:26
  • @RaghavSood, maybe I am not generating the ABI correctly. I added a screenshot of remix. I can deposit funds when testing. Aug 22, 2018 at 1:30
  • @smarx, web3 ^0.20.5 Aug 22, 2018 at 1:33
  • @runningraptor deposit doesn't take any parameters in your screenshot either.
    – user19510
    Aug 22, 2018 at 1:37

2 Answers 2

0

Your ABI is wrapped in an extra array.

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

Remove one pair of square brackets:

const ABI = [
  {
    ...
  },
  ...
];
0
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 [email protected]

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 and acknowledge that you have read and understand our privacy policy and code of conduct.

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