Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broad Khaki Wasp - Incorrect rounding in the ReputationMarket._calcCost() function. #66

Open
sherlock-admin3 opened this issue Dec 30, 2024 · 0 comments

Comments

@sherlock-admin3
Copy link
Contributor

Broad Khaki Wasp

Medium

Incorrect rounding in the ReputationMarket._calcCost() function.

Summary

When buying and selling, the cost is calculated using rounding based on isPositive. However, the rounding should be based on isBuy, not isPositive.

Root Cause

The _calcCost() function calculates cost by rounding based on isPositive.

If isPositive is false (indicating that DISTRUST votes are being traded), the calculation is rounded up.

Consider the following scenario:

  1. A user buys 2 DISTRUST votes.
  2. The user sells a DISTRUST vote.
  3. The user sells another DISTRUST vote.

During the buying process, rounding up occurs once, but when selling, rounding up occurs twice—at steps 2 and 3. As a result, marketFunds will be decremented by a dust amount.

If marketFunds was originally 0 (with the market created by the admin at a 0 creation cost), then step 3 becomes impossible.

In fact, isPositive is never related to the rounding direction.

      function _calcCost(
        Market memory market,
        bool isPositive,
        bool isBuy,
        uint256 amount
      ) private pure returns (uint256 cost) {
        ...

        int256 costRatio = LMSR.getCost(
          market.votes[TRUST],
          market.votes[DISTRUST],
          voteDelta[0],
          voteDelta[1],
          market.liquidityParameter
        );

        uint256 positiveCostRatio = costRatio > 0 ? uint256(costRatio) : uint256(costRatio * -1);
        // multiply cost ratio by base price to get cost; divide by 1e18 to apply ratio
        cost = positiveCostRatio.mulDiv(
          market.basePrice,
          1e18,
1057      isPositive ? Math.Rounding.Floor : Math.Rounding.Ceil
        );
      }

Internal pre-conditions

External pre-conditions

Attack Path

Impact

The last vote might not be sold.

PoC

Mitigation

Use !isBuy instead of isPositive.

        cost = positiveCostRatio.mulDiv(
          market.basePrice,
          1e18,
-         isPositive ? Math.Rounding.Floor : Math.Rounding.Ceil
+         !isBuy ? Math.Rounding.Floor : Math.Rounding.Ceil
        );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant