2

I have this crontract:

pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

contract Tickets {
  struct Ticket {
    uint serie;
    uint number;
    uint datetime;
  }

  Ticket[] tickets;

  function addTicket(Ticket memory newTicket) public returns(bool success) {
    tickets.push(newTicket);
    return true;
  }

  function getTickets() public view returns(Ticket[] memory) {
    return tickets;
  }
}

I compile it with truffle truffle compile, then I run truffle develop and finally run migrate with all ok.

When I try to create a ticket with:

contract.methods.addTicket({serie: 1, number: 2000, datetime: 1583942530609}).send({from: account})

I get this error:

UnhandledPromiseRejectionWarning: Error: Returned error: VM Exception while processing transaction: out of gas

Any help?

  • Debugging idea: use uint instead of Ticket (i.e., passing a single uint value, to be pushed into a uint array), and see if it still fails with the same error-message. If yes, then the problem is most likely in your off-chain code rather than your on-chain code. In that case, I would start by making sure that the contract object in your Truffle script holds a properly deployed contract (i.e., has an address and all). – goodvibration Mar 11 at 16:12
  • 1
    Another idea, stemming directly from the error-message, is to add gas-configuration when sending the transaction, i.e., something like send({from: account, gas: 2000000}). Only problem is, these "gas" error messages are unfortunately in most cases not the result of any gas-related issue. – goodvibration Mar 11 at 16:15
  • If I remove one of the struct attributes it works, so it seem related to complexity. – drinor Mar 12 at 7:22
  • @goodvibration I try: send({from: account, gas: 2000000}) and it works, can you explain me why? – drinor Mar 12 at 7:23
  • Please replace send with estimateGas and tell me what you get. – goodvibration Mar 12 at 7:45
1

If you call transaction.send without providing a gas value, then the value returned (in a Promise) from transaction.estimateGas is used by default.

In some cases, this value is an underestimate of the actual amount of gas required for executing the transaction.

A possible solution for this is to do something like this:

const MIN_GAS = 1000000;
const gas = await transaction.estimateGas(x, y, z, {from: address});
const receipt = await transaction.send(x, y, z, {from: address, gas: Math.max(gas, MIN_GAS)});

UPDATE:

If you're worried about MIN_GAS being spent even when a smaller amount is really needed, then rest assure that when the transaction is finally executed, your account pays only the exact amount of gas required for execution.

You may ask yourself why not just specify the maximum possible (i.e., block gas-limit).

There are two primary reasons for avoiding that:

  1. The node will always check beforehand, that your account indeed has the total amount of gas * gasPrice + value (according to what you've specified in the object passed to send). If you specify a large (unnecessary) value of gas, then it increases the chances of your transaction being rejected for insufficient balance, even though your account has sufficient balance for the actual transaction to be executed.
  2. Miners typically search for transactions with the highest gasPrice and the lowest gas, as it yields the best profit-per-time scheme on their side). Thus, the higher the value of gas you specify, the longer it will take for your transaction to be executed.
| improve this answer | |

Your Answer

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

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