On BSC, usually when your transaction to a contract fails such a tx uses about 30k gas when you do it through a wallet. But when a transaction made with an ethers.js script fails, it uses all the gas up to the gasLimit. Is there anything I can do to make my script behave correctly?

What should be: https://bscscan.com/tx/0xb36a1ae9d8294db8e1e1faf23c5c8d98d5e1cbcf3ae3bd57dc7f1fcb648b9041

What happens: https://bscscan.com/tx/0x864e489c1e678d536b07d84bccd609d07002d6d1a66a6a0ff2a368ab53bc47eb

const ethers = require("ethers");

const purchaseAmount = ethers.utils.parseEther("1");
const recepient = "";

const privateKey = "";

const sender = "";

const provider = new ethers.providers.WebSocketProvider("wss://bsc-ws-node.nariox.org:443");

const wallet = new ethers.Wallet(privateKey, provider);

const Tx = require('ethereumjs-tx')

async function sendEths() {

  let txCount = await provider.getTransactionCount(sender);
   let tx = {
    nonce: ethers.utils.hexlify(txCount),
    to: recepient,
    value: purchaseAmount,
    gasLimit: 140000,
    gasPrice: ethers.utils.parseUnits("5", "gwei"),

  console.log("Sending transactions");

  let receipt = await wallet.sendTransaction(tx);

  console.log("Transaction receipt");


  • That'a a bit puzzling because these tx have no input data but yet behave differently... Are you the owner of both the addresses that sent the tx that you linked? Do you have the contract source code?
    – Undead8
    Jul 9 at 23:14
  • Do you have the contract source code? The developers have control how to deal with errors. One way to deal with these errors is to call estimateGas if it fails then it is likely the transaction will also fail.
    – Ismael
    Jul 10 at 4:37

This actually, is called robbery. It is programmed in the sources, if your transaction fails, instead of consuming what you have so far consumed, the EVM will eat up your full gas limit even if you consumed 1 gas unit after the initial 21,000 . There is nothing you can do because this robbery is programmed within the sources of Ethereum:

if err != nil {
    if err != ErrExecutionReverted {
        gas = 0
    // TODO: consider clearing up unused snapshots:
    //} else {
    //  evm.StateDB.DiscardSnapshot(snapshot)


Shame on you, Vitalik Buterin.

If you want it to "behave correctly" as you say, just issue "REVERT" opcode at the end, because this is the condition that will decide either eat up your gas or not:

if err != ErrExecutionReverted {
    gas = 0

it will eat up if you have error different than revert, and thats exactly what you observe in Etherscan, Invalid opcode is not a REVERT-able exit status.

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.