Contract write transactions failing for OpenLogin connector on Polygon Amoy network

Intro

Since we updated to Polygon Amoy because of the upcoming deprecation of Polygon Mumbai on Alchemy, transactions made using the OpenLogin connector are nearly always failing.

Problem

We notice the following cases with transactions:

1. They fail with a TransactionExecutionError caused by eth_sendRawTransaction:

TransactionExecutionError: An internal error was received.

Request Arguments:
  from:  0x669285824dBBD0CE1F3e73c747Be8E558DF37C92
  to:    0xE5c1713Ca42A35dfD12D4e1D694a6B60f6f1bC84
  data:  ...

Details: Internal JSON-RPC error.
Version: viem@2.8.13

2. They fail on the client because of insufficient funds to pay for gas fee:
Since the gasPrice is null and apparently not calculated automatically in 1), we specify it and pass it to our writeContract function call:

import {useGasPrice} from 'wagmi';
import {writeContract} from 'wagmi/actions';

const {data: gasPrice} = useGasPrice({
  chainId,
});
return writeContract(wagmiConfig, {
  abi: ...,
  address: ...,
  functionName: ...
  args: ...,
  account: ...,
  gasPrice,
});
ContractFunctionExecutionError: The total cost (gas * gas fee + value) of executing this transaction exceeds the balance of the account.

This error could arise when the account does not have enough funds to:
 - pay for the total gas fee,
 - pay for the value to send.
 
The cost of the transaction is calculated as `gas * gas fee + value`, where:
 - `gas` is the amount of gas needed for transaction to execute,
 - `gas fee` is the gas fee,
 - `value` is the amount of ether to send to the recipient.
 
Raw Call Arguments:
  from:      0x669285824dBBD0CE1F3e73c747Be8E558DF37C92
  to:        0xE5c1713Ca42A35dfD12D4e1D694a6B60f6f1bC84
  data:      ...
  gasPrice:  72.89225666 gwei
 
Contract Call:
  address:   0xE5c1713Ca42A35dfD12D4e1D694a6B60f6f1bC84
  function:  ...
  args:      ...
  sender:    0x669285824dBBD0CE1F3e73c747Be8E558DF37C92

Docs: https://viem.sh/docs/contract/simulateContract
Details: err: insufficient funds for gas * price + value: address 0x669285824dBBD0CE1F3e73c747Be8E558DF37C92 have 230432362823251550 want 40090741163000000000 (supplied gas 550000000)
Version: viem@2.8.13

The wallet has 230432362823251550 (0.23043236282325155 MATIC)
The contract call is asking for 40090741163000000000 in fees (40.090741163 MATIC)

3. They load indefinitely without an error.
Confirmed by waiting 5+ minutes on different transactions and amounts.

4. They succeed but fees are high
This ERC20 USDC approve transaction with hash 0xcd70fd1eb9e32c3b890de43d519e9f24e5895d33cb490f63faf07f436c29f4a4 used ~0.01 MATIC

