ethereumjs / ethereumjs-tx

Project is in active development and has been moved to the EthereumJS VM monorepo.
https://github.com/ethereumjs/ethereumjs-vm/tree/master/packages/tx
Mozilla Public License 2.0
779 stars 235 forks source link

err: Error: base fee exceeds gas limit when values are correct #96

Closed PaulRBerg closed 5 years ago

PaulRBerg commented 6 years ago

Expected

Token transaction should execute successfully.

Behaviour

The base fee exceeds the gas limit, when that's not the case. The gas limit I set is 0xEA60, which in decimal is 60,000, definitely lower than Ganache's block gas limit of 6,721,975.

Code

const Tx = require('ethereumjs-tx');

const config = require('./config');
const contract = require('./contract');
const web3 = require('./web3');

const main = async () => {
    const count = await web3.eth.getTransactionCount(config.from);
    const nonce = web3.toHex(count);

    const gasPrice = web3.eth.gasPrice.toNumber();

    const block = await web3.eth.getBlock(3);
    console.log('block.gasLimit', block.gasLimit);
    console.log('web3.toDecimal(\'0xEA60\')', web3.toDecimal('0xEA60'));

    const rawTx = {
        'from': config.from,
        'nonce': nonce,
        'gasPrice': gasPrice,
        'gasLimit': '0xEA60',
        'to': config.to,
        'value': '0x10',
        'data': contract.transfer.getData(config.to, 10, { from: config.from }),
        'chainId': '0x03'
    };

    const privateKey = Buffer.from('8c...', 'hex');
    const tx = new Tx(rawTx);
    tx.sign(privateKey);
    const serializedTx = tx.serialize();

    web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), (err, hash) => {
        if (!err) {
            console.log('hash:', hash);
            console.log(web3.eth.getTransaction(hash));
        } else {
            console.log('err:', err);
        }

        console.log('from\'s balance:', contract.balanceOf.call(config.from));
        console.log('to\'s balance:', contract.balanceOf.call(config.to));
    });
};

main();

Tools

• ethereumjs-tx: 1.3.4 • web3: 0.20.6 • ganache (UI): 1.1.0 • node: 9.3.0 • os: osx high sierra 10.13.3

Full log ouput here.

danjm commented 5 years ago

This quite possibly could have been caused by the value of the 'data' property of the raw tx.

The comparison ran into here is that of the base gas cost of the transactions with the gas limit set when creating the transaction (not the block gas limit). The "base gas cost" depends on the data included in the transaction, the standard gas fee, and possibly a fee associated with sending to the creation address.

The relevant code is:

  /**
   * The amount of gas paid for the data in this tx
   * @return {BN}
   */
  getDataFee () {
    const data = this.raw[5]
    const cost = new BN(0)
    for (let i = 0; i < data.length; i++) {
      data[i] === 0 ? cost.iaddn(fees.txDataZeroGas.v) : cost.iaddn(fees.txDataNonZeroGas.v)
    }
    return cost
  }

  /**
   * the minimum amount of gas the tx must have (DataFee + TxFee + Creation Fee)
   * @return {BN}
   */
  getBaseFee () {
    const fee = this.getDataFee().iaddn(fees.txGas.v)
    if (this._homestead && this.toCreationAddress()) {
      fee.iaddn(fees.txCreation.v)
    }
    return fee
  }

I made a few attempts to recreate this but couldn't. Given that, how old this issue is, and given the probably explanation of the experienced error, I am going to close for now.

But if anyone experiences this again, please comment or open a new issue.