Summary
In classic blackjack a ace has a value of either 1 or 11 depending on what is most advantagous for the player or dealer. The TwentyOne
contract handles aces as having only the value of 1.
Vulnerability Details
Not handling aces as 1 or 11 according to regular blackjack rules leads to unintended gameplay by the player.
Impact
A player may loose the game when thinking the hand is a winner.
Tools Used
Manual code review
Recommendations
Identify aces in the hand.
Initially count aces as 11.
Check if hand is bust.
If hand is busted subtract 10 from hand.
Adjust playerHand
function to handle aces correctly:
function playersHand(address player) public view returns (uint256) {
uint256 playerTotal = 0;
+ uint256 acesCount = 0;
for (uint256 i = 0; i < playersDeck[player].playersCards.length; i++) {
uint256 cardValue = playersDeck[player].playersCards[i] % 13;
+ if (cardValue == 1) {
+ playerTotal += 11;
+ acesCount += 1;
+ } else if (cardValue >= 10 || cardValue == 0) {
- if (cardValue == 0 || cardValue >= 10) {
playerTotal += 10;
} else {
playerTotal += cardValue;
}
}
// Adjust for aces if total is over 21
+ while (playerTotal > 21 && acesCount > 0) {
+ playerTotal -= 10; // Change an ace from 11 to 1
+ acesCount -= 1;
+ }
return playerTotal;
}
Adjust dealerHand
function to handle aces correctly:
function dealersHand(address player) public view returns (uint256) {
uint256 dealerTotal = 0;
+ uint256 acesCount = 0;
for (uint256 i = 0; i < dealersDeck[player].dealersCards.length; i++) {
uint256 cardValue = dealersDeck[player].dealersCards[i] % 13;
+ if (cardValue == 0) {
+ dealerTotal += 11;
+ acesCount += 1;
+ } else if (cardValue >= 10 || cardValue == 0) {
- if (cardValue >= 10) {
dealerTotal += 10;
} else {
dealerTotal += cardValue;
}
}
// Adjust for aces if total is over 21
+ while (dealerTotal > 21 && acesCount > 0) {
+ dealerTotal -= 10; // Change an ace from 11 to 1
+ acesCount -= 1;
+ }
return dealerTotal;
}