TwentyOne

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

transfer() Method in endGame Function Fails with Smart Contract Wallets

Summary

The endGame function in the smart contract uses the transfer() method to distribute prizes to players. However, this implementation introduces a critical bug when interacting with modern smart contract wallets (e.g., Gnosis Safe). The transfer() method imposes a hard gas limit of 2300 gas, which is insufficient for most smart wallets to process incoming Ether. Consequently, transactions to such wallets revert, preventing prize distribution and potentially locking funds in the contract.

Vulnerability Details

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

function endGame(address player, bool playerWon) internal {
delete playersDeck[player].playersCards; // Clear the player's cards
delete dealersDeck[player].dealersCards; // Clear the dealer's cards
delete availableCards[player]; // Reset the deck
if (playerWon) {
payable(player).transfer(2 ether); < @audit
emit FeeWithdrawn(player, 2 ether); // Emit the prize withdrawal event
}
}

Impact

Funds will be locked in contract if player is a smart wallet or contract that requires more than 2300 gas to receive ether

Tools Used

Manual Review

Recommendations

Replace transfer() with the recommended call() pattern:

function endGame(address player, bool playerWon) internal {
// Clear player-specific game state
delete playersDeck[player].playersCards;
delete dealersDeck[player].dealersCards;
delete availableCards[player];
// Handle reward if the player won
if (playerWon) {
uint256 prizeAmount = 2 ether; // Define prize amount
require(address(this).balance >= prizeAmount, "Insufficient contract balance");
// Use `call` to transfer funds
(bool success, ) = player.call{value: prizeAmount}("");
require(success, "Transfer failed");
emit FeeWithdrawn(player, prizeAmount); // Emit event
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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