Info

  • The same code works perfectly on Polygon Mumbai.
  • The same transactions are successful and gas fees are much lower using MetaMask with the Web3Auth Connector.
  • Using a public rpc url (‘https://rpc-amoy.polygon.technology’) instead of our private Alchemy url makes no difference except that case 3) seems to happen more often.

Environment

package.json

{
  "dependencies": {
    "@tanstack/react-query": "^5.24.2",
    "@web3auth/base": "^8.0.0",
    "@web3auth/ethereum-provider": "^8.0.1",
    "@web3auth/no-modal": "^8.0.1",
    "@web3auth/openlogin-adapter": "^8.0.1",
    "@web3auth/metamask-adapter": "^8.0.1",
    "@web3auth/web3auth-wagmi-connector": "^6.0.0",
    "viem": "^2.8.13",
    "wagmi": "^2.5.11"  
  }
}

Web3Auth

import environment from '#/environment/environment';
import {getHttpTransportUrl} from '#/utils/get-http-transport-url';
import {CHAIN_NAMESPACES, OPENLOGIN_NETWORK} from '@web3auth/base';
import {EthereumPrivateKeyProvider} from '@web3auth/ethereum-provider';
import {MetamaskAdapter} from '@web3auth/metamask-adapter';
import {Web3AuthNoModal} from '@web3auth/no-modal';
import {OpenloginAdapter} from '@web3auth/openlogin-adapter';
import {Chain} from 'wagmi/chains';

export const getWeb3AuthInstance = (chain: Chain) => {
  const chainConfig = {
    chainNamespace: CHAIN_NAMESPACES.EIP155,
    chainId: '0x' + chain.id.toString(16),
    rpcTarget: getHttpTransportUrl(chain),
    displayName: chain.name,
    tickerName: chain.nativeCurrency?.name,
    ticker: chain.nativeCurrency?.symbol,
    blockExplorerUrl: chain.blockExplorers?.default.url[0] as string,
  };

  const privateKeyProvider = new EthereumPrivateKeyProvider({
    config: {chainConfig},
  });

  const web3AuthInstance = new Web3AuthNoModal({
    clientId: environment.web3AuthClientId,
    web3AuthNetwork: OPENLOGIN_NETWORK.CYAN,
    storageKey: 'local',
    chainConfig,
    enableLogging: false,
    sessionTime: 86400,
    privateKeyProvider,
  });

  web3AuthInstance.configureAdapter(
    new OpenloginAdapter({
      adapterSettings: {
        uxMode: 'redirect',
        replaceUrlOnRedirect: false,
      },
      loginSettings: {
        mfaLevel: 'none',
      },
    }),
  );

  web3AuthInstance.configureAdapter(new MetamaskAdapter());

  return web3AuthInstance;
};

Hi @afarley,

I hope you’re doing well. I wanted to let you know that we’re currently experiencing a similar issue with the latest versions of ethers and web3.js.

Even though this isn’t directly related to our SDK, I’m going to bring this up with our product team to see if we can find a workaround or provide some guidance.

Thanks for bringing this to our attention, and I’ll get back to you as soon as I have more information. Your patience and understanding are greatly appreciated as we work through this.

1 Like

@TomTom Do you have a time estimate as to when things should be resolved? Our users can’t do transactions at the moment.

Hi @afarley,

I hope you’re doing well. I’ve been running some tests to better understand the situation you’re facing. Could you let me know which library you’re currently using to execute the transfer?

For context, I’ve been using web3.js version 1.10.4 and haven’t encountered any issues with the following code snippet:

const receipt = await web3.eth.sendTransaction({
  from: fromAddress,
  to: destination,
  value: amount,
  maxPriorityFeePerGas: "5000000000", // Max priority fee per gas
  maxFeePerGas: "60000000000", // Max fee per gas
});

If you’re using a different library or version, sharing that information and code could help us pinpoint the issue more accurately.

Looking forward to your response and eager to help you get this sorted out!

1 Like

@TomTom All this information is detailed in my initial post:

  • We are using wagmi (2.5.11) + viem (2.8.13)
  • Transactions (like in your example) run fine, contract write operations (like in our example) do not.
  • It’s a simple contract write operation which is working on every other network but Polygon Amoy:
return writeContract(wagmiConfig, {
  abi: ...,
  address: ...,
  functionName: ...
  args: ...,
  account: ...
});
  • Passing maxPriorityFeePerGas and maxFeePerGas like you suggested in your example gives the same error as 2) in my initial post:
ContractFunctionExecutionError: The total cost (gas * gas fee + value) of executing this transaction exceeds the balance of the account.

Hi @afarley,

I hope you’re doing well! I wanted to share with you that writing contracts are functioning correctly on our end. To give you a clearer picture, here’s a video demonstration: Dropbox - amoyIssue.mov - Simplify your life

Could you let me know if you’ve had the chance to try out the latest version of Viem or the specific version of web3.js I previously mentioned?

@TomTom Yes we’ve updated to the latest version of both wagmi and viem. I just don’t understand why eth_sendRawTransaction sometimes fails because it requires 1.04 MATIC, while it works perfectly with very low gas fees on metamask.

Using web3.js is not an option as it would require changing our entire stack.

Hi @afarley,

I hope you’re doing well! I wanted to share with you the implementation of Viem in our stack. You can find it here: GitHub - Web3Auth/web3auth-pnp-examples at feat/add-viem.

From my testing, everything seems to be working fine on the Amoy Testnet. Could you please check on your end and confirm whether it’s working for you as well?

I’m here to help with any issues you might encounter or any questions you may have. Looking forward to your feedback!

The same issue you are having is related to upgrading web3.js from 1.X to 4.X

please check this link to find the solution : Migration from 1.8v to 4v caused Insufficient funds error · Issue #6249 · web3/web3.js · GitHub

You have to estimate the gas first

      const amount = web3.utils.toWei("0.001", "ether"); // Convert 1 ether to wei
      let transaction = {
        from: fromAddress,
        to: destinationAddress,
        data: "0x",
        value: amount,
      }
      
      transaction = { ...transaction, gas: await web3.eth.estimateGas(transaction)} as any;

      // Submit transaction to the blockchain
      const receipt = await web3.eth.sendTransaction(transaction);