Rock Paper Scissors

First Flight #38
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: low
Valid

[H-01] ETH Rounding Error in RockPaperScissors::_handleTie()

Summary

The _handleTie() function contains an integer division rounding error that causes permanent loss of ETH during tie resolution. This occurs when refunding players after deducting protocol fees from the total pot.

Vulnerability Details

Location: _handleTie() function in RockPaperScissors.sol
Vulnerable Code:

uint256 fee = (totalPot * PROTOCOL_FEE_PERCENT) / 100;
uint256 refundPerPlayer = (totalPot - fee) / 2; // Problematic division

PoC Scenario

1) Game Setup:

  • Patrick bets: 52.5 ETH

  • Dacian bets: 52.5 ETH

  • Total pot: 105 ETH

2) Tie Resolution

uint256 fee = (105 ether * 10) / 100; // 10.5 ETH
uint256 remaining = 105 ether - 10.5 ether; // 94.5 ETH
uint256 refundPerPlayer = remaining / 2; // 47.25 ETH → truncates to 47 ETH

3) Result:

  • Patrick receives: 47 ETH

  • Dacian receives: 47 ETH

  • Contract retains: 0.5 ETH (94 ETH distributed from 94.5 ETH remaining)

Impact

  • Progressive ETH accumulation in contract (0.5 ETH lost per tie at these stakes)

  • Direct financial loss to players (violates exact refund principle)

Tools Used

  • Manual Calculation Review

Recommendations

- uint256 fee = (totalPot * PROTOCOL_FEE_PERCENT) / 100;
- uint256 refundPerPlayer = (totalPot - fee) / 2;
// Fix: Precise percentage math
+ uint256 refundPerPlayer = (totalPot * (100 - PROTOCOL_FEE_PERCENT)) / 200;

or use Fixed-Point Arithmetic such as mulDiv

Updates

Appeal created

m3dython Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Rounding Error

The tie-handling logic loses one wei due to integer division

m3dython Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Rounding Error

The tie-handling logic loses one wei due to integer division

Support

FAQs

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