The joinGameWithEth
function allows a user to join a game by sending ETH. It does not validate if the game has already been joined by another player. This allows multiple participants to call the function within the same block, thus overwriting the previous value of playerB
.
The joinGameWithEth
function is vulnerable to front-running attacks. This is because it allows any address to join a game by matching the creator’s bet amount.
The function relies only on msg.sender
and msg.value
to validate joining.
It has no check to verify if game.playerB
is empty before it sets it. Multiple users can call joinGameWithEth
, and the last one process can simply overwrite playerB
Attack Scenario
Lets see an example;
Lets say John attempts to join a game by calling joinGameWithEth()
.
Peter monitors the mempool and sees John transaction.
Peter front-runs John by submitting the same function call with a higher gas price.
Peter transaction executes first, making him playerB
.
John’s transaction fails
Legitimate users may be unable to join games.
Users can lose ETH due to failed transactions.
Incorrect assignment of playerB which may lead to unexpected game outcome.
Manual Review
Consider implementing a Commit-Reveal Scheme. It can be used to prevent front-running by hiding user intentions until after a transaction is securely recorded on-chain.
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.