Ethers.js: Error: gas required exceeds allowance or always failing transaction

Created on 23 Mar 2019  路  14Comments  路  Source: ethers-io/ethers.js

i am trying to make transfer from wallet B to wallet C and wallet A is the owner of ERC20 tokens
and i got error (node:2168) UnhandledPromiseRejectionWarning: Error: gas required exceeds allowance or always failing transaction for approveAndCall method.

`const approveCall = async() => {

            var gasNewPrice = await provider.estimateGas(transactionNew);
            console.log(gasNewPrice);
            var approved = await 
contract.approveAndCall(fromAddress,numberOfTokens,gasNewPrice);
            return approved;
        }
        const transferTokens = async() => {
            var transaction = await contract.transferFrom(fromAddress,targetAddress,numberOfTokens)
            return transaction;
        };
        approveCall().then(function (resultApprove) {
            console.log(resultApprove);
            transferTokens().then(function (resultTransfer) {
                console.log(resultTransfer);
            });
        }); `

what went wrong ?

discussion

Most helpful comment

This seems to be an issue with certain contracts with certain backends, where the backend fails to correctly estimate the gas. It seems more common when a contract calls to another contract. Which provider are you using?

The only really way to prevent this is to manually set your gas limit (instead of letting estimateGas from being used):

let overrides = {
    gasLimit: 750000
};
var transaction = await contract.transferFrom(from, to, amount, overrides);

And then dial in the correct gas estimate per call. This can also be set in the ABI (and if you use viper will be added to the ABI for you). To use it in the Human-Readable ABI, you can use:

let abi = [
    "function transferFrom(address from, address to, uint256 amount) @750000"
];

Not ideal, and if you find a way to make estimateGas behave, let me know. But for now, it seems like these cases require a manually set gasLimit.

All 14 comments

This seems to be an issue with certain contracts with certain backends, where the backend fails to correctly estimate the gas. It seems more common when a contract calls to another contract. Which provider are you using?

The only really way to prevent this is to manually set your gas limit (instead of letting estimateGas from being used):

let overrides = {
    gasLimit: 750000
};
var transaction = await contract.transferFrom(from, to, amount, overrides);

And then dial in the correct gas estimate per call. This can also be set in the ABI (and if you use viper will be added to the ABI for you). To use it in the Human-Readable ABI, you can use:

let abi = [
    "function transferFrom(address from, address to, uint256 amount) @750000"
];

Not ideal, and if you find a way to make estimateGas behave, let me know. But for now, it seems like these cases require a manually set gasLimit.

Hi, Thank you for your reply.
I tried setting gasLimit default and now the error is gone and the transaction is happening but the transaction is always failing, you can see here.

if I do a transaction for 0 tokens it works perfectly

what might be causing to fail the transaction it has ether in from an account and also enough ERC20 tokens.

It is not using all the gas, so it is a revert (or require). Perhaps you are trying to transfer more tokens than you have? Or transferFrom more than your allowance? I would need to see the contract code to figure that out.

@iamsuz Did you call the approve function on the token contract before calling transferFrom from your contract?

I have the same issue. but the contract i am running doesn't need any token transfer, when i am trying to update any value into the contract i get this error.

If someone has a solution please do share.

For what it's worth, this issue happens to me when I call a contract that calls another contracts. Take a look at Payroll.sol and the createSalary method.

@PaulRBerg, if i am right, this screenshot here could be the reason why your transaction is failing. You cannot call approve method from within this your contract.
Screen Shot 2019-12-16 at 11 11 23 PM

@SirPhemmiey no, I did not use approve function my issue was, I was trying to transfer the more tokens than the contract had (my decimal was different when I was calling the contract and when I deployed the contract so could not figured out earlier).

@SirPhemmiey of course I can call approve from within a contract. Why wouldn't that be possible?

@PaulRBerg approve uses msg.sender under the hood. So, if you call the approve function from within your contract, approve will see it as msg.sender which is not right because your contract does not have/hold any token hence, the reason for your failing transactions. You should call the approve function outside your contract and the sender of the transaction should be the token owner.

Sorry, we are discussing two different problems.

Yes, you are entirely correct that the user must call approve outside the contract, but calling approve in my contract logic is necessary because of the specific business logic of Sablier.

The bug that I was talking about is that ethers throws an error when calling estimateGas on the Payroll.sol contract, but not on other contracts that do not call other contracts internally.

Oh Okay, I see.

But if you're calling approve in your contract and transaction is successful, I'd love to explore and use it too instead of me performing two different transactions on my end.

Has this been addressed? I feel at the very least we can agree this contract requires a hard-coded gasLimit as nodes don't seem able to estimate it...

I'm going to close this now, but please feel free to re-open or continue discussing here (I monitor closed issues).

Thanks! :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ricmoo picture ricmoo  路  3Comments

moshebeeri picture moshebeeri  路  3Comments

zemse picture zemse  路  3Comments

abhishekp1996 picture abhishekp1996  路  3Comments

crazyrabbitLTC picture crazyrabbitLTC  路  3Comments