The RockPaperScissors::cancelGame()
internal function is vulnerable to a reentrancy attack due to the use of low-level .call{value: ...}("")
to refund ETH before updating all critical state or applying reentrancy protections.
The following lines in the code are vulnerable:
The contract sends ETH to both players using low-level call
before completing the full game termination flow.
This gives a malicious player/contract (attacker) a chance to re-enter the same function again and again get a refund for the ETH bet.
Malicious players could exploit reentrancy to re-enter _cancelGame()
multiple times and thus corrupt game state, claim extra tokens or ETH, or manipulate game logic.
Manual review
Paste the following contract code in your RockPaperScissos.t.sol
file:
Now add the following in your test cases:
This will pass and thus verify the reentrancy issue.
Apply the checks-effects-interactions pattern:
Update all game state before making external calls.
Or use OpenZeppelin's ReentrancyGuard
and mark all external-entry points as nonReentrant
.
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.