Incorrect funding-rate calculation
Description
The protocol implements a velocity-based funding-rate model where the velocity is defined as follows:
And the actual funding rate is defined as follows:
As per the documentation, there are nine different cases to calculate the funding rate depending upon the current state of velocity and previous funding rate. The code missed two of these cases while calculating the funding rate, due to which the resulting funding rate calculations are incorrect. These two cases are
abs(newFundingRate) < abs(lastFundingRate)
andabs(newFundingRate) < maxFundingRate
andlastVelocity < 0
abs(newFundingRate) < abs(lastFundingRate)
andabs(newFundingRate) < maxFundingRate
andlastVelocity > 0
For example, for the first case, to calculate the funding rate, the area under the curve of the image shown below is needed.
To calculate the area, the area crossed in blue is not required as it cancels out, and only the area crossed with red is required. Therefore, the effective numBlocksToCharge
should be
numBlocks - int256(2 * absNewFundingRate / absLastVelocity)
instead of this (as currently defined in the code):
numBlocks - int256(2 * absLastFundingRate / absLastVelocity)
Impact
As the case is not considered in the code, in the above cases, the value of numBlocksToCharge
would become negative. And while calculating accumulated_funding_rate_change
, this would lead to an integer overflow, which would revert the transaction.
Recommendations
Add the missing cases in the getPendingAccFundingFees
function.
Remediation
This issue has been acknowledged by Ostium Labs, and fixes were implemented in the following commits: