The Rock Paper Scissors contract includes a receive()
function that allows it to accept ETH directly, but provides no mechanism to withdraw this ETH. This creates a permanent ETH lock situation where funds sent directly to the contract become irretrievable.
The contract includes a receive()
function that accepts ETH without any restrictions:
However, the only ETH withdrawal mechanism in the contract is the withdrawFees()
function, which only allows the admin to withdraw from the accumulatedFees
variable:
The problem is that ETH sent through the receive()
function:
Is added to the contract's general balance
Is not tracked in the accumulatedFees
variable
Cannot be withdrawn through the withdrawFees()
function
Has no other withdrawal mechanism
This vulnerability has medium impact because:
Any ETH sent directly to the contract (not through game functions) is permanently locked
Users or admins who accidentally send ETH to the contract address will lose those funds
There is no recovery mechanism for these locked funds
This issue is compounded because having a receive()
function explicitly signals that the contract is designed to accept ETH, yet that ETH becomes trapped.
Manual code review
There are two possible approaches to fix this vulnerability:
Option 1: Remove the receive function
This prevents ETH from being sent directly to the contract, making the contract behavior clearer.
Option 2: Add a withdrawal mechanism for all contract balance
Either approach would prevent ETH from being permanently locked in the contract.
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.