DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Critical Precision Loss in PnL Calculations Leading to Significant User Losses

[H-02] Critical Precision Loss in PnL Calculations Leading to Significant User Losses

Description

The PerpetualVault contract contains a critical precision loss vulnerability in its PnL calculations. When calculating profits and losses, the contract performs division operations before applying precision multipliers, resulting in severe truncation of user profits.

Impact

HIGH - Direct financial loss to users

  • Users receive near-zero profits on profitable trades

  • Most severely impacts:

    • Large positions (>$100k)

    • Leveraged positions (especially 5x-10x)

    • Small price movements (<1%)

  • Loss severity increases with position size

  • Affects all profitable trades across the protocol

Proof of Concept

Testing with a realistic scenario demonstrates the severity:

contract PrecisionLossExploit {
uint256 constant PRECISION = 1e18;
uint256 constant BASIS_POINTS_DIVISOR = 10000;
function simulateRealPnLCalculation(
uint256 size,
uint256 priceDelta,
uint256 avgPrice
) public pure returns (uint256) {
// Current implementation (loses precision)
uint256 delta = (size * priceDelta) / avgPrice;
return delta / BASIS_POINTS_DIVISOR;
}
function simulateCorrectPnLCalculation(
uint256 size,
uint256 priceDelta,
uint256 avgPrice
) public pure returns (uint256) {
// Correct implementation (maintains precision)
return (size * priceDelta * PRECISION) / (avgPrice * BASIS_POINTS_DIVISOR);
}
}

Testing with $100k position at 10x leverage:

Position: $100,000
Leverage: 10x
Price Movement: +1%
Expected PnL: $1,000.00
Actual PnL: $0.10
Lost Value: $999.90 (99.99% loss)

Root Cause

The vulnerability stems from incorrect ordering of arithmetic operations:

// Vulnerable implementation (PerpetualVault.sol:224)
profit = (baseValue * change) / divisor / PRECISION; // Precision lost
// Correct implementation
profit = (baseValue * change * PRECISION) / divisor; // Precision maintained

Recommendations

Short Term

  1. Reorder arithmetic operations to maintain precision:

function calculatePnL(uint256 baseValue, uint256 change) public pure returns (uint256) {
return (baseValue * change * PRECISION) / BASIS_POINTS_DIVISOR;
}

Long Term

  1. Implement comprehensive decimal handling library

  2. Add invariant tests for precision maintenance

  3. Implement minimum profit thresholds

  4. Consider using established fixed-point arithmetic libraries (e.g. PRBMath)

Risk Assessment

Impact Analysis

  • Financial: Critical (99.99% profit loss)

  • Scope: All users with profitable trades

  • Complexity: Low (fundamental calculation error)

Affected Components

  • PnL calculations

  • Profit distribution

  • Fee calculations

  • Position valuations

Timeline

  • Found: February 20, 2025

  • Reported: February 21, 2025

  • Fixed: Pending

Updates

Lead Judging Commences

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality
Assigned finding tags:

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.