5/5
## Calculating Borrowing Fees in GMX Synthetics Understanding how fees are calculated is crucial when interacting with decentralized finance (DeFi) protocols. In GMX Synthetics, borrowing fees are applied to leveraged positions. This lesson dives into the specific mechanism and Solidity code used to determine these fees, focusing on the `getBorrowingFees` function found within the GMX protocol's smart contracts. **Locating the Logic: `MarketUtils.sol`** The core logic for calculating borrowing fees resides in the `gmx-synthetics` repository, specifically within the `MarketUtils.sol` contract file: `contracts/market/MarketUtils.sol` The primary function responsible is `getBorrowingFees`. **The Role of the Cumulative Borrowing Factor** GMX Synthetics employs a `cumulativeBorrowingFactor` for each market (e.g., ETH/USD). This isn't the instantaneous borrowing rate; instead, it represents the *accumulated sum* of borrowing rates over time for that specific market. Think of it as a running total that grows based on borrowing demand and duration. When a user opens or modifies a leveraged position, the protocol takes a snapshot of the market's current `cumulativeBorrowingFactor` and stores it within the position's data (`position.borrowingFactor`). This snapshot serves as a reference point for future fee calculations. **The `getBorrowingFees` Function Explained** The `getBorrowingFees` function calculates the borrowing fees accrued on a specific position *since its last update* (when `position.borrowingFactor` was last recorded). **Function Signature:** ```solidity function getBorrowingFees( DataStore dataStore, Position.Props memory position ) internal view returns (uint256) ``` * **`dataStore`**: Provides access to necessary market data, including the latest cumulative factors. * **`position`**: A struct (`Position.Props`) containing all relevant details about the user's position, including its size (`sizeInUsd`), market, and the last recorded borrowing factor (`borrowingFactor`). * **`returns (uint256)`**: The calculated borrowing fee amount (with precision). **Crucial Precondition:** As noted in the contract's comments, this function operates under the assumption that the market's `cumulativeBorrowingFactor` has already been updated to its most current value *before* `getBorrowingFees` is invoked. **Step-by-Step Calculation:** 1. **Fetch the Latest Factor:** The function first retrieves the *current* `cumulativeBorrowingFactor` for the market associated with the input `position`. ```solidity // Get the latest cumulative borrowing factor for the position's market uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market); ``` 2. **Safety Check:** A sanity check ensures the factor stored within the position (`position.borrowingFactor`) is not greater than the current market factor. If it were, it would imply an inconsistency or error. ```solidity // Safety check: The stored factor should not be greater than the current one if (position.borrowingFactor > cumulativeBorrowingFactor) { revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor, cumulativeBorrowingFactor); } ``` 3. **Calculate the Factor Difference (`diffFactor`):** The core of the calculation lies in determining how much the `cumulativeBorrowingFactor` has increased since the position's factor was last recorded. This difference (`diffFactor`) represents the aggregate borrowing rate multiplier applicable to the position during that time period. ```solidity // Calculate the difference since the position was last updated uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor; ``` 4. **Apply Factor to Position Size:** Finally, the calculated `diffFactor` is multiplied by the size of the position, denominated in USD (`position.sizeInUsd`). The `Precision.applyFactor` helper function handles this multiplication while managing the fixed-point precision used throughout the GMX contracts. The result is the total borrowing fee accrued in USD terms (with precision). ```solidity // Apply the difference factor to the position's size in USD // Precision.applyFactor performs multiplication handling precision return Precision.applyFactor(position.sizeInUsd, diffFactor); ``` **Summary Formula:** The calculation can be conceptually summarized as: `Borrowing Fee = Position Size (USD) * (Current Cumulative Borrowing Factor - Position's Last Recorded Borrowing Factor)` **Key Concepts Recap:** * **Position (`Position.Props`)**: Stores details of a leveraged trade, including its USD size, market, and the `borrowingFactor` captured at its last update. * **Cumulative Borrowing Factor**: A market-level metric tracking the sum of borrowing rates over time. * **`diffFactor`**: The change in the `cumulativeBorrowingFactor` since the position was last updated, representing the effective rate multiplier for that period. * **Borrowing Fee**: The cost incurred for leverage, calculated by applying the `diffFactor` to the position's USD size. This mechanism ensures that borrowing fees accurately reflect both the size of the position and the duration for which leverage was utilized, based on the dynamically changing market borrowing conditions captured by the `cumulativeBorrowingFactor`.
Understanding how fees are calculated is crucial when interacting with decentralized finance (DeFi) protocols. In GMX Synthetics, borrowing fees are applied to leveraged positions. This lesson dives into the specific mechanism and Solidity code used to determine these fees, focusing on the getBorrowingFees
function found within the GMX protocol's smart contracts.
Locating the Logic: MarketUtils.sol
The core logic for calculating borrowing fees resides in the gmx-synthetics
repository, specifically within the MarketUtils.sol
contract file:
contracts/market/MarketUtils.sol
The primary function responsible is getBorrowingFees
.
The Role of the Cumulative Borrowing Factor
GMX Synthetics employs a cumulativeBorrowingFactor
for each market (e.g., ETH/USD). This isn't the instantaneous borrowing rate; instead, it represents the accumulated sum of borrowing rates over time for that specific market. Think of it as a running total that grows based on borrowing demand and duration.
When a user opens or modifies a leveraged position, the protocol takes a snapshot of the market's current cumulativeBorrowingFactor
and stores it within the position's data (position.borrowingFactor
). This snapshot serves as a reference point for future fee calculations.
The getBorrowingFees
Function Explained
The getBorrowingFees
function calculates the borrowing fees accrued on a specific position since its last update (when position.borrowingFactor
was last recorded).
Function Signature:
dataStore
: Provides access to necessary market data, including the latest cumulative factors.
position
: A struct (Position.Props
) containing all relevant details about the user's position, including its size (sizeInUsd
), market, and the last recorded borrowing factor (borrowingFactor
).
returns (uint256)
: The calculated borrowing fee amount (with precision).
Crucial Precondition: As noted in the contract's comments, this function operates under the assumption that the market's cumulativeBorrowingFactor
has already been updated to its most current value before getBorrowingFees
is invoked.
Step-by-Step Calculation:
Fetch the Latest Factor: The function first retrieves the current cumulativeBorrowingFactor
for the market associated with the input position
.
Safety Check: A sanity check ensures the factor stored within the position (position.borrowingFactor
) is not greater than the current market factor. If it were, it would imply an inconsistency or error.
Calculate the Factor Difference (diffFactor
): The core of the calculation lies in determining how much the cumulativeBorrowingFactor
has increased since the position's factor was last recorded. This difference (diffFactor
) represents the aggregate borrowing rate multiplier applicable to the position during that time period.
Apply Factor to Position Size: Finally, the calculated diffFactor
is multiplied by the size of the position, denominated in USD (position.sizeInUsd
). The Precision.applyFactor
helper function handles this multiplication while managing the fixed-point precision used throughout the GMX contracts. The result is the total borrowing fee accrued in USD terms (with precision).
Summary Formula:
The calculation can be conceptually summarized as:
Borrowing Fee = Position Size (USD) * (Current Cumulative Borrowing Factor - Position's Last Recorded Borrowing Factor)
Key Concepts Recap:
Position (Position.Props
): Stores details of a leveraged trade, including its USD size, market, and the borrowingFactor
captured at its last update.
Cumulative Borrowing Factor: A market-level metric tracking the sum of borrowing rates over time.
diffFactor
: The change in the cumulativeBorrowingFactor
since the position was last updated, representing the effective rate multiplier for that period.
Borrowing Fee: The cost incurred for leverage, calculated by applying the diffFactor
to the position's USD size.
This mechanism ensures that borrowing fees accurately reflect both the size of the position and the duration for which leverage was utilized, based on the dynamically changing market borrowing conditions captured by the cumulativeBorrowingFactor
.
A technical breakdown to Calculating GMX Borrowing Fees - Dive into the `MarketUtils.sol` contract to see how the `getBorrowingFees` function calculates costs. Understand the role of the `cumulativeBorrowingFactor` and how it's applied to position size.
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