TwentyOne

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

Unsafe ERC20 Operations

Summary

The contract uses .transfer() which has a fixed gas limit of 2300, making it vulnerable to failure when sending ETH to contracts with complex receive functions.

Vulnerability Details

function test_UnsafeTransferOperation() public {
// Setup with gas-heavy receiver
GasHeavyReceiver gasHeavy = new GasHeavyReceiver();
vm.deal(address(twentyOne), 10 ether);
vm.deal(address(gasHeavy), 2 ether);
vm.startPrank(address(gasHeavy));
twentyOne.startGame{value: 1 ether}();
// Force winning condition
vm.mockCall(
address(twentyOne),
abi.encodeWithSignature("dealersHand(address)", address(gasHeavy)),
abi.encode(22)
);
// Should revert due to transfer() gas limit
vm.expectRevert();
twentyOne.call();
vm.stopPrank();
}
contract GasHeavyReceiver {
uint256[] data;
receive() external payable {
for(uint i = 0; i < 100; i++) {
data.push(i);
}
}
}

Impact

  • Payouts to contract winners can fail

  • Game rewards might be permanently locked

  • Poor user experience for smart contract players

Tools Used

  • Manual code review

  • Forge testing framework

  • Gas analysis

Recommendations

Replace .transfer() with .call():

(bool success, ) = payable(player).call{value: amount}("");
require(success, "Transfer failed");

Follow checks-effects-interactions pattern and implement reentrancy guards.

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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