TwentyOne

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

[H-01] Incorrect Ace Card Value Implementation in TwentyOne Contract

Summary

The TwentyOne contract incorrectly implements the value calculation for Ace cards in Blackjack. In standard Blackjack rules, an Ace can count as either 1 or 11, with the value being chosen to benefit the player. However, the current implementation always treats Aces as 1, which significantly disadvantages players and breaks core game mechanics.

Vulnerability Details

Location: src/TwentyOne.sol

https://github.com/Cyfrin/2024-11-TwentyOne/blob/main/src/TwentyOne.sol#L29
https://github.com/Cyfrin/2024-11-TwentyOne/blob/main/src/TwentyOne.sol#L43

The vulnerability exists in both the playersHand() and dealersHand() functions where card values are calculated. The current implementation treats Aces (cardValue == 1) the same as any other number card, assigning it a value of 1 instead of implementing the flexible 1/11 rule.

// In playersHand()
if (cardValue == 0 || cardValue >= 10) {
playerTotal += 10;
} else {
playerTotal += cardValue; // Ace is treated as 1
}
// In dealersHand()
if (cardValue >= 10) {
dealerTotal += 10;
} else {
dealerTotal += cardValue; // Ace is treated as 1
}

Proof of Concept:

function testAceAndKingNotTwentyOne() public {
// Start game as player
vm.startPrank(player);
vm.deal(player, 2 ether);
game.startGame{value: 1 ether}();
// Force specific cards: Ace and King
vm.store(
address(game),
keccak256(abi.encode(player, uint256(0))),
bytes32(uint256(2))
);
bytes32 slot = keccak256(abi.encode(
keccak256(abi.encode(player, uint256(0)))
));
vm.store(address(game), bytes32(uint256(slot)), bytes32(uint256(1))); // Ace
vm.store(address(game), bytes32(uint256(slot) + 1), bytes32(uint256(13))); // King
uint256 total = game.playersHand(player);
// Test proves that Ace + King = 11 instead of the correct value of 21
assertEq(total, 11, "Ace + King should be calculated as 21 (11 + 10) but is calculated as 11 (1 + 10)");
}

Impact

The incorrect implementation of Ace card values has several significant impacts:

  1. Game Mechanics Breaking

    • Players cannot achieve Blackjack (21) with an Ace + 10-value card combination

    • Natural Blackjack hands are impossible, removing a key game feature

    • Players are forced to treat Aces as only 1, significantly reducing strategic options

    • This implementation does not follow standard Blackjack rules

  2. Economic Impact

    • Players have reduced winning chances due to suboptimal hand values

    • Potential loss of player funds due to hands being incorrectly valued

    • House advantage is artificially increased beyond intended game design

  3. Trust and Fairness

    • Breaks standard Blackjack rules that players expect

    • May lead to player dissatisfaction and loss of trust

    • Could be perceived as intentionally unfair game mechanics

Tools Used

  • Foundry Testing Framework

  • Manual Code Review

  • Custom test cases for Ace card scenarios

Recommendations

  1. Implement Flexible Ace Value Calculation:

function calculateHandValue(uint256[] memory cards) internal pure returns (uint256) {
uint256 total = 0;
uint256 aces = 0;
// First pass: count aces and add other cards
for (uint256 i = 0; i < cards.length; i++) {
uint256 cardValue = cards[i] % 13;
if (cardValue == 1) {
aces++;
} else if (cardValue == 0 || cardValue >= 10) {
total += 10;
} else {
total += cardValue;
}
}
// Second pass: add aces optimally
for (uint256 i = 0; i < aces; i++) {
if (total + 11 <= 21) {
total += 11;
} else {
total += 1;
}
}
return total;
}
  1. Update Existing Functions:

    • Modify both playersHand() and dealersHand() to use the new calculation method

    • Ensure consistent Ace handling across all game functions

  2. Add Comprehensive Testing:

    • Test Ace + face card combinations

    • Test multiple Ace scenarios

    • Test edge cases with Aces and various hand totals

    • Verify correct Blackjack detection

  3. Documentation Updates:

    • Add clear documentation about Ace card handling

    • Include examples of various Ace value scenarios

    • Document the expected behavior for multiple Aces

Updates

Lead Judging Commences

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

Wrong ace value

Natural Blackjack not implemented

Naturals. If a player's first two cards are an ace and a "ten-card" (a picture card or 10), giving a count of 21 in two cards, this is a natural or "blackjack." If any player has a natural and the dealer does not, the dealer immediately pays that player one and a half times the amount of their bet.

Appeal created

iepathos Submitter
11 months ago
inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Wrong ace value

Natural Blackjack not implemented

Naturals. If a player's first two cards are an ace and a "ten-card" (a picture card or 10), giving a count of 21 in two cards, this is a natural or "blackjack." If any player has a natural and the dealer does not, the dealer immediately pays that player one and a half times the amount of their bet.

Support

FAQs

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