Skip to content

Latest commit

 

History

History
82 lines (58 loc) · 2.86 KB

File metadata and controls

82 lines (58 loc) · 2.86 KB

Fluffy Charcoal Toad

High

Insufficient Slippage Protection in Vote Purchases

Summary

Missing slippage validation on final vote count will cause financial losses for users as attackers can front-run large trades to force unfavorable execution prices. buyVotes decreases votes until they fit within msg.value without checking minVotesToBuy.

Root Cause

In ReputationMarket.sol:buyVotes there is a missing validation check between the final number of votes purchased and the user's specified minimum:

https://github.com/sherlock-audit/2024-12-ethos-update/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L440

// if the cost is greater than the maximum votes to buy,
    // decrement vote count and recalculate until we identify the max number of votes they can afford
    while (totalCostIncludingFees > msg.value) {
      currentVotesToBuy--;
      (purchaseCostBeforeFees, protocolFee, donation, totalCostIncludingFees) = _calculateBuy(
        markets[profileId],
        isPositive,
        currentVotesToBuy
      );

Internal Pre-conditions

  1. User needs to submit a buyVotes transaction with maxVotesToBuy significantly higher than minVotesToBuy
  2. Transaction needs to include sufficient ETH for minVotesToBuy at current prices
  3. Market needs to have enough liquidity to execute large trades

External Pre-conditions

  1. Network needs to have sufficient congestion to allow front-running

Attack Path

  1. Attacker monitors mempool for large buyVotes transactions
  2. When victim transaction detected with large maxVotesToBuy, attacker submits front-running trade with higher gas price
  3. Attacker's trade executes first, driving up market price
  4. Victim's transaction executes but receives fewer votes than minVotesToBuy due to price impact
  5. Attacker can then sell votes at higher price

Impact

Users suffer losses due to unfavorable trade execution, potentially receiving significantly fewer votes than their specified minimum.

PoC

function testSlippageExploit() public {
    // Setup market
    uint256 profileId = 1;
    market.createMarket{value: 1 ether}();
    
    // Victim transaction parameters
    uint256 maxVotes = 1000;
    uint256 minVotes = 800;
    uint256 victimETH = 10 ether;
    
    // Attacker front-runs
    vm.prank(attacker);
    market.buyVotes{value: 20 ether}(profileId, true, 2000);
    
    // Victim transaction executes
    vm.prank(victim);
    market.buyVotes{value: victimETH}(profileId, true, maxVotes, minVotes);
    
    // Check victim's received votes
    uint256 actualVotes = market.getUserVotes(victim, profileId).trustVotes;
    assertLt(actualVotes, minVotes); // Victim receives fewer votes than minimum
}

Mitigation

  1. Add slippage check before executing trade
  2. Add deadline parameter to prevent stale trades
  3. Implement price oracle with TWAP to reduce manipulation