5/5
## Understanding `MarketUtils.getNextFundingFactorPerSecond` This lesson delves into the `MarketUtils.getNextFundingFactorPerSecond` internal view function found within the `gmx-synthetics` codebase (specifically `contracts/market/MarketUtils.sol`). Its primary purpose is to determine the next funding factor per second for a given market, a crucial component of the funding fee mechanism designed to keep the open interest between long and short positions balanced. The fundamental principle driving this calculation is the **skew**, or difference, between the total long open interest and the total short open interest in the market. A larger skew generally results in a larger funding factor, creating incentives for trades that help reduce this imbalance. The calculation can follow either a static or an adaptive path, depending on market configuration. ### Key Parameters Before diving into the code, let's define the key variables involved in the calculation, often referenced during the process: * `F`: The target funding factor per second (output of parts of the calculation). * `L`: Long open interest in USD. * `S`: Short open interest in USD. * `e`: Funding exponent factor (`fundingExponentFactor`). A factor applied to the open interest difference to introduce non-linearity. * `Fi`: Funding *increase* factor per second (`fundingIncreaseFactorPerSecond`). Used in the adaptive funding calculation. If zero, static calculation is used. * `Fd`: Funding *decrease* factor per second (`fundingDecreaseFactorPerSecond`). Used in the adaptive funding calculation. * `F_min`: Minimum funding factor per second (`minFundingFactorPerSecond`). The absolute lower bound for the funding factor magnitude. * `F_max`: Maximum funding factor per second (`maxFundingFactorPerSecond`). The absolute upper bound for the funding factor magnitude. * `F_market`: A base funding factor specific to the market (`fundingFactor`). Used in the static calculation. * `f`: An intermediate value representing the normalized, exponentiated skew, calculated as `f = abs(L - S) ^ e / (L + S)`. * `F0`: The saved funding factor per second from the *previous* calculation interval (`savedFundingFactorPerSecond`). Used as the starting point for adaptive funding. * `Ts`: Threshold for stable funding (`thresholdForStableFunding`). A threshold for `f` used in adaptive funding. * `Td`: Threshold for decrease funding (`thresholdForDecreaseFunding`). A threshold for `f` used in adaptive funding. * `dt`: Duration in seconds since the last funding update (`durationInSeconds`). An input parameter. ### Function Logic and Code Walkthrough The `getNextFundingFactorPerSecond` function orchestrates the calculation based on the current market state and configuration. 1. **Function Signature:** The function is defined as internal and view, taking necessary context and market data as input: ```solidity // File: contracts/market/MarketUtils.sol function getNextFundingFactorPerSecond( DataStore dataStore, address market, uint256 longOpenInterest, uint256 shortOpenInterest, uint256 durationInSeconds ) internal view returns (uint256, bool, int256) { // ... implementation ... } ``` It receives the `dataStore` for fetching configuration, the `market` address, current `longOpenInterest` (`L`) and `shortOpenInterest` (`S`), and the `durationInSeconds` (`dt`) since the last update. It returns the magnitude of the next funding factor, a boolean indicating if it's positive (true for long pays short), and the raw signed funding factor. 2. **Initial Skew and Total Open Interest Calculation:** The function first calculates the absolute difference and the sum of the open interests: ```solidity cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest); // |L - S| cache.totalOpenInterest = longOpenInterest + shortOpenInterest; // L + S ``` 3. **Fetching Configuration:** Market-specific configuration parameters like `fundingIncreaseFactorPerSecond` (`Fi`), `fundingExponentFactor` (`e`), `fundingFactor` (`F_market`), `maxFundingFactorPerSecond` (`F_max`), `savedFundingFactorPerSecond` (`F0`), thresholds (`Ts`, `Td`), `fundingDecreaseFactorPerSecond` (`Fd`), and `minFundingFactorPerSecond` (`F_min`) are retrieved from the `dataStore` using keys specific to the `market`. 4. **Handling Edge Cases:** * If the `totalOpenInterest` is zero, the function reverts, as funding calculation is not possible. * If the absolute difference (`diffUsd`) is zero *and* the adaptive funding factor `Fi` is also zero, the funding factor is simply zero, and the function returns early. 5. **Calculating Intermediate Factor `f`:** The core skew measure `f` is calculated: ```solidity cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market); // Fetch e // Apply exponent: |L - S| ^ e cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor); // Normalize by total OI: (|L - S| ^ e) / (L + S) cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest); // This is f ``` 6. **Static vs. Adaptive Funding Path:** The calculation path diverges based on whether the `fundingIncreaseFactorPerSecond` (`Fi`) is zero. * **Static Funding Path (`Fi == 0`):** If adaptive funding is disabled (`Fi` is zero), a simpler static calculation is performed: * Fetch the market's base `fundingFactor` (`F_market`) and `maxFundingFactorPerSecond` (`F_max`). * Calculate a preliminary funding factor: `fundingFactorPerSecond = f * F_market`. This uses the intermediate skew factor `f`. * Cap the result: The calculated `fundingFactorPerSecond` is capped at `F_max`. If `fundingFactorPerSecond > F_max`, it is set to `F_max`. * The final result corresponds to the formula: `F = min(f * F_market, F_max)`. The sign depends on whether `L > S` or `S > L`. * **Adaptive Funding Path (`Fi != 0`):** If adaptive funding is enabled (`Fi` is non-zero), the funding rate adjusts incrementally from its previous value (`F0`) based on the current skew (`f`) and time elapsed (`dt`). * Fetch the `savedFundingFactorPerSecond` (`F0`), `thresholdForStableFunding` (`Ts`), `thresholdForDecreaseFunding` (`Td`), and `fundingDecreaseFactorPerSecond` (`Fd`). * **Determine Directionality:** Check if the current skew direction (`L > S` or `S > L`) matches the sign of the previous funding factor `F0`. * **Determine Change Type:** Based on the directionality check and comparing the intermediate factor `f` against thresholds `Ts` and `Td`: * If `isSkewTheSameDirectionAsFunding` is true: * If `f > Ts`, the type is `Increase`. * If `f < Td`, the type is `Decrease`. * Otherwise (`Td <= f <= Ts`), the type is `NoChange` (the rate `F0` is maintained). * If `isSkewTheSameDirectionAsFunding` is false (skew direction flipped): The type is forced to `Increase` to push the funding rate towards the new skew direction. * **Calculate Next Funding Factor (`F`) based on Change Type:** * **Increase:** The change amount is calculated as `increaseValue = f * Fi * dt`. This amount is added to the previous funding factor `F0`, ensuring the sign aligns with the current skew (positive if `L > S`, negative if `S > L`). Formula: `F = F0 +/- (f * Fi * dt)`. * **Decrease:** The change amount is calculated as `decreaseValue = Fd * dt`. The logic aims to reduce the *magnitude* of `F0` towards zero. * If `|F0| <= decreaseValue`, the new factor `F` is set to a minimal value (+1 if `F0 > 0`, -1 if `F0 < 0`) to prevent overshooting zero significantly. * Otherwise, the magnitude is reduced: `nextMagnitude = |F0| - decreaseValue`. The original sign of `F0` is reapplied to this new magnitude. Formula: `F = (|F0| - Fd * dt) * sign(F0)`. * **NoChange:** `F = F0`. 7. **Bounding the Result:** Regardless of whether the static or adaptive path was taken, the resulting funding factor (`F`) is bounded: * The magnitude `|F|` is capped at `maxFundingFactorPerSecond` (`F_max`). Formula: `F = sign(F) * min(|F|, F_max)`. * The magnitude `|F|` is also floored by `minFundingFactorPerSecond` (`F_min`). Formula: `F = sign(F) * max(|F|, F_min)`. This ensures the final funding factor per second remains within the configured acceptable range for the market. The function uses helper utilities like `Calc.boundMagnitude` to apply these bounds. ### Conclusion The `MarketUtils.getNextFundingFactorPerSecond` function implements a sophisticated mechanism for calculating funding rates in GMX Synthetics. Key takeaways include: 1. **Skew Dominance:** The difference between long and short open interest (`L` vs `S`) is the primary driver of the funding rate's magnitude and direction. 2. **Configurable Calculation:** Markets can use either a direct, static calculation (`Fi = 0`) based on the current skew and market parameters, or a more gradual, adaptive calculation (`Fi != 0`). 3. **Adaptive Gradualism:** When adaptive funding is active, the rate changes incrementally from its previous value (`F0`) based on the skew factor (`f`) relative to thresholds (`Ts`, `Td`), and specific increase/decrease factors (`Fi`, `Fd`) over time (`dt`). This smooths out rate changes. 4. **Safety Bounds:** The final calculated rate is always constrained by market-specific minimum (`F_min`) and maximum (`F_max`) bounds to ensure stability. Understanding this function provides insight into how GMX Synthetics incentivizes market balance through its funding fee mechanism.
MarketUtils.getNextFundingFactorPerSecond
This lesson delves into the MarketUtils.getNextFundingFactorPerSecond
internal view function found within the gmx-synthetics
codebase (specifically contracts/market/MarketUtils.sol
). Its primary purpose is to determine the next funding factor per second for a given market, a crucial component of the funding fee mechanism designed to keep the open interest between long and short positions balanced.
The fundamental principle driving this calculation is the skew, or difference, between the total long open interest and the total short open interest in the market. A larger skew generally results in a larger funding factor, creating incentives for trades that help reduce this imbalance. The calculation can follow either a static or an adaptive path, depending on market configuration.
Before diving into the code, let's define the key variables involved in the calculation, often referenced during the process:
F
: The target funding factor per second (output of parts of the calculation).
L
: Long open interest in USD.
S
: Short open interest in USD.
e
: Funding exponent factor (fundingExponentFactor
). A factor applied to the open interest difference to introduce non-linearity.
Fi
: Funding increase factor per second (fundingIncreaseFactorPerSecond
). Used in the adaptive funding calculation. If zero, static calculation is used.
Fd
: Funding decrease factor per second (fundingDecreaseFactorPerSecond
). Used in the adaptive funding calculation.
F_min
: Minimum funding factor per second (minFundingFactorPerSecond
). The absolute lower bound for the funding factor magnitude.
F_max
: Maximum funding factor per second (maxFundingFactorPerSecond
). The absolute upper bound for the funding factor magnitude.
F_market
: A base funding factor specific to the market (fundingFactor
). Used in the static calculation.
f
: An intermediate value representing the normalized, exponentiated skew, calculated as f = abs(L - S) ^ e / (L + S)
.
F0
: The saved funding factor per second from the previous calculation interval (savedFundingFactorPerSecond
). Used as the starting point for adaptive funding.
Ts
: Threshold for stable funding (thresholdForStableFunding
). A threshold for f
used in adaptive funding.
Td
: Threshold for decrease funding (thresholdForDecreaseFunding
). A threshold for f
used in adaptive funding.
dt
: Duration in seconds since the last funding update (durationInSeconds
). An input parameter.
The getNextFundingFactorPerSecond
function orchestrates the calculation based on the current market state and configuration.
Function Signature:
The function is defined as internal and view, taking necessary context and market data as input:
It receives the dataStore
for fetching configuration, the market
address, current longOpenInterest
(L
) and shortOpenInterest
(S
), and the durationInSeconds
(dt
) since the last update. It returns the magnitude of the next funding factor, a boolean indicating if it's positive (true for long pays short), and the raw signed funding factor.
Initial Skew and Total Open Interest Calculation:
The function first calculates the absolute difference and the sum of the open interests:
Fetching Configuration:
Market-specific configuration parameters like fundingIncreaseFactorPerSecond
(Fi
), fundingExponentFactor
(e
), fundingFactor
(F_market
), maxFundingFactorPerSecond
(F_max
), savedFundingFactorPerSecond
(F0
), thresholds (Ts
, Td
), fundingDecreaseFactorPerSecond
(Fd
), and minFundingFactorPerSecond
(F_min
) are retrieved from the dataStore
using keys specific to the market
.
Handling Edge Cases:
If the totalOpenInterest
is zero, the function reverts, as funding calculation is not possible.
If the absolute difference (diffUsd
) is zero and the adaptive funding factor Fi
is also zero, the funding factor is simply zero, and the function returns early.
Calculating Intermediate Factor f
:
The core skew measure f
is calculated:
Static vs. Adaptive Funding Path:
The calculation path diverges based on whether the fundingIncreaseFactorPerSecond
(Fi
) is zero.
Static Funding Path (Fi == 0
):
If adaptive funding is disabled (Fi
is zero), a simpler static calculation is performed:
Fetch the market's base fundingFactor
(F_market
) and maxFundingFactorPerSecond
(F_max
).
Calculate a preliminary funding factor: fundingFactorPerSecond = f * F_market
. This uses the intermediate skew factor f
.
Cap the result: The calculated fundingFactorPerSecond
is capped at F_max
. If fundingFactorPerSecond > F_max
, it is set to F_max
.
The final result corresponds to the formula: F = min(f * F_market, F_max)
. The sign depends on whether L > S
or S > L
.
Adaptive Funding Path (Fi != 0
):
If adaptive funding is enabled (Fi
is non-zero), the funding rate adjusts incrementally from its previous value (F0
) based on the current skew (f
) and time elapsed (dt
).
Fetch the savedFundingFactorPerSecond
(F0
), thresholdForStableFunding
(Ts
), thresholdForDecreaseFunding
(Td
), and fundingDecreaseFactorPerSecond
(Fd
).
Determine Directionality: Check if the current skew direction (L > S
or S > L
) matches the sign of the previous funding factor F0
.
Determine Change Type: Based on the directionality check and comparing the intermediate factor f
against thresholds Ts
and Td
:
If isSkewTheSameDirectionAsFunding
is true:
If f > Ts
, the type is Increase
.
If f < Td
, the type is Decrease
.
Otherwise (Td <= f <= Ts
), the type is NoChange
(the rate F0
is maintained).
If isSkewTheSameDirectionAsFunding
is false (skew direction flipped): The type is forced to Increase
to push the funding rate towards the new skew direction.
Calculate Next Funding Factor (F
) based on Change Type:
Increase: The change amount is calculated as increaseValue = f * Fi * dt
. This amount is added to the previous funding factor F0
, ensuring the sign aligns with the current skew (positive if L > S
, negative if S > L
). Formula: F = F0 +/- (f * Fi * dt)
.
Decrease: The change amount is calculated as decreaseValue = Fd * dt
. The logic aims to reduce the magnitude of F0
towards zero.
If |F0| <= decreaseValue
, the new factor F
is set to a minimal value (+1 if F0 > 0
, -1 if F0 < 0
) to prevent overshooting zero significantly.
Otherwise, the magnitude is reduced: nextMagnitude = |F0| - decreaseValue
. The original sign of F0
is reapplied to this new magnitude. Formula: F = (|F0| - Fd * dt) * sign(F0)
.
NoChange: F = F0
.
Bounding the Result:
Regardless of whether the static or adaptive path was taken, the resulting funding factor (F
) is bounded:
The magnitude |F|
is capped at maxFundingFactorPerSecond
(F_max
). Formula: F = sign(F) * min(|F|, F_max)
.
The magnitude |F|
is also floored by minFundingFactorPerSecond
(F_min
). Formula: F = sign(F) * max(|F|, F_min)
.
This ensures the final funding factor per second remains within the configured acceptable range for the market. The function uses helper utilities like Calc.boundMagnitude
to apply these bounds.
The MarketUtils.getNextFundingFactorPerSecond
function implements a sophisticated mechanism for calculating funding rates in GMX Synthetics. Key takeaways include:
Skew Dominance: The difference between long and short open interest (L
vs S
) is the primary driver of the funding rate's magnitude and direction.
Configurable Calculation: Markets can use either a direct, static calculation (Fi = 0
) based on the current skew and market parameters, or a more gradual, adaptive calculation (Fi != 0
).
Adaptive Gradualism: When adaptive funding is active, the rate changes incrementally from its previous value (F0
) based on the skew factor (f
) relative to thresholds (Ts
, Td
), and specific increase/decrease factors (Fi
, Fd
) over time (dt
). This smooths out rate changes.
Safety Bounds: The final calculated rate is always constrained by market-specific minimum (F_min
) and maximum (F_max
) bounds to ensure stability.
Understanding this function provides insight into how GMX Synthetics incentivizes market balance through its funding fee mechanism.
A detailed examination to Decoding GMX Funding Factor Logic - Uncover the mechanics of `MarketUtils.getNextFundingFactorPerSecond` in GMX Synthetics, focusing on open interest skew's role. Learn how static versus adaptive funding calculations determine the rate using key parameters and bounding.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Cyfrin Updraft has partnered with GMX to provide SSCD+ certifications vouchers to the first 25 students who demonstrate the completion of this course and are building on top of GMX. Join the GMX Discord server to redeem your coupon, or navigate to the docs to learn more!
Course Overview
About the course
Mechanics and contract architecture of the GMX protocol
Token pricing and fees
Liquidity: GM pools and GLV vaults
Math, funding rates, liquidation pricing, P&L calculations
Limit orders, take profit orders, stop loss, and stop market orders
Auto-cancel and auto-deleveraging
GLP, esGMX, GMX staking and delegation
DeFi Developer
$75,000 - $200,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Security researcher
$49,999 - $120,000 (avg. salary)
Last updated on June 26, 2025
Duration: 8min
Duration: 1h 19min
Duration: 1h 24min
Duration: 16min
Duration: 11min
Duration: 11min
Duration: 6min
Course Overview
About the course
Mechanics and contract architecture of the GMX protocol
Token pricing and fees
Liquidity: GM pools and GLV vaults
Math, funding rates, liquidation pricing, P&L calculations
Limit orders, take profit orders, stop loss, and stop market orders
Auto-cancel and auto-deleveraging
GLP, esGMX, GMX staking and delegation
DeFi Developer
$75,000 - $200,000 (avg. salary)
Smart Contract Engineer
$100,000 - $150,000 (avg. salary)
Web3 developer
$60,000 - $150,000 (avg. salary)
Web3 Developer Relations
$85,000 - $125,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Security researcher
$49,999 - $120,000 (avg. salary)
Last updated on June 26, 2025