TwentyOne

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

Casino Controls the Deck

Summary

The current implementation doesn't correctly account for the dual value of Aces (1 or 11) in Twenty-One.

Vulnerability Details

An Ace can be counted as either 1 or 11, whichever is more beneficial to the hand without causing it to exceed 21 (a bust). The existing playersHand and dealersHand functions treat an Ace (represented by a card value of 0 or values >= 10 after the modulo operation) as always having a value of 10. This is incorrect.

Impact

This flaw leads to inaccurate hand totals. Here are some specific scenarios:

  1. False Busts: A player might have a hand like Ace + 6, which should be 17. The current code would calculate it as 16, potentially leading the player to hit and bust unnecessarily.

  2. Incorrect Dealer Wins: The dealer might have a hand like Ace + 8, which should be 19. The current code would calculate it as 18. If the player has 19, the game would be incorrectly declared a draw or a player loss, depending on how ties are handled.

  3. Misleading Player Decisions: Because the player's hand total is inaccurate, they'll make decisions (hit or stand) based on incorrect information, leading to suboptimal play.

Tools Used

Foundry and Manual reading

Recommendation For Mitigation

The hand calculation logic must be modified to handle Aces correctly. Here's a refined approach:

function playersHand(address player) public view returns (uint256) {
uint256 playerTotal = 0;
uint256 numAces = 0; // Track the number of Aces
for (uint256 i = 0; i < playersDeck[player].playersCards.length; i++) {
uint256 cardValue = playersDeck[player].playersCards[i] % 13;
if (cardValue == 0) { // Ace
numAces++;
playerTotal += 11; // Initially count Ace as 11
} else if (cardValue >= 10) { // Face cards and 10
playerTotal += 10;
} else { // Number cards
playerTotal += cardValue;
}
}
// Reduce Ace value from 11 to 1 if needed, one Ace at a time
while (playerTotal > 21 && numAces > 0) {
playerTotal -= 10;
numAces--;
}
return playerTotal;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Wrong ace value

Support

FAQs

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