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:
| Field | Type | Description |
|---|---|---|
feeUsd | bigint | Total fee in USD (30-decimal precision) |
feeTokenAmount | bigint | Total fee in native token units |
feeToken | Token | Native token data |
gasLimit | bigint | Adjusted gas limit (after multiplier) |
isFeeHigh | boolean | true when fee exceeds the chain's high-fee threshold |
isFeeVeryHigh | boolean | true 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.
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.
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.
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,
});