The RockPaperScissors smart contract includes a receive() function that allows it to accept ETH directly, but it lacks any mechanism to extract these funds if they are accidentally sent to the contract outside of the intended game mechanisms. This creates a risk of permanently trapped ETH that cannot be recovered by either players or the contract administrator.
The issue is present in the receive() function (lines 582-585):
This function allows the contract to accept ETH transfers, but there is no corresponding functionality in the contract to withdraw or utilize these funds if they are sent outside of the normal game creation or joining process. While the contract includes a withdrawFees function for the admin to withdraw accumulated protocol fees, it specifically only allows withdrawal from the accumulatedFees balance, not from the contract's entire ETH balance.
The absence of a rescue mechanism means any ETH sent directly to the contract address (whether accidentally or intentionally) will be permanently locked within the contract with no way to recover it.
Permanent Fund Loss: Any ETH directly sent to the contract by mistake becomes permanently trapped.
No Recovery Mechanism: Neither players nor the admin can recover these trapped funds.
Accumulated Loss Over Time: Small amounts of accidentally sent ETH could accumulate over time into a significant amount.
Manual code review
Implement an admin function to withdraw any excess ETH that is not part of active games or accumulated fees:
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.