1

Developing an application which relies on a blockchain. Have test chain running with help of testrpc and I'm using truffle to compile and deploy contracts. This way I've created some contracts and tested their interactions. All is working well.

Now I want to create a front-end using ReactJS. I've successfully pulled data out of one of the contracts and displayed that. When I try to create a transaction which will actually update the chain's state, I run into some problems. Note that the transaction does work when I execute it 'manually' from the truffle console.

truffle console, ClientHandler.deployed().pushJob("src","dst",1,1) gives me back a valid tx hash and changes the state of the contract with the parameters that were passed to it. I would like to do the same thing when a user presses a button after filling out a form.

However, right now, when the button is pressed, I will receive invalid JUMP error in EVM. Before I was sending it without any gas and it would give me an out-of-gas error. This does not happen when using truffle but might be because truffle takes care of it automatically.

Any feedback and help is greatly appreciated, obviously i'm quite new to all this.

import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import './App.css';
import Web3 from 'web3';
import { _ } from 'lodash';

var EthereumClient = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var ClientHandlerContractABI = [{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"jobs","outputs":[{"name":"id","type":"uint256"},{"name":"source","type":"bytes32"},{"name":"destination","type":"bytes32"},{"name":"resourceReq","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"jobOwners","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getJobs","outputs":[{"name":"","type":"uint256[]"},{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"},{"name":"","type":"uint256[]"},{"name":"","type":"address[]"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_source","type":"bytes32"},{"name":"_destination","type":"bytes32"},{"name":"_resourceReq","type":"uint256"},{"name":"_unitPrice","type":"uint256"}],"name":"pushJob","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"inputs":[{"name":"_cmc","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"succes","type":"bool"}],"name":"pushJobEvent","type":"event"}]
var ClientHandlerContractAddress = '0x7b8ec3373298fbbfd890e2ea48b0fa258321840e'
var ClientHandlerContract = EthereumClient.eth.contract(ClientHandlerContractABI).at(ClientHandlerContractAddress);

export default class Form extends React.Component {

    constructor(props) {
        super(props)
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleSourceChange = this.handleSourceChange.bind(this);
        this.handleDestinationChange = this.handleDestinationChange.bind(this);
        EthereumClient.eth.defaultAccount = EthereumClient.eth.accounts[0]
        this.state = {
            src : '',
            dst : ''
        }
    }

    handleSourceChange(e) {
        this.setState({src: e.target.value});
    }

    handleDestinationChange(e) {
        this.setState({dst: e.target.value});
    }


    handleSubmit(e) {
        e.preventDefault();
        var src = this.state.src.trim();
        var dst = this.state.dst.trim();
        console.log(src);
        if (!dst || !src) {
            return;
        }
        console.log(EthereumClient.eth.defaultAccount)

        var rtn = ClientHandlerContract.pushJob(src,dst,0,0, {from: EthereumClient.defaultAccount, value:EthereumClient.toWei(20,'ether')});
        //TODO: Tx to BC

        this.setState({src: '', dst: ''});
        return;
    }

    render() {
        return (
            <form className="Form" onSubmit={this.handleSubmit}>
            <input type="text" placeholder="Your name" value={this.state.src} onChange={this.handleSourceChange} />
            <input type="text" placeholder="Your comment" value={this.state.dst} onChange={this.handleDestinationChange} />
            <input type="submit" value="Post" />
            </form>
       )
    }
}

The ClientHandler contract looks like this:

pragma solidity ^0.4.2;
import "/Users/pieteraerts/dccTruffle/contracts/ContractManagement.sol";
import "/Users/pieteraerts/dccTruffle/contracts/Exchange.sol";

contract ClientHandler{

    ContractManagement CMC;

    Job[] public jobs;

    struct Job {
        uint id;
        bytes32 source;
        bytes32 destination;
        uint resourceReq;
    }

    uint jobCounter;
    mapping(uint => address) public jobOwners;

    event pushJobEvent(address sender, bool succes);

    function ClientHandler(address _cmc){
        CMC = ContractManagement(_cmc);
        CMC.registerContract("ClientHandler");
        jobCounter = 0;
    }

    function pushJob(bytes32 _source, bytes32 _destination, uint _resourceReq, uint _unitPrice) returns (bool) {

        Job memory newJob;

        newJob.id = jobCounter;
        newJob.source = _source;
        newJob.destination = _destination;
        newJob.resourceReq = _resourceReq;

        jobs.push(newJob);

        jobOwners[jobCounter] = msg.sender;

        Exchange ex = Exchange(CMC.getAddress("Exchange"));

        if (!ex.postBid(_unitPrice, _resourceReq, newJob.id ) ){
            pushJobEvent(msg.sender, false);
            return false;
        }

        jobCounter = jobCounter + 1;
        pushJobEvent(msg.sender, true);
        return true;
    }

    function getJobs() constant returns (uint[], bytes32[], bytes32[], uint[], address[]){

        uint length = jobs.length;

        uint[] memory ids = new uint[](length);
        bytes32[] memory sources = new bytes32[](length);
        bytes32[] memory destinations = new bytes32[](length);
        uint[] memory resourceReqs = new uint[](length);
        address[] memory owners = new address[](length);

        for (uint i = 0; i < jobs.length; i++){
            Job memory currentJob;
            currentJob = jobs[i];

            ids[i] = currentJob.id;
            sources[i] = currentJob.source;
            destinations[i] = currentJob.destination;
            resourceReqs[i] = currentJob.resourceReq;
            owners[i] = jobOwners[currentJob.id];
        }

        return (ids, sources, destinations, resourceReqs, owners);
    }

}
  • Fixed my problem. Had to add the payable function modifier to the function pushJobs, otherwise it is not able to receive ether send to it and will throw invalid JUMP. – user1329182 Nov 4 '16 at 0:44

Your Answer

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

Browse other questions tagged or ask your own question.