Skip to main content

executionFee

This module provides utilities for calculating execution fees and estimating gas limits for various GMX protocol operations. It handles fee calculations for orders, deposits, withdrawals, and batch operations while considering network-specific gas costs and limits.

Methods

The executionFee module exports two categories of functions: fee calculation functions that convert a gas limit into a token amount the user must pay, and gas estimation functions that compute the gas limit for each operation type.

Fee calculation

getExecutionFee

getExecutionFee(
chainId: number,
gasLimits: GasLimitsConfig,
tokensData: TokensData,
estimatedGasLimit: bigint,
gasPrice: bigint,
oraclePriceCount: bigint,
numberOfParts?: number
): ExecutionFee | undefined

Converts an estimated gas limit into a full ExecutionFee object. Internally it applies the estimatedFeeMultiplierFactor from GasLimitsConfig and adds per-oracle-price overhead before multiplying by gasPrice. Returns undefined if the native token is not found in tokensData.

The returned ExecutionFee contains:

FieldTypeDescription
feeUsdbigintTotal fee in USD (30-decimal precision)
feeTokenAmountbigintTotal fee in native token units
feeTokenTokenNative token data
gasLimitbigintAdjusted gas limit (after multiplier)
isFeeHighbooleantrue when fee exceeds the chain's high-fee threshold
isFeeVeryHighbooleantrue when fee exceeds the chain's excessive-fee threshold
import { getExecutionFee } from "@gmx-io/sdk/utils/fees";

const executionFee = getExecutionFee(
42161, // Arbitrum
gasLimits,
tokensData,
500000n, // estimated gas for the operation
1000000000n, // gas price in wei
2n // number of oracle prices required
);

if (executionFee) {
console.log("Fee USD:", executionFee.feeUsd);
console.log("Fee token amount:", executionFee.feeTokenAmount);
if (executionFee.isFeeVeryHigh) {
console.warn("Execution fee is excessively high");
} else if (executionFee.isFeeHigh) {
console.warn("Execution fee is high");
}
}

estimateRelayerGasLimit

estimateRelayerGasLimit(params: {
gasLimits: GasLimitsConfig;
tokenPermitsCount: number;
feeSwapsCount: number;
feeExternalCallsGasLimit: bigint;
oraclePriceCount: number;
transactionPayloadGasLimit: bigint;
l1GasLimit: bigint;
}): bigint

Estimates the total gas limit for a relayer-submitted Express Trading transaction. The total is the sum of: per-permit overhead, per-fee-swap overhead, per-oracle-price overhead, external calls gas limit, the transaction payload gas limit, and the L1 gas buffer.

import { estimateRelayerGasLimit } from "@gmx-io/sdk/utils/fees";

const gasLimit = estimateRelayerGasLimit({
gasLimits,
tokenPermitsCount: 1,
feeSwapsCount: 1, // 1 swap needed to convert payment token to relay fee token
feeExternalCallsGasLimit: 0n,
oraclePriceCount: 3,
transactionPayloadGasLimit: 200000n,
l1GasLimit: 0n, // non-zero only for L1-anchored chains
});

approximateL1GasBuffer

approximateL1GasBuffer(params: {
l1Reference: L1ExpressOrderGasReference;
sizeOfData: bigint;
}): bigint

Estimates the L1 gas buffer for an Express Trading transaction by logarithmically scaling the reference gas limit based on data size. The formula is:

result = round(l1Reference.gasLimit × log(sizeOfData) / log(l1Reference.sizeOfData))

Falls back to l1Reference.gasLimit if the logarithm produces a non-finite value (for example, when sizeOfData is 0n).

import { approximateL1GasBuffer } from "@gmx-io/sdk/utils/fees";

const l1GasBuffer = approximateL1GasBuffer({
l1Reference: {
gasLimit: 100000n,
sizeOfData: 1000n, // reference data size in bytes
},
sizeOfData: 1500n, // actual data size for this transaction
});

estimateBatchGasLimit

