Withdrawal commission got reverted for this error BEP20: transfer amount exceeds allowance

I am using fireBlocks sdk. To withdraw crypto.
you can check my code here →

Hello Shahid,

Can you please post the code in the code block here instead of Pastebin URLs?


const fireblocksSettings = require("../fireblocksSettings");
const mathOps = require("../utils/math");
const logger = require("../logger");
const { slippage } = require("../fireblocksSettings");
const AggregatorService = require("./AggregatorService");
const VaultAssetService = require("./VaultAssetService");
const TransactionService = require("./TransactionService");
const ProviderService = require("./ProviderService");
const TransactionFactory = require("../factories/TransactionFactory");
const appConfig = new (require(`../config.${process.env.NODE_ENV}`))();
const FireblocksSDK = require("fireblocks-sdk").FireblocksSDK;
const fireblocks = new FireblocksSDK(
  appConfig.fireblocksSecret,
  appConfig.fireblocksKey,
);

class WithdrawService {
  constructor(securityContext) {
    this.transactionServiceInstance = new TransactionService(securityContext);
    this.vaultAssetServiceInstance = new VaultAssetService(securityContext);
    this.aggregatorServiceInstance = new AggregatorService();
  }

  execute = async (
    {
      amount,
      fireblocksAssetId,
      vaultId,
      inTokenAddress,
      externalAddress,
      txnUserId,
    },
    tenantId,
    userId,
  ) => {
    let providerService = new ProviderService(vaultId, inTokenAddress);
    const vaultAsset = await fireblocks.getVaultAccountAsset(
      vaultId,
      fireblocksAssetId,
    );
    if (vaultAsset.available < amount)
      throw new Error("Insufficient balance. Balance:" + vaultAsset.available);

    const withdrawalCommission = mathOps.getWithdrawCommission(amount);
    logger.info(`withdrawalCommission is comission is ${withdrawalCommission}`);
    const usersCut = mathOps.getUsersCut(amount);

    logger.info(`user cut is  is , ${usersCut}`);

    if (fireblocksAssetId == fireblocksSettings.usdcAssetId) {
      const cryptoWithdrawalCommissionUSDCData =
        await this.transferCommissionUSDC(
          {
            assetId: fireblocksAssetId,
            vaultId: vaultId,
            amount: withdrawalCommission,
            txnUserId: txnUserId,
          },
          tenantId,
          userId,
        );
    } else {
      const account = await this.getTxnAccount(
        vaultId,
        fireblocksAssetId,
        tenantId,
        userId,
      );
      logger.info(`Account : ${account}`);

      const commissionAccount = await this.getTxnAccount(
        fireblocksSettings.withdrawalCommission,
        fireblocksSettings.usdcAssetId,
        tenantId,
        userId,
      );
      logger.info(`Commission Account : ${commissionAccount}`);

      let gasPrice = await providerService.getGas();
      const aggregatorResult =
        await this.aggregatorServiceInstance.getCryptoWithdrawSwapQuote({
          inTokenAddress: inTokenAddress,
          withdrawalCommission: withdrawalCommission,
          gasPrice: gasPrice,
          account: commissionAccount,
        });
      logger.info("got swap quote\n" + JSON.stringify(aggregatorResult));

      const commissionData = await this.transferCommission(
        {
          assetId: fireblocksAssetId,
          vaultId: vaultId,
          contractParam: aggregatorResult.data.data,
          withdrawalCommission: withdrawalCommission,
          txnUserId: txnUserId,
          fee: aggregatorResult.data.estimatedGas,
        },
        tenantId,
        userId,
      );
    }

    const withdrawalData = await this.transferWithdrawal(
      {
        assetId: fireblocksAssetId,
        vaultId: vaultId,
        externalAddress: externalAddress,
        amount: usersCut,
        txnUserId: txnUserId,
      },
      tenantId,
      userId,
    );

    return withdrawalData;
  };

  getTxnAccount = async (vaultId, assetId, tenantId, userId) => {
    const addressResult = await this.vaultAssetServiceInstance.getAddresses(
      { vaultAccountId: vaultId, assetId: assetId },
      tenantId,
      userId,
    );
    return addressResult[0].address;
  };

  transferWithdrawal = async (
    { assetId, vaultId, externalAddress, amount, txnUserId },
    tenantId,
    userId,
  ) =>
    await this.transactionServiceInstance.create(
      TransactionFactory.cryptoWithdrawal(
        assetId,
        vaultId,
        externalAddress,
        amount,
        txnUserId,
      ),
      tenantId,
      userId,
    );

  transferCommission = async (
    { assetId, vaultId, contractParam, withdrawalCommission, txnUserId, fee },
    tenantId,
    userId,
  ) =>
    await this.transactionServiceInstance.create(
      TransactionFactory.cryptoWithdrawalCommissionContract(
        assetId,
        vaultId,
        contractParam,
        assetId === fireblocksSettings.baseAssetId ? withdrawalCommission : "0",
        txnUserId,
      ),
      tenantId,
      userId,
    );

  transferCommissionUSDC = async (
    { assetId, vaultId, amount, txnUserId },
    tenantId,
    userId,
  ) =>
    await this.transactionServiceInstance.create(
      TransactionFactory.cryptoUSDCWithdrawalCommission(
        assetId,
        vaultId,
        amount,
        txnUserId,
      ),
      tenantId,
      userId,
    );
}
module.exports = WithdrawService;

Hello @Shahid Thank you for sharing, I am with Fireblocks support and I am looking into why the execution gets reverted for this transfer.

Hello @Shahid I believe the error you received, “transfer amount exceeds allowance” refers to a smart contract level error where you must call an approve function in this BEP20 contract your interacting with. Can you please share the smart contract address?