TwentyOne

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

First Winner Cannot Receive Prize Due to Insufficient Contract Balance

Summary

The contract does not include a mechanism to fund the prize pool upon deployment, nor does it validate whether sufficient funds are available to pay the winner. If the first player to win the game does so when the contract balance is insufficient, the prize transfer will revert, leaving the player without their winnings. Additionally, since the withdrawal is implemented using a push-based method, the player will not be able to withdraw their winnings later, even if the contract balance becomes sufficient.

Vulnerability Details

Root Cause:

  • The contract lacks an initial deposit or funding mechanism to establish a prize pool at deployment.

  • The endGame function attempts to pay winnings using the transfer method without checking if sufficient funds are available in the contract:

    if (playerWon) {
    payable(player).transfer(2 ether);
    emit FeeWithdrawn(player, 2 ether);
    }
  • Symptoms:

    • If the first player to win does so when the contract balance is less than 2 ETH:

      • The transfer call reverts, and the player receives no winnings.

      • The player’s wager of 1 ETH may also be lost or unrefunded.

    • Since the transfer is a push-based method, the player cannot retry withdrawing their winnings, even if the contract is funded later.

  • Code Affected:

    • endGame Function:

      if (playerWon) {
      payable(player).transfer(2 ether);
      emit FeeWithdrawn(player, 2 ether);
      }
  • Behavior Details:

    • Players rely on the contract’s immediate balance for payouts. If the contract lacks funds at the moment of execution, the winnings are permanently lost.

    • There is no fallback mechanism to handle insufficient funds or to retry failed payouts.

Impact

First Winner’s Financial Loss:

  • The first player to win may not receive their prize due to insufficient funds in the contract, resulting in financial loss and dissatisfaction.

  • Loss of Trust and Game Integrity:

    • Players lose trust in the game if winnings are not reliably paid out. The lack of initial funding damages the protocol’s credibility.

  • Operational Limitation of Push Method:

    • Push-based withdrawals prevent retrying payouts if funds are unavailable at the time of execution.

Tools Used

Manual code review.

Recommendations

Require Initial Funding During Deployment:

  • Modify the contract constructor to enforce a minimum initial funding requirement at deployment. This ensures the prize pool is pre-funded before players participate.
    Example:

constructor() payable {
require(msg.value >= 10 ether, "Initial funding of 10 ETH required");
}
  • The owner deploying the contract must send the initial funding amount as part of the deployment transaction.

  • Add a Deposit Function for Prize Pool Funding:

    • Provide the contract owner with the ability to deposit additional funds into the prize pool dynamically to ensure ongoing liquidity.
      Example:

    function depositPrizePool() public payable onlyOwner {
    require(msg.value > 0, "Must send Ether to fund the prize pool");
    }
    • This function allows the contract to be topped up as needed, ensuring prizes can always be paid out.

  • Combine Both Approaches:

    • Implement both initial funding and the ability to deposit additional funds to provide flexibility and maintain a sustainable prize pool:

      • Require sufficient funding at deployment.

      • Allow dynamic refills during the contract’s lifetime.

  • Document Funding Responsibilities:

    • Include clear instructions in the project documentation that:

      • Initial funding is required during deployment.

      • The contract owner must ensure the prize pool remains funded to avoid payout failures.

Updates

Lead Judging Commences

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

Contract Lacks Mechanism to Initialize or Deposit Ether

Support

FAQs

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