estimateBatchGasLimit(params: {
gasLimits: GasLimitsConfig;
createOrdersCount: number;
updateOrdersCount: number;
cancelOrdersCount: number;
externalCallsGasLimit: bigint;
isGmxAccount: boolean;
}): bigint

Estimates the gas limit for a batch of order operations. Adds a gmxAccountCollateralGasLimit overhead when isGmxAccount is true.

import { estimateBatchGasLimit } from "@gmx-io/sdk/utils/fees";

const batchGasLimit = estimateBatchGasLimit({
gasLimits,
createOrdersCount: 2,
updateOrdersCount: 0,
cancelOrdersCount: 1,
externalCallsGasLimit: 0n,
isGmxAccount: false,
});

estimateBatchMinGasPaymentTokenAmount

estimateBatchMinGasPaymentTokenAmount(params: {
chainId: ContractsChainId;
gasPaymentToken: TokenData;
isGmxAccount: boolean;
relayFeeToken: TokenData;
gasPrice: bigint;
gasLimits: GasLimitsConfig;
l1Reference: L1ExpressOrderGasReference | undefined;
tokensData: TokensData;
createOrdersCount?: number; // default: 1
updateOrdersCount?: number; // default: 0
cancelOrdersCount?: number; // default: 0
executionFeeAmount?: bigint; // pass to override the estimated execution fee
}): bigint

Estimates the minimum amount of gasPaymentToken the user must hold to cover a batch Express Trading transaction — including the relayer fee, batch gas limit, and execution fee. Converts the total from the relay fee token denomination to the payment token denomination.

note

chainId must be a ContractsChainId (a supported chain ID literal), not a generic number.

import { estimateBatchMinGasPaymentTokenAmount } from "@gmx-io/sdk/utils/fees";

const minPayment = estimateBatchMinGasPaymentTokenAmount({
chainId: 42161, // ContractsChainId for Arbitrum
gasPaymentToken: usdcToken,
isGmxAccount: false,
relayFeeToken: wethToken,
gasPrice: 1000000000n,
gasLimits,
l1Reference: undefined,
tokensData,
createOrdersCount: 2,
updateOrdersCount: 0,
cancelOrdersCount: 1,
});

Gas estimation

These functions mirror their on-chain counterparts (Copy from contract in the source). They compute the gas limit for specific operation types by combining the base limit from GasLimitsConfig with per-swap and callback overheads.

estimateExecuteIncreaseOrderGasLimit

estimateExecuteIncreaseOrderGasLimit(
gasLimits: GasLimitsConfig,
order: { swapsCount?: number; callbackGasLimit?: bigint }
): bigint

Estimates gas for a Market Increase or Limit Increase order. swapsCount defaults to 0.

import { estimateExecuteIncreaseOrderGasLimit } from "@gmx-io/sdk/utils/fees";

const gasLimit = estimateExecuteIncreaseOrderGasLimit(gasLimits, {
swapsCount: 1, // number of token swaps along the collateral path
callbackGasLimit: 0n,
});

estimateExecuteDecreaseOrderGasLimit

estimateExecuteDecreaseOrderGasLimit(
gasLimits: GasLimitsConfig,
order: {
swapsCount: number;
callbackGasLimit?: bigint;
decreaseSwapType?: DecreasePositionSwapType;
}
): bigint

Estimates gas for a Market Decrease, Limit Decrease, Stop-Loss, or Take-Profit order. When decreaseSwapType is not NoSwap, one additional swap is added to swapsCount.

import { estimateExecuteDecreaseOrderGasLimit } from "@gmx-io/sdk/utils/fees";
import { DecreasePositionSwapType } from "@gmx-io/sdk/utils/orders";

const gasLimit = estimateExecuteDecreaseOrderGasLimit(gasLimits, {
swapsCount: 0,
decreaseSwapType: DecreasePositionSwapType.SwapCollateralTokenToPnlToken,
});

estimateExecuteSwapOrderGasLimit

