8

I successfully implemented a smart contract using remix in the Rinkeby testnet, and can interact with it from remix.

Now I'm building a simple frontend for it but although I have been able to obtain one of it's public variables, I'm not able to call a state changing function, Metamask returns

"Transaction Error. Exception thrown in contract code."

and when I send the transaction it fails. I looked all over the web and haven't found anything related. The abi looks ok, the contract is working and has the function correctly instantiated.

I'm currently using web3.js 0.20 and Chrome + Metamask, and I'm writing the function per web3's documentation. Follows the code:

My contract:

/// @title Contract Echos, prints the certificates
contract Echos is AccessControl {

    event logPrintedCertificate(address contractAddress, string _name, string _course);

    function printCertificate (string _name, string _course) public canAccess("printCertificate") whenNotPaused returns (address _certificateAddress) {

        // creates certificate smart contract
        address certificateAddr ess = new EchosCertificate(_name, _course);

        // creates the event, to be used to query all the certificates
        logPrintedCertificate(certificateAddress, _name, _course);

        return certificateAddress;
    }

    /// @dev Invalidates a deployed certificate
    function invalidateCertificate(address _certificateContract) external canAccess("printCertificate") {
        EchosCertificate certContract = EchosCertificate(_certificateContract);
        certContract.invalidate();
    }

}

abi (obtained from remix):

[
    {
        "constant": true,
        "inputs": [],
        "name": "paused",
        "outputs": [
            {
                "name": "",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [
            {
                "name": "_user",
                "type": "address"
            },
            {
                "name": "_transaction",
                "type": "string"
            }
        ],
        "name": "hasAccess",
        "outputs": [
            {
                "name": "",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_user",
                "type": "address"
            },
            {
                "name": "_transaction",
                "type": "string"
            }
        ],
        "name": "grantAccess",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "tokenContract",
                "type": "address"
            }
        ],
        "name": "withdrawTokens",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [],
        "name": "unpause",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_certificateContract",
                "type": "address"
            }
        ],
        "name": "invalidateCertificate",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": false,
                "name": "contractAddress",
                "type": "address"
            },
            {
                "indexed": false,
                "name": "_name",
                "type": "string"
            },
            {
                "indexed": false,
                "name": "_course",
                "type": "string"
            }
        ],
        "name": "logPrintedCertificate",
        "type": "event"
    },
    {
        "constant": false,
        "inputs": [],
        "name": "pause",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [],
        "name": "withdrawBalance",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_name",
                "type": "string"
            },
            {
                "name": "_course",
                "type": "string"
            }
        ],
        "name": "printCertificate",
        "outputs": [
            {
                "name": "_certificateAddress",
                "type": "address"
            }
        ],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_user",
                "type": "address"
            },
            {
                "name": "_transaction",
                "type": "string"
            }
        ],
        "name": "revokeAccess",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }
]

function to get public variable (working):

  echosContract.paused.call(function(error, result) {
    if (!error) {
      console.log(result);
    } else
      console.error(error);
  });

function to end transaction to state changing function (returns the aforementioned error):

  echosContract.printCertificate.sendTransaction(name, course, {
    gas: 30000,
    from: web3.eth.coinbase
  }, function(error, result) {
    if (!error) {
      console.log(result);
    } else
      console.error(error);
  });

I also tried calling the contract without "sendTransaction" (both ways are available in the documentation) and without optional transaction parameters and get the same result.

2 Answers 2

15

After reviewing the whole contract code, checking the ABI function by function, using mist, metamask and several web3 versions I found that the mistake was actually a low gas limit. Increasing the tx gas limit solved the problem right away.

An accurate error description would have saved me a day (12h working day).

Hope this helps folks that find the same misleading error.

Cheers

0

It's not the best solution, sometimes works and other no. you can do different config of GAs and Gwei. I think there is something in the **Metamask version!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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