Transaction Fails with "Not Enough Funds" Error Despite Sufficient User Balance

I am encountering an issue while interacting with a deployed contract on the Fuel Network. The problem arises intermittently: the transaction fails with the following error message:

“_FuelError: The account(s) sending the transaction don’t have enough funds to cover the transaction.”

However, based on the balance logs, the user wallet has sufficient funds.

User Balance Log

Here is the user balance log before the transaction is sent:

sql

Copy code

User balance - --> 0.000494734 ETH

Code Implementation

Below is the code snippet used to check and fund the user wallet if the balance is insufficient:

typescript

Copy code

const balance = await userWallet.getBalance();
const formattedBalance = (parseFloat(balance.toString()) / 10 ** 9).toFixed(9);

console.log("User balance - -->", formattedBalance);

if (balance.lt(new BN(0.0001 * 10 ** 9))) {
  console.log("User wallet has insufficient funds, funding from sponsor...");

  const sponsorWalletPvtKey = getSponserWalletPvtKey(network);
  const sponsorWallet = Wallet.fromPrivateKey(sponsorWalletPvtKey, provider);

  await sponsorWallet.transfer(userWallet.address, new BN(0.0007 * 10 ** 9));
  console.log("User wallet funded successfully.");
}

// Contract interaction
const updateTransaction = await contract.functions
  .update_game_session_increase_score(id, 1)
  .call();

What I Observed:

  1. The user wallet shows a balance of 0.000494734 ETH before the transaction.
  2. The error states insufficient funds, even though this amount should be enough to cover the gas fees and the transaction cost.

Questions:

  1. Why does the transaction fail with “not enough funds” despite the wallet balance being sufficient?
  2. Is there a delay or finality issue where the balance is not updated immediately on the network?

Any insights or suggestions would be greatly appreciated. Thank you!

1 Like

Hey @jitendra-lync thanks for your question. I’m curious to know how you’ve determined that the funds in the wallet are sufficient if you haven’t estimated the fee before sending the transaction.

The getTransactionCost method on the function invocation scope can be used to estimate the cost of a contract call.

You can also use the simulate method to dry-run the contract call to ensure the wallet has sufficient funds to cover the transaction.

Please let me know if this points you in the right direction!

1 Like

I am facing an issue when trying to simulate and execute a transaction on the Fuel Network. Despite running a successful simulate() to validate the transaction, the execution fails with the following error:

“The account(s) sending the transaction don’t have enough funds to cover the transaction.”

const id = {
  Address: { bits: userWallet.address.toB256().toString() },
};

// Simulate the transaction
const simulation = await contract.functions
  .update_game_session_increase_score(id, 1)
  .simulate();

if (!simulation) {
  throw new Error(
    "Transaction simulation failed: Execution may not succeed."
  );
}
console.log("Transaction simulation successful.");

// Check session status
const checkStatus = await contract.functions
  .get_game_session_started(id)
  .get();
console.log("Session status:", checkStatus);

// Execute the transaction
const updateTransaction = await contract.functions
  .update_game_session_increase_score(id, 1)
  .call();
console.log("Transaction successful, hash:", updateTransaction.transactionId);
  1. The simulate() function runs successfully, indicating that the transaction should be valid and executable.
  2. Despite the simulation being successful, when the transaction is sent using call(), it fails with:

“The account(s) sending the transaction don’t have enough funds to cover the transaction.”

  1. The wallet balance before the transaction is logged and confirmed to be sufficient to cover gas fees.
1 Like

'i am encountering an issue while sending multiple transactions using Fuel. Although my user wallet has sufficient funds to cover the gas fees, I’m still getting an “Insufficient funds” error during certain transactions.

Here are the details of my implementation and issue:

  1. Context:
  • The wallet balance is validated before initiating a transaction. If the funds are insufficient, I fund the user wallet from a sponsor wallet with enough gas to handle multiple transactions.
  • Gas fees for each transaction are minimal, and funds seem sufficient after each validation.
  1. Error:
  • When sending multiple requests simultaneously, I intermittently get the following error

