TwentyOne

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

`dealersHand` Function Does Not Handle Correct Value for the King Card

Summary

In blackjack each card holds a numerical value for the points it represents:

  • Ace => could be 1 or 11 (I was assuming that in this case it is always 1)

  • 2-9 => Their face value is the same

  • 10, Jack, Queen & King => 10.

The protocol handles these calculations by module of 13 (the 13 cards). It then checks to see which card it is Ace, King and everything in between.

Vulnerability Details

https://github.com/Cyfrin/2024-11-TwentyOne/blob/a4429168302722d14a5e5996d25d6fc5be22a899/src/TwentyOne.sol#L47

The vulnerability lies with the dealersHand function. Unlike the playersHand function, it does not check for the cardValue to be 0 (which would be the case for a King card as it is the 13th, 26th, 39th, 52nd card - all multiplications of 13).

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

Consider these following scenarios:

  • Dealer has a 2 and a 13 (2 and king). Calculations will give a total of 15.

  • Dealer has a 2 and a 26 (2 and king). Calculations will give a total of 28.

  • Dealer has a 2 and a 39 (2 and king). Calculations will give a total of 41.

  • Dealer has a 2 and a 52 (2 and king). Calculations will give a total of 54.

In the first scenario the result is a bad one to try and win the match. However, in all of the other ones it is a sure loss! Guaranteeing a win for the player almost every time the dealer has been dealt a king.

Tools Used

Manual Analysis

Recommendations

As the playershand function add the following code to the first if statement:

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) {
+ if (cardValue == 0 || cardValue >= 10) {
dealerTotal += 10;
} else {
dealerTotal += cardValue;
}
}
}
Updates

Lead Judging Commences

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

Asymmetric calculation of hands is rigged in the player`s favor.

Support

FAQs

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