Solidity Testing – Resolving Invalid Opcode Error at transferFrom() Call

erc-20invalid-opcodesoliditytestingtruffle

I get the following error:

1) Contract: Bencoin should send Bencoin correctly via transferFrom(address, address, uint256):                                       
     Uncaught Error: VM Exception while processing transaction: invalid opcode                                                          
      at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:36886:16)                                     
      at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:206712:36                                                             
      at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:205491:13)                 
      at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:207364:18)                   
      at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:207654:12)                             
      at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:207809:12)                         
      at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:207769:24)                               
      at endReadableNT (_stream_readable.js:1047:12)                                                                                    

When I run the following test with truffle test:

  it("should send Bencoin correctly via transferFrom(address, address, uint256)", function() {
    var bencoin;

    var amount = 5;

    // Get initial balances of first and second account.
    var account_one = accounts[0]; // should be 9;
    var account_two = accounts[1]; // should be 8;

    var account_one_starting_balance;
    var account_two_starting_balance;
    var account_one_running_balance;
    var account_two_running_balance;

    return Bencoin.deployed().then(function(instance) {
      bencoin = instance;
    })

    .then(function() {
      return bencoin.balanceOf.call(account_one);
    }).then(function(balance) {
      account_one_starting_balance = balance.toNumber();
      return bencoin.balanceOf.call(account_two);
    }).then(function(balance) {
      account_two_starting_balance = balance.toNumber();
    }).then(function() {
      // the balance of account one should start off equal to 9
      assert.equal(
        account_one_starting_balance,
        9,
        "Account one did not start with a balance of 9 Bencoin"
      );
      // the balance of account two should start off equal to 8
      assert.equal(
        account_two_starting_balance,
        8,
        "Account two did not start with a balance of 8 Bencoin"
      );
    })

    // approve the transfer of 5 Bencoin from account_one to account_two
    .then(function() {
      bencoin.approve(account_two, amount);
    }).then(function() {
      return bencoin.allowance.call(account_one, account_two);
    }).then(function(allowance) {
      assert.equal(
        allowance,
        amount,
        "account_two was not successfully approved to transferFrom() 5 Bencoin from account_one"
      );
    })

    // execute the transfer of 5 Bencoin from account_one to account_two (code fails here)   
    .then(function() {
      bencoin.transferFrom(account_one, account_two, amount);
    }).then(function() {
      return bencoin.balanceOf.call(account_one);
    }).then(function(balance) {
      account_one_running_balance = balance.toNumber();
    }).then(function(balance) {
      return bencoin.balanceOf.call(account_two);
    }).then(function(balance) {
      account_two_running_balance = balance.toNumber();
    }).then(function() {
      // 5 was taken from 9, so the balance of account one should be 4
      assert.equal(
        account_one_running_balance,
        account_one_starting_balance - amount,
        "5 Bencoin were not correctly taken from the sender"
      );
      // 5 was added to 8, so the balance of account two should be 13
      assert.equal(
        account_two_running_balance,
        account_two_starting_balance + amount,
        "5 Bencoin were not correctly sent to the receiver"
      );
    });
  });

I'm running truffle test on testrpc and my token is an ERC20 token that extends the OpenZeppelin StandardToken.sol.

EDIT: Here is my contract code:

pragma solidity ^0.4.4;
import "zeppelin-solidity/contracts/token/StandardToken.sol";

contract Bencoin is StandardToken {
  string public name = "Bencoin"; 
  string public symbol = "BEN";
  uint public decimals = 18;
  uint public INITIAL_SUPPLY = 0;

  function Bencoin() {
    totalSupply = INITIAL_SUPPLY;
  }

  function mintCoin(address _to, uint256 _value) {
    balances[_to] = balances[_to].add(_value);
    totalSupply = totalSupply.add(_value); 
  }
}

The values 9 for account_one and 8 for account_two are set in previous tests. These values are assert()ed for at the start of the transferFrom() test, and they always pass that assert(), so its not that I don't have the funds in account 1. (9 is > 5, of course)

Best Answer

The problem is that you are approving account_two to transfer funds from account_one, but you are executing the transfer with account_one

The test should be something like this

  bencoin.transferFrom(account_one, account_two, amount, { from: account_two });
Related Topic