TwentyOne

First Flight #29
Beginner FriendlyGameFiFoundrySolidity
100 EXP
View results
Submission Details
Severity: low
Invalid

Player Can lost ETH if start the game with more than 1 eth as Value `TwentyOne::startGame()`

Description:
Although the game logic specifies that a player can only start with exactly 1 ETH and win double that amount if victorious, the contract currently allows players to send more than 1 ETH when calling startGame(). Any excess ETH sent is not accounted for or refunded, resulting in the player losing the additional funds, even if they win.

function startGame() public payable returns (uint256) {
_;
@> require(msg.value >= 1 ether, "not enough ether sent");
_;
}

Impact:

  1. Players who inadvertently send more than 1 ETH will lose the excess amount, leading to financial losses.

  2. This could harm the contract's reputation, reducing player trust and deterring users from engaging with the game.

  3. ewer players might participate, negatively affecting the adoption and success of the game.

Proof of Concept:

  1. Add this POC to TwentyOne.t.sol

function test_Call_PlayerWins() public {
vm.startPrank(player1); // Start acting as player1
twentyOne.startGame{value: 5 ether}();
// Mock the dealer's behavior to ensure player wins
// Simulate dealer cards by manipulating state
vm.mockCall(
address(twentyOne),
abi.encodeWithSignature("dealersHand(address)", player1),
abi.encode(18) // Dealer's hand total is 18
);
uint256 initialPlayerBalance = player1.balance;
// Player calls to compare hands
twentyOne.call();
// Check if the player's balance increased (prize payout)
uint256 finalPlayerBalance = player1.balance;
assertGt(finalPlayerBalance, initialPlayerBalance);
console.log(finalPlayerBalance, initialPlayerBalance);
vm.stopPrank();
}
  1. Run the command :

Forge test
  1. Notice the player entered with 5 ETH and although he win he get only 2 ETH as balance and instead it should be 6.

Recommended Mitigation:

  1. Restrict the game start to exactly 1 ETH and reject transactions with any other amount.

require(msg.value == 1 ether, "You must send exactly 1 ETH to start the game");
  1. Alternatively, refund any excess ETH to the sender:

uint256 excess = msg.value - 1 ether;
if (excess > 0) {
payable(msg.sender).transfer(excess);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[INVALID] User mistake, too much ETH sent

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.