Skip to content

Latest commit

 

History

History
60 lines (36 loc) · 1.81 KB

File metadata and controls

60 lines (36 loc) · 1.81 KB

Cheesy Cinnabar Mammoth

Medium

Vote sellers underpaid for votes

Summary

When a vote seller sells their votes, the amount the seller receives is calculated in _calculateSell by calling calcVotePrice. The problem is that calcVotePrice is called after market.votes[] is updated, returning a price that's lower than what the user should actually receive for that vote.

Root Cause

market.vote[] is updated before _calcVotePrice() is called.

https://github.com/sherlock-audit/2024-11-ethos-network-ii/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L1036-L1038

Internal pre-conditions

  1. A vote holder needs to call sellVotes() to sell their votes

External pre-conditions

n/a

Attack Path

  1. Say there are 100 TRUST votes and 100 DISTRUST votes in a market
  2. A vote seller wants to sell 1 TRUST vote
  3. The price the vote seller receives for the vote should be the vote price (100 * basePrice / 200) minus the protocol fee
  4. But instead, the vote seller will receive their vote for (99 * basePrice / 199) minus the protocol fee because markets.vote[] is updated before the vote price is calculated instead of after.

Impact

Loss of funds for vote sellers because they never receive the full price per vote that they should actually receive.

PoC

No response

Mitigation

Update the code in the while loop in _calculateSell to:

while (votesSold < amount) {
      if (market.votes[isPositive ? TRUST : DISTRUST] <= 1) {
        revert InsufficientVotesToSell(profileId);
      }

-      market.votes[isPositive ? TRUST : DISTRUST] -= 1;
-      votePrice = _calcVotePrice(market, isPositive);

+      votePrice = _calcVotePrice(market, isPositive);
+      market.votes[isPositive ? TRUST : DISTRUST] -= 1;

      fundsReceived += votePrice;
      votesSold++;
    }