Skip to content

Latest commit

 

History

History
56 lines (42 loc) · 2.81 KB

File metadata and controls

56 lines (42 loc) · 2.81 KB

Recumbent Shamrock Barracuda

High

Fee calculation vulnerability will overcharge users during vote purchases

Summary

The _calculateBuy function calculates fees (protocolFee and donation) using msg.value instead of the actual funds utilized for the purchase (fundsPaid). This results in users being overcharged if msg.value exceeds the amount needed to purchase the intended vote, and users who provide more ETH than needed to make the purchase lose more. https://github.com/sherlock-audit/2024-11-ethos-network-ii/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L942-L960

Root Cause

The root cause lies in the misalignment between the fee calculation basis and the actual funds used:

  • Fee Basis Mismatch: Fees are derived from msg.value (total ETH sent) rather than fundsPaid (ETH actually spent for votes).
  • Implementation Error: The call to previewFees uses funds (mapped to msg.value) without adjusting for the actual paid funds.

Impact

  • Overpayment: Users providing excess ETH are charged disproportionately high fees, leading to financial inefficiency and user dissatisfaction.

Proof of Concept (PoC)

  1. Setup

    • Assume UserA with msg.value = 10 ETH, UserB with msg.value = 9 ETH
    • Number of votes to buy = 5 votes.
    • fundsPaid required for 5 votes = 8 ETH.(Assume that the number of votes that UserA and UserB can buy with the funds they pays is at most 5. In other words, since buying 6 votes requires 11 ETH, users can only buy 5 votes.)
    • Fee rate = 10%.
  2. Execution

    • Fees are calculated on msg.value: UserA: protocolFee = 1 ETH UserB: protocolFee = 0.9 ETH
    • Actual funds used (fundsPaid) for votes: fundsPaid = 8 ETH (UserA and UserB are the same.)
    • Total paid: UserA: totalPaid = 9 ETH, overPaid = 9 - 8 - 8 * 0.1 = 0.2 ETH UserB: totalPaid = 8.9 ETH, overPaid = 8.9 - 8 - 8 * 0.1 = 0.1 ETH
  3. Observed Behavior

    • UserA and UserB spent more than necessary.
    • UserA and UserB bought the same number of votes, but UserA paid more than UserB.

Mitigation

To address the identified issue in _calculateBuy, the fee calculation logic should be corrected to ensure that fees are proportional to the actual funds spent on purchasing votes. Here’s the step-by-step mitigation strategy: (The same as the calcFee function of EthosVouch contract.)

  1. Update calculation logic of fundsAvailable:
    fundsAvailable = funds * BASIS_POINTS_BASE / (BASIS_POINTS_BASE + entryProtocolFeeBasisPoints + donationBasisPoints)
  2. After the loop, calculate the final protocolFee and donation for the total fundsPaid:
    (protocolFee, donation) = previewFees(fundsPaid, true);
    fundsPaid += protocolFee + donation;