“The account(s) sending the transaction don’t have enough funds to cover the transaction.”

  • Transaction Details:
  • TxHash: 0x0f8a57118aeed05529fb1c8e325b3bbc6100e49a31cfa9cc4c600d069ea77405
  • Gas fees are very low compared to the available balance at the time.
  • Possible Issue:
  • Could this be related to race conditions or unconfirmed transactions consuming the balance temporarily during concurrent requests?
  • Or is there some delay in balance updates when multiple transactions are in progress?
  • Code Reference:
const nodeUrl = getNodeUrl(networkNumber as NetworkType);
    const provider = await Provider.create(nodeUrl);

    const userPrivateKey = privateKey;
    const userWallet = Wallet.fromPrivateKey(userPrivateKey, provider);
    const balance = await userWallet.getBalance();
    const formattedBalance = (parseFloat(balance.toString()) / 10 ** 9).toFixed(
      9
    );

    console.log("user balance - -->", formattedBalance.toString());
    if (balance.lt(new BN(0.0001 * 10 ** 9))) {
      console.log(
        "User wallet has insufficient funds, funding from sponsor..."
      );

      const sponserWalletPvtKey = getSponserWalletPvtKey(network);
      const sponserWallet = Wallet.fromPrivateKey(
        sponserWalletPvtKey,
        provider
      );
      await sponserWallet.transfer(
        userWallet.address,
        new BN(0.0007 * 10 ** 9)
      );
      console.log("User wallet funded successfully.");
    }
    // eslint-disable-next-line camelcase
    const contract = new GameSession(
      GAME_SESSION_CONTRACT as string,
      userWallet
    );

    const id: IdentityInput = {
      Address: {
        bits: userWallet.address.toB256().toString(),
      },
    };

    const estimatedCost = await contract.functions
      .update_game_session_increase_score(id, 1)
      .getTransactionCost();

    console.log("Total Gas max fee:", estimatedCost.maxFee.toString());

    const updatedBalance = await userWallet.getBalance();
    console.log("User Balance:", updatedBalance.toString());
    if (updatedBalance.lt(estimatedCost.maxFee)) {
      throw new Error(
        `Insufficient funds: Required ${estimatedCost.maxFee.toString()}, Available ${updatedBalance.toString()}`
      );
    }
    console.log(
      "Sufficient funds available. Proceeding with the transaction..."
    );

   

    const checkStatus = await contract.functions
      .get_game_session_started(id)
      .get();

    if (!checkStatus.value) {
      const txn = await contract.functions.start_new_game_session(id).call();
      await txn.waitForResult();
    }
    const updateTransaction = await contract.functions
      .update_game_session_increase_score(id, 1)
      .call();
    const session = await contract.functions.get_game_session_score(id).get();

Question:

  • Why does this error occur during concurrent requests despite having sufficient funds?
  • Is there a recommended way to handle transactions in parallel to avoid balance conflicts or update delays?
  • Is there any condition that requires a minimum amount to make the transaction on fuel?

Hi @jitendra-lync I’m sorry that you are still experiencing these issues. I think the questions you have raised are valid, if there is no interdependency between these contract calls, certainly I’d encourage you to explore these multiple contract calls using the multiCall method.

If you have a github repository that reproduces the issue that would be appreciated, so we could debug this in greater detail. But with what you have shared, I’d refactor the code as such:

const nodeUrl = getNodeUrl(networkNumber as NetworkType);
const provider = await Provider.create(nodeUrl);

const userPrivateKey = privateKey;
const userWallet = Wallet.fromPrivateKey(userPrivateKey, provider);
const balance = await userWallet.getBalance();

const contract = new GameSession(
    GAME_SESSION_CONTRACT as string,
    userWallet
);

const id: IdentityInput = {
    Address: {
    bits: userWallet.address.toB256().toString(),
    },
};

