The joinGameWithEth()
function in the RockPaperScissors contract receives ETH from Player B but doesn't explicitly track this ETH in the contract's state variables. This creates an accounting discrepancy and potential for fund loss, especially in game cancellation or refund scenarios.
In the joinGameWithEth()
function (lines 155-165), Player B sends ETH to match the bet amount set by Player A:
The function is correctly marked as payable
and checks that the sent amount matches the required bet. However, it doesn't update any state variable to track that this ETH has been received. The ETH is implicitly stored in the contract's balance, but there's no accounting for it in the game's state.
This contrasts with the token-based game creation and joining, where tokens are explicitly transferred to the contract with transferFrom()
:
This lack of explicit ETH accounting can lead to several issues:
Accounting Discrepancy: The contract's ETH balance might not match the sum of all game bets, making it difficult to audit and verify the contract's financial state.
Potential Fund Loss: If a game is canceled or ends in a draw, there's no clear record of how much ETH should be returned to Player B. This could lead to incorrect refund amounts or even complete loss of funds.
Reentrancy Vulnerability Enhancement: Since the ETH tracking isn't explicit, it could complicate reentrancy protection and make it harder to implement secure fund management.
Contract Insolvency Risk: Over time, if the contract fails to properly account for all ETH received, it could become insolvent and unable to pay out winnings or refunds.
Manual code review
Static analysis of the contract's ETH handling
Logical analysis of game flow and fund management
Update the joinGameWithEth()
function to explicitly track the received ETH:
Add a totalBet
field to the Game
struct to track the total ETH held for each game:
Update all functions that handle ETH (like _finishGame()
and _cancelGame()
) to use this explicit accounting:
Consider implementing a pull-over-push pattern for ETH withdrawals to further enhance security and avoid potential reentrancy issues.
These changes would ensure proper accounting of ETH throughout the contract, reducing the risk of fund loss and improving the contract's financial transparency.
ETH sent directly to the contract via the receive function or after a canceled game becomes permanently locked
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.