1

I'm playing around with truffle and I have this simple program here that I can't seem to get to work...

contract MyContract {

  struct Test {
    bool testBool;
  }

  mapping (address => Test[]) public tests;

  function issueTest(address _owner) public {

      Test memory test;
      test.testBool = false;
      tests[_owner].push(test);
  }

  function setTestBool(address _owner, uint _index) public
    returns (bool sucess) {

    tests[_owner][_index].testBool = true;

    return tests[_owner][_index].testBool;
  }

  function getTestBool(address _owner, uint _index) public returns (bool testBool) {
    return tests[_owner][_index].testBool;
  }
}

in my test file I have:

let myContract;
  var reciever = web3.eth.accounts[1];

  before(async() => {
    myContract = await MyContract.deployed();
  });
it("Test Bool", async() => {

    await myContract.issueTest.call(reciever);
    var sucess = await myContract.setTestBool.call(reciever, 0);
    assert.equal(sucess, true, "Test Bool was set.");

    var result = await myContract.getTestBool.call(reciever, 0);
    assert.equal(result, true, "Bool is true.");
  });

When I do truffle test I get this error:

 Error: Error: VM Exception while executing eth_call: invalid opcode

I think the problem is with .call(). I dont understand what call does very well.

Any help would be great Thanks!

mark
  • 209
  • 1
  • 7

2 Answers2

0

If you get invalid opcode error, you most likely have tried to access the EVM via or in a state that is not consistent. For instance calling getTestBool with an address that hasn't been set via issueTest.

As for testing, with truffle I think its cleaner to use a chain of Promises.

var MyContract = artifacts.require("./MyContract.sol");

contract('MyContract', function(accounts) {
  var mainAccount = accounts[0];
  var nobody = accounts[1];
  var contract;

  it("Test Bool", function() {
    // Build the contract ...
    return MyContract.deployed().then(function(instance) {
      contract = instance;
    // ... then issue the test ...
      return contract.issueTest(mainAccount, {from: mainAccount});
    }).then(function() {
    // ... then set the bool ...
      return contract.setTestBool.call(mainAccount, 0, {from: mainAccount});
    }).then(function(result) {
    // ... then assert it was set. 
      assert.equal(true, result, "Did not set testBool to true");
      return contract.setTestBool.call(mainAccount, 0, {from: mainAccount});
       // no need for from because call does not change EVM state
      return contract.getTestBool.call(mainAccount, 0);
    }).then(function(result) {
      assert.equal(true, result, "testBool failed");
    });
  });
});
Victory
  • 1,231
  • 1
  • 8
  • 21
0

The problem is that you are trying to .call() the getTestBool() function but the function is not marked as view/constant.

If the function doesn't modify the state of the contract, then it should be marked as view/constant.

pabloruiz55
  • 7,686
  • 2
  • 17
  • 38