const { maxFee: totalMaxFee, gasUsed: totalGasUsed } = await contract.multiCall([
     contract.functions
    .get_game_session_started(id),
    contract.functions
    .update_game_session_increase_score(id, 1),
    contract.functions.get_game_session_score(id),
    contract.start_new_game_session(id)
]).getTransactionCost();


   
if (balance.lt(totalMaxFee)) {
    console.log(
    "User wallet has insufficient funds, funding from sponsor..."
    );

    const sponserWalletPvtKey = getSponserWalletPvtKey(network);
    const sponserWallet = Wallet.fromPrivateKey(
    sponserWalletPvtKey,
    provider
    );

    // Send the total maxFee for the contract calls + fee to cover sponsorship
    await sponserWallet.transfer(
    userWallet.address,
     totalMaxFee + 1000
    );
    console.log("User wallet funded successfully.");
}


const checkStatus = await contract.functions
    .get_game_session_started(id)
    .get();

if (!checkStatus.value) {
    const txn = await contract.functions.start_new_game_session(id).call();
    await txn.waitForResult();
}

// Further logic ...

i am getting the same issue
Request_Endpoint: POST /api/contract/gameSession
user balance - → 0.000468434
Request_Endpoint: POST /api/contract/gameSession
user balance - → 0.000468434
Request_Endpoint: POST /api/contract/gameSession
Request_Endpoint: POST /api/contract/gameSession
Request_Endpoint: POST /api/contract/gameSession
user balance - → 0.000466562
Request_Endpoint: POST /api/contract/gameSession
user balance - → 0.000466562
user balance - → 0.000466562
Error while creating game session: _FuelError: The account(s) sending the transaction don’t have enough funds to cover the transaction.

export const gameSession = async (req: Request, res: Response) => {
  try {
    let { privateKey, network, networkNumber } = req.body;

    if (!privateKey) {
      return res.status(400).json({
        message: "private key is required.",
        status: 400,
        success: false,
      });
    }
    const nodeUrl = getNodeUrl(networkNumber as NetworkType);
    const provider = await Provider.create(nodeUrl);

    const userPrivateKey = privateKey;
    const userWallet = Wallet.fromPrivateKey(userPrivateKey, provider);
    const balance = await userWallet.getBalance();

    // eslint-disable-next-line camelcase
    const contract = new GameSession(
      GAME_SESSION_CONTRACT as string,
      userWallet
    );

    const id: IdentityInput = {
      Address: {
        bits: userWallet.address.toB256().toString(),
      },
    };
    const sessionStarted = await contract.functions
      .get_game_session_started(id)
      .get();
    const calls = [
      contract.functions.get_game_session_started(id),
      contract.functions.update_game_session_increase_score(id, 1),
      contract.functions.get_game_session_score(id),
    ];

    if (!sessionStarted.value) {
      calls.push(contract.functions.start_new_game_session(id));
    }

    const { maxFee: totalMaxFee, gasUsed: totalGasUsed } = await contract
      .multiCall(calls)
      .getTransactionCost();

    const formattedBalance = (parseFloat(balance.toString()) / 10 ** 9).toFixed(
      9
    );
    console.log("user balance - -->", formattedBalance.toString());

    if (balance.lt(totalMaxFee)) {
      console.log(
        "User wallet has insufficient funds, funding from sponsor..."
      );

      const sponserWalletPvtKey = getSponserWalletPvtKey(network);
      const sponserWallet = Wallet.fromPrivateKey(
        sponserWalletPvtKey,
        provider
      );
      await sponserWallet.transfer(
        userWallet.address,
        totalMaxFee.add(new BN(0.0001 * 10 ** 9))
      );
      console.log("User wallet funded successfully.");
    }

    const updateTransaction = await contract.functions
      .update_game_session_increase_score(id, 1)
      .call();
    const session = await contract.functions.get_game_session_score(id).get();


    return res.status(201).json({
      status: 201,
      success: true,
      message: "Score Updated Successfully",
      data: {
        transactionHash: updateTransaction.transactionId,
        sessionScore: session.value.toNumber(),
      },
    });
  } catch (error: any) {
    console.log("Error while creating game session: ", error);
    return res
      .status(500)
      .json({ success: false, error: error?.message ? error.message : error });
  }
};

this is my code.
This error occurs when
I am hitting multiple requests at the same time.
when I send a single request, then there is no problem related to funds