Skip to content

Commit

Permalink
fix rounding issues
Browse files Browse the repository at this point in the history
  • Loading branch information
xdev10 committed Jun 12, 2023
1 parent fbca7f2 commit f8cdb4d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 27 deletions.
45 changes: 20 additions & 25 deletions contracts/market/MarketUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1118,13 +1118,21 @@ library MarketUtils {
function getFundingAmountPerSizeDelta(
uint256 fundingAmount,
uint256 openInterest,
bool roundUp
bool roundUpMagnitude
) internal pure returns (uint256) {
if (fundingAmount == 0 || openInterest == 0) { return 0; }

uint256 divisor = Calc.roundUpDivision(openInterest, Precision.FLOAT_PRECISION_SQRT);
uint256 divisor;

return Precision.toFactor(fundingAmount, divisor, roundUp);
// if the magnitude should be rounded up, then round the divisor down
// if the magnitude should not be rounded up, then round the divisor up
if (roundUpMagnitude) {
divisor = openInterest / Precision.FLOAT_PRECISION_SQRT;
} else {
divisor = Calc.roundUpDivision(openInterest, Precision.FLOAT_PRECISION_SQRT);
}

return Precision.toFactor(fundingAmount, divisor, roundUpMagnitude);
}

// @dev update the cumulative borrowing factor for a market
Expand Down Expand Up @@ -1354,33 +1362,20 @@ library MarketUtils {
) internal pure returns (int256) {
int256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);

// divide the positionSizeInUsd by Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values
// are stored based on FLOAT_PRECISION_SQRT values instead of FLOAT_PRECISION to reduce the chance
// of overflows
// adjustedPositionSizeInUsd will always be zero if positionSizeInUsd is less than Precision.FLOAT_PRECISION_SQRT
// position sizes should be validated to be above a minimum amount
// to prevent gaming by using small positions to avoid paying funding fees
uint256 adjustedPositionSizeInUsd = positionSizeInUsd / Precision.FLOAT_PRECISION_SQRT;

int256 numerator = adjustedPositionSizeInUsd.toInt256() * fundingDiffFactor;

if (numerator == 0) { return 0; }

// if the funding fee amount is negative, it means this amount should be claimable
// by the user
// round the funding fee amount down for this case
if (numerator < 0) {
return numerator / Precision.FLOAT_PRECISION.toInt256();
}

// a user could avoid paying funding fees by continually updating the position
// before the funding fee becomes large enough to be chargeable
// to avoid this, the funding fee amount is rounded up if it is positive
//
// this could lead to large additional charges if the token has a low number of decimals
// or if the token's value is very high, so care should be taken to inform user's if that
// is the case
return Calc.roundUpMagnitudeDivision(numerator, Precision.FLOAT_PRECISION);
// or if the token's value is very high, so care should be taken to inform users of this
//
// if the fundingDiffFactor is negative, it means this amount should be claimable
// by the user round the funding fee amount down for this case
bool roundUpMagnitude = fundingDiffFactor > 0;

// divide the result by Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values
// are stored based on FLOAT_PRECISION_SQRT values
return Precision.applyFactor(positionSizeInUsd, fundingDiffFactor, roundUpMagnitude) / Precision.FLOAT_PRECISION_SQRT.toInt256();
}

// @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor
Expand Down
21 changes: 19 additions & 2 deletions contracts/utils/Precision.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ library Precision {
return applyFraction(value, factor, FLOAT_PRECISION);
}

function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {
return applyFraction(value, factor, FLOAT_PRECISION, roundUpMagnitude);
}

function applyFraction(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {
return Math.mulDiv(value, numerator, denominator);
}
Expand All @@ -61,6 +65,19 @@ library Precision {
return numerator > 0 ? result.toInt256() : -result.toInt256();
}

function applyFraction(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {
uint256 result = applyFraction(value, numerator.abs(), denominator, roundUpMagnitude);
return numerator > 0 ? result.toInt256() : -result.toInt256();
}

function applyFraction(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {
if (roundUpMagnitude) {
return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);
}

return Math.mulDiv(value, numerator, denominator);
}

function applyExponentFactor(
uint256 floatValue,
uint256 exponentFactor
Expand All @@ -84,10 +101,10 @@ library Precision {
return weiToFloat(weiValue);
}

function toFactor(uint256 value, uint256 divisor, bool roundUp) internal pure returns (uint256) {
function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {
if (value == 0) { return 0; }

if (roundUp) {
if (roundUpMagnitude) {
return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);
}

Expand Down

0 comments on commit f8cdb4d

Please sign in to comment.