So I am using Wagmi, which uses Ethers.js under the hood. I have to approve the router address first in order to buy the other token. It works when I use the exact or slightly greater amount than what I send thru UI textbox. But it fails if I modify (into MetaMask popup textbox) the value close to my max balance.

For example. I have above 9000 mockBUSD and wanted to approve 50 of them for the router. If I use the default (50) or 500 mockBUSD (in the MetaMask popup textbox) transaction goes without any issue, and in the next step I can buy another token that is paired with mockBUSD. But if I modify the value to 6000 in the MetaMask popup, the transaction fails.

Here is txn that succeed - https://testnet.bscscan.com/tx/0x39deda5d7f7f0a91ce0481169d379eb7ba50c2d2827252d90986a3a972d23c48 (approved 2000 mockBUSD)

Here is another that fails - https://testnet.bscscan.com/tx/0x3820c27ac48d0be7a23d6cf884cc24dfea261e1639abb29c3061961016d3c264 (approved 6000 mockBUSD)

And I tried several times, and the outcomes were similar. What could be the reason for this weird issue?

  • You ever get around to figuring this out? I have this problem intermittently and can confirm it is due to different allowance amounts - did a wide range of different tests with different amounts and it does consistently fail but can not yet in the root cause (also using wagmi/ethers) Commented Apr 14, 2023 at 20:46

3 Answers 3


Your error states: "Warning! Error encountered during contract execution [out of gas]." So it is not going through because you run out of gas.

If a transaction exhausts its gas, it implies that the gas limit specified for the transaction is insufficient to cover the total gas required. Typically, wallets can make a relatively precise estimation of the gas needed for a transaction. However, if the estimated gas falls short, you may raise it manually. To ensure adequate gas coverage for most contract interactions, setting the gas limit to 60,000 should suffice. Any excess gas will be refunded to you.

  • I am sure the error is due to something else, because I have enough gas. The txn fails only when I enter a larger amount (say more than 70% of my total balance).
    – sanjay dev
    Commented Mar 22, 2023 at 3:58
  • Have you tried giving it more gas?
    – PSS
    Commented Mar 22, 2023 at 13:47
  • I suggest you give it 60,000 gas and post a link to that failed transaction. I’d like to see the error, when you give it more gas, please 🙏🏻
    – PSS
    Commented Mar 22, 2023 at 13:51
  • Well. I spent whole day digging it. And it has very weird error. So it works if I try thru testnet directly. There is no cap limit. As soon as I try it from my dapp, error is shown for bigger amount and no error for smaller amount. And again, if I use dapp and change the gas fees it does work. One more point, this is happening to only this token, not with the other one. So this is kind of very weird error for me.
    – sanjay dev
    Commented Mar 22, 2023 at 16:15
  • I guess posting your code for others to look at could be your next option.
    – PSS
    Commented Mar 22, 2023 at 21:29

I likewise encountered this problem gas estimation for ERC20 approve calls on Ethereum mainnet. While I couldn't pinpoint why the estimations failed (most cases the gas limit was off by 20 to 30 gas units) I queried around 500 blocks to see how much gas approval cost for 10 different tokens (USDC, DAI, WETH, LINK, etc.).

From there, the max gas cost I found was 60311 so I hardcoded my dApp to use 62500 for some wiggle room - hopefully this number helps.


You seem to assuming the gas cost is always the same, but it isn't. Besides the cost of the transaction execution (which can vary for reasons like changing from/to zero and refunds, but not in your case), there are certain "base" costs you have to pay:

  • every transaction automatically costs 21,000 gas
  • every nonzero byte of calldata is 16 gas, zero byte is 4 gas

The first is fixed but the second is not.

You can see in the geth debug trace for the successful approve tx that the execution cost is 7528 gas.

7528 + 21000 + 644 = 29,172 which is the amount the tx cost and you set as the gas limit

Where did the 644 come from? That's the cost for the calldata:

Function: approve(address spender,uint256 amount)

MethodID: 0x095ea7b3
[0]:  000000000000000000000000f8302046b3fbb0167916c7847946a76b1f517ee7
[1]:  00000000000000000000000000000000000000000000006c6b935b8bbd400000

Let's break down the cost of this calldata:

  • Method ID:
    • 4 nonzero bytes
    • 0 zero bytes
  • spender
    • 20 nonzero bytes
    • 12 zero bytes
  • amount
    • 7 nonzero bytes
    • 25 zero bytes

Remember it's 16 gas for nonzero byte and 4 gas for zero byte, which gives:

(4 + 20 + 7) * 16 + (12 + 25) * 4 = 644

What about for the failed tx? Similar calculation but the amount is slightly longer (8 bytes)!

So the calldata cost changes from 644 to 656 and the result exceeds your gas limit by 12.

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.