TwentyOne

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

TwentyOne Analysis Report

TwentyOne Analysis Report

This report was generated by a manual review of the smart contract code. It highlights potential security vulnerabilities, optimizations, and other issues to improve the overall robustness of the code. This review is not a substitute for a formal security audit or extensive testing.

Table of Contents


Summary

Files Summary

Key Value
.sol Files 1
Total nSLOC 140

Issue Summary

Category No. of Issues
High 2
Medium 2
Low 5

High Issues

H-1: Predictable Randomness Vulnerability

Description

The contract uses block.timestamp, msg.sender, and block.prevrandao for randomness in the drawCard function. These values are predictable and manipulable by miners, leading to potential exploits.

Impact

An attacker or miner could manipulate the randomness to favor specific outcomes, undermining the fairness of the game.

Recommendation

Use a more secure source of randomness, such as Chainlink VRF, which is verifiable and tamper-proof.

  • Affected Code:

    uint256 randomIndex = uint256(
    keccak256(abi.encodePacked(block.timestamp, msg.sender, block.prevrandao))
    ) % availableCards[player].length;

H-2: Lack of Access Control for Withdrawals

Description

The endGame function pays out 2 ether if the player wins. There is no restriction preventing malicious actors from calling this function directly and exploiting the contract.

Impact

An attacker could exploit the contract to drain funds if they manipulate game conditions.

Recommendation

Implement stricter access control using modifiers to ensure that only valid game participants can trigger payouts.


Medium Issues

M-1: block.prevrandao Dependency

Description

The contract relies on block.prevrandao for randomness, which miners can influence to manipulate outcomes.

Impact

This dependency reduces the randomness quality, allowing miners to exploit the game logic.

Recommendation

Use an external randomness provider like Chainlink VRF instead of on-chain randomness.


M-2: Potential Reentrancy in endGame

Description

The endGame function performs an external Ether transfer (payable(player).transfer(2 ether)) before clearing the state.

Impact

This may expose the contract to reentrancy attacks, allowing malicious contracts to repeatedly call endGame and drain funds.

Recommendation

Perform state changes before external calls, or use the checks-effects-interactions pattern to mitigate reentrancy risks.

Affected Code:

payable(player).transfer(2 ether);

Low Issues

L-1: Solidity Pragma Version

Description

The contract uses pragma solidity ^0.8.13;. Using a wide version range increases the risk of unintended behavior due to compiler changes.

Recommendation

Specify a fixed compiler version for consistency and to avoid unintended bugs.

Affected Code:

pragma solidity ^0.8.13;

L-2: Inefficient State Reset in endGame

Description

The endGame function deletes mappings for players' cards and the deck. This process could be optimized.

Recommendation

Use delete playersDeck[player] and delete dealersDeck[player] instead of accessing individual arrays.

L-3: Missing external Modifier

Description

Several public functions, such as startGame, are never called internally. The external modifier could save gas.

Recommendation

Use the external modifier for functions that are not invoked within the contract.

Examples:

function startGame() public payable returns (uint256);

L-4: Lack of Indexed Fields in Events

Description

The events (PlayerLostTheGame, PlayerWonTheGame, etc.) do not include indexed fields, making it harder for off-chain tools to filter events.

Recommendation

Add indexed parameters to events, such as address indexed player.

L-5: Magic Numbers for Ether Values

Description

The contract hardcodes Ether values (e.g., 1 ether, 2 ether).

Recommendation

Define constants for these values for better readability and maintainability.

Example:

uint256 constant GAME_ENTRY_FEE = 1 ether;
uint256 constant WINNING_PRIZE = 2 ether;
Updates

Lead Judging Commences

inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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