Summary
The playersHand
and dealersHand
functions both incorrectly handle Aces, which are represented by cardValue == 0. Aces in Blackjack should be valued as either 1 or 11, depending on the current hand total. However, the current implementation fails to account for this flexibility, leading to incorrect hand totals.
Vulnerability Details
In the playersHand
function, Aces are incorrectly valued as 10, which does not reflect their potential value of 1 or 11.
function playersHand(address player) public view returns (uint256) {
uint256 playerTotal = 0;
for (uint256 i = 0; i < playersDeck[player].playersCards.length; i++) {
uint256 cardValue = playersDeck[player].playersCards[i] % 13;
if (cardValue == 0 || cardValue >= 10) {
playerTotal += 10;
} else {
playerTotal += cardValue;
}
}
return playerTotal;
}
In the dealersHand
function, Aces are effectively treated as 0, resulting in their value being lost in the calculation.
function dealersHand(address player) public view returns (uint256) {
uint256 dealerTotal = 0;
for (uint256 i = 0; i < dealersDeck[player].dealersCards.length; i++) {
uint256 cardValue = dealersDeck[player].dealersCards[i] % 13;
if (cardValue >= 10) {
dealerTotal += 10;
} else {
dealerTotal += cardValue;
}
}
return dealerTotal;
}
Impact
The incorrect handling of Ace values in both the players' and dealers' hands can potentially result in incorrect game outcomes and unfair payouts.
Tools Used
Manual review.
Recommended Mitigation
Implement logic in both playersHand
and dealersHand
functions to dynamically assign Aces a value of 1 or 11 based on the current hand total. This can be achieved by initially treating Aces as 11 and then adjusting the total if it exceeds 21 by converting to 1.
function calculateHand(uint256[] memory cards) internal pure returns (uint256) {
uint256 total = 0;
uint256 aceCount = 0;
for (uint256 i = 0; i < cards.length; i++) {
uint256 cardValue = cards[i] % 13;
if (cardValue == 0) {
total += 11;
aceCount++;
} else if (cardValue >= 10) {
total += 10;
} else {
total += cardValue;
}
}
while (total > 21 && aceCount > 0) {
total -= 10;
aceCount--;
}
return total;
}
function playersHand(address player) public view returns (uint256) {
return calculateHand(playersDeck[player].playersCards);
}
function dealersHand(address player) public view returns (uint256) {
return calculateHand(dealersDeck[player].dealersCards);
}