5/5
## Calculating the Updated Cumulative Borrowing Factor in GMX Synthetics This lesson delves into the calculation of the `nextCumulativeBorrowingFactor` within the `MarketUtils.sol` contract of the GMX Synthetics protocol. Understanding this calculation is key to comprehending how borrowing fees accrue for positions over time. The function `getNextCumulativeBorrowingFactor` is an internal view function responsible for determining what the cumulative borrowing factor *should* be at the current block timestamp, based on the time elapsed since its last update and the prevailing borrowing rate. The `cumulativeBorrowingFactor` itself represents the total accumulated borrowing cost multiplier for a specific market (e.g., ETH) and position side (long or short). It doesn't get updated with every passing second due to gas cost constraints. Instead, it's updated periodically or when necessary (like during position interactions). This function calculates the value this factor would have if it *were* updated at the current moment. Let's break down the steps involved in the `getNextCumulativeBorrowingFactor` function: **1. Calculate Time Elapsed (`durationInSeconds`)** The first step is to determine how much time has passed since the `cumulativeBorrowingFactor` for the specific market and position side was last recorded. ```solidity // Line 2348 uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong); ``` This line calls a helper function, `getSecondsSinceCumulativeBorrowingFactorUpdated`, which queries the `DataStore` contract to retrieve the timestamp of the last update and calculates the difference from the current block timestamp, returning the duration in seconds. **2. Get the Current Borrowing Rate (`borrowingFactorPerSecond`)** Next, the function needs the current rate at which borrowing costs accrue per second. ```solidity // Lines 2349-2353 uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond( dataStore, market, prices, isLong ); ``` This involves calling another helper function, `getBorrowingFactorPerSecond`. The precise mechanics of how this per-second rate is determined (often based on factors like pool utilization) are handled within that function and are not detailed within `getNextCumulativeBorrowingFactor` itself. For the purpose of this calculation, we treat it as providing the relevant instantaneous borrowing rate. **3. Retrieve the Last Stored Factor (`cumulativeBorrowingFactor`)** To calculate the *updated* factor, we need the *previous* value as a starting point. ```solidity // Line 2355 uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong); ``` This line fetches the most recently saved `cumulativeBorrowingFactor` for the given market and side from the `DataStore`. **4. Calculate the Increase (`delta`)** This is where the core calculation happens, determining how much the factor should have increased during the `durationInSeconds`. ```solidity // Line 2357 uint256 delta = durationInSeconds * borrowingFactorPerSecond; ``` Crucially, instead of simulating the passage of time second-by-second and adding the `borrowingFactorPerSecond` iteratively (which would be computationally expensive and consume significant gas), the code performs a single multiplication. This approach relies on the assumption that the `borrowingFactorPerSecond` remained constant during the `durationInSeconds`. By multiplying the total duration by the per-second rate, we efficiently calculate the total accumulated increase (`delta`) over that period. This is a significant gas optimization. While mathematically equivalent to summing the rate for each second *if the rate is constant*, multiplication is far cheaper on-chain. **5. Calculate the Updated Factor (`nextCumulativeBorrowingFactor`)** With the increase (`delta`) calculated, the final step is to add it to the previously stored value. ```solidity // Line 2358 uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta; ``` This yields the `nextCumulativeBorrowingFactor` – the value the factor should hold at the current time. **6. Return Values** Finally, the function returns the calculated values. ```solidity // Line 2360 return (nextCumulativeBorrowingFactor, delta); ``` It provides both the newly computed `nextCumulativeBorrowingFactor` and the `delta` (the total increase calculated in step 4). Returning the `delta` can be useful for callers who might need to know the incremental change. In summary, `getNextCumulativeBorrowingFactor` calculates the up-to-date cumulative borrowing factor by: * Determining the time elapsed since the last update. * Fetching the current borrowing rate per second. * Retrieving the last saved factor value. * Calculating the total increase (`delta`) using efficient multiplication (duration * rate). * Adding the `delta` to the last saved factor. This process ensures that borrowing costs can be accurately accounted for whenever needed, using a gas-optimized approach that assumes a constant borrowing rate between updates.
This lesson delves into the calculation of the nextCumulativeBorrowingFactor
within the MarketUtils.sol
contract of the GMX Synthetics protocol. Understanding this calculation is key to comprehending how borrowing fees accrue for positions over time. The function getNextCumulativeBorrowingFactor
is an internal view function responsible for determining what the cumulative borrowing factor should be at the current block timestamp, based on the time elapsed since its last update and the prevailing borrowing rate.
The cumulativeBorrowingFactor
itself represents the total accumulated borrowing cost multiplier for a specific market (e.g., ETH) and position side (long or short). It doesn't get updated with every passing second due to gas cost constraints. Instead, it's updated periodically or when necessary (like during position interactions). This function calculates the value this factor would have if it were updated at the current moment.
Let's break down the steps involved in the getNextCumulativeBorrowingFactor
function:
1. Calculate Time Elapsed (durationInSeconds
)
The first step is to determine how much time has passed since the cumulativeBorrowingFactor
for the specific market and position side was last recorded.
This line calls a helper function, getSecondsSinceCumulativeBorrowingFactorUpdated
, which queries the DataStore
contract to retrieve the timestamp of the last update and calculates the difference from the current block timestamp, returning the duration in seconds.
2. Get the Current Borrowing Rate (borrowingFactorPerSecond
)
Next, the function needs the current rate at which borrowing costs accrue per second.
This involves calling another helper function, getBorrowingFactorPerSecond
. The precise mechanics of how this per-second rate is determined (often based on factors like pool utilization) are handled within that function and are not detailed within getNextCumulativeBorrowingFactor
itself. For the purpose of this calculation, we treat it as providing the relevant instantaneous borrowing rate.
3. Retrieve the Last Stored Factor (cumulativeBorrowingFactor
)
To calculate the updated factor, we need the previous value as a starting point.
This line fetches the most recently saved cumulativeBorrowingFactor
for the given market and side from the DataStore
.
4. Calculate the Increase (delta
)
This is where the core calculation happens, determining how much the factor should have increased during the durationInSeconds
.
Crucially, instead of simulating the passage of time second-by-second and adding the borrowingFactorPerSecond
iteratively (which would be computationally expensive and consume significant gas), the code performs a single multiplication. This approach relies on the assumption that the borrowingFactorPerSecond
remained constant during the durationInSeconds
. By multiplying the total duration by the per-second rate, we efficiently calculate the total accumulated increase (delta
) over that period. This is a significant gas optimization. While mathematically equivalent to summing the rate for each second if the rate is constant, multiplication is far cheaper on-chain.
5. Calculate the Updated Factor (nextCumulativeBorrowingFactor
)
With the increase (delta
) calculated, the final step is to add it to the previously stored value.
This yields the nextCumulativeBorrowingFactor
– the value the factor should hold at the current time.
6. Return Values
Finally, the function returns the calculated values.
It provides both the newly computed nextCumulativeBorrowingFactor
and the delta
(the total increase calculated in step 4). Returning the delta
can be useful for callers who might need to know the incremental change.
In summary, getNextCumulativeBorrowingFactor
calculates the up-to-date cumulative borrowing factor by:
Determining the time elapsed since the last update.
Fetching the current borrowing rate per second.
Retrieving the last saved factor value.
Calculating the total increase (delta
) using efficient multiplication (duration * rate).
Adding the delta
to the last saved factor.
This process ensures that borrowing costs can be accurately accounted for whenever needed, using a gas-optimized approach that assumes a constant borrowing rate between updates.
A detailed breakdown to Calculating the Next Cumulative Borrowing Factor - Explore how GMX Synthetics computes the updated cumulative borrowing factor in `MarketUtils.sol`. Learn how elapsed time and the borrowing rate per second are multiplied to efficiently determine the next factor value.
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