estimateExecuteSwapOrderGasLimit(
gasLimits: GasLimitsConfig,
order: { swapsCount: number; callbackGasLimit?: bigint }
): bigint

Estimates gas for a Market Swap or Limit Swap order.

import { estimateExecuteSwapOrderGasLimit } from "@gmx-io/sdk/utils/fees";

const gasLimit = estimateExecuteSwapOrderGasLimit(gasLimits, {
swapsCount: 2, // number of market hops in the swap path
callbackGasLimit: 0n,
});

estimateExecuteDepositGasLimit

estimateExecuteDepositGasLimit(
gasLimits: GasLimitsConfig,
deposit: { swapsCount?: number | bigint; callbackGasLimit?: bigint }
): bigint

Estimates gas for a GM token deposit (not a position increase). swapsCount is the total number of input-token swaps required before the deposit — for example, 2 when depositing USDC into an ETH/USDC market that accepts only the long and short tokens individually.

note

This function is for GM pool deposits only. For position increases (Market Increase / Limit Increase), use estimateExecuteIncreaseOrderGasLimit.

import { estimateExecuteDepositGasLimit } from "@gmx-io/sdk/utils/fees";

const gasLimit = estimateExecuteDepositGasLimit(gasLimits, {
swapsCount: 2, // total token swaps needed before the deposit
callbackGasLimit: 0n,
});

estimateExecuteGlvDepositGasLimit

estimateExecuteGlvDepositGasLimit(
gasLimits: GasLimitsConfig,
params: {
isMarketTokenDeposit: boolean;
marketsCount: bigint;
swapsCount: bigint;
}
): bigint

Estimates gas for a GLV deposit. When isMarketTokenDeposit is true, the user deposits GM tokens directly and no deposit or swap gas is added — only the GLV base gas and per-market overhead. When false, the base GM deposit gas and swap gas are added on top.

import { estimateExecuteGlvDepositGasLimit } from "@gmx-io/sdk/utils/fees";

// Deposit raw tokens (not GM tokens) into a GLV vault across 5 markets with 1 input swap
const gasLimit = estimateExecuteGlvDepositGasLimit(gasLimits, {
isMarketTokenDeposit: false,
marketsCount: 5n,
swapsCount: 1n,
});

estimateExecuteGlvWithdrawalGasLimit

estimateExecuteGlvWithdrawalGasLimit(
gasLimits: GasLimitsConfig,
params: { marketsCount: bigint; swapsCount: bigint }
): bigint

Estimates gas for a GLV withdrawal. Both marketsCount and swapsCount affect the result.

import { estimateExecuteGlvWithdrawalGasLimit } from "@gmx-io/sdk/utils/fees";

const gasLimit = estimateExecuteGlvWithdrawalGasLimit(gasLimits, {
marketsCount: 5n,
swapsCount: 1n,
});

estimateExecuteWithdrawalGasLimit

estimateExecuteWithdrawalGasLimit(
gasLimits: GasLimitsConfig,
withdrawal: { callbackGasLimit?: bigint; swapsCount?: bigint }
): bigint

Estimates gas for a GM token withdrawal (not a position decrease). swapsCount defaults to 0n.

note

This function is for GM pool withdrawals only. For position decreases, use estimateExecuteDecreaseOrderGasLimit.

import { estimateExecuteWithdrawalGasLimit } from "@gmx-io/sdk/utils/fees";

const gasLimit = estimateExecuteWithdrawalGasLimit(gasLimits, {
swapsCount: 1n, // token swaps performed after the withdrawal
callbackGasLimit: 0n,
});

estimateExecuteShiftGasLimit

estimateExecuteShiftGasLimit(
gasLimits: GasLimitsConfig,
shift: { callbackGasLimit?: bigint }
): bigint

Estimates gas for a GM pool shift (moving liquidity from one market to another without withdrawing).

import { estimateExecuteShiftGasLimit } from "@gmx-io/sdk/utils/fees";

const gasLimit = estimateExecuteShiftGasLimit(gasLimits, {
callbackGasLimit: 